Im trying to run some tests in python. Im using Unittest framework.
The test "test_processJson" uses a test Json, dictTestString, and then checks if it has one or more elements. This is my script "testing.py"
import json
import starter#The code Im trying to test
import unittest
class MyTests(unittest.TestCase):
def test_processJson(json):
dictTestString = '{"city":"Barcelona"}'
jTest = json.loads(dictTestString)
dictProcess = starter.processJson(dictTest)
self.assertEquals(dictProcess["city"], "Barcelona")
if __name__ == '__main__':
unittest.main()
The problem comes when I run the test I get this error:
Traceback (most recent call last):
File "testing.py", line 16, in test_processJson
jTest = json.loads(dictTestString)
AttributeError: 'MyTests' object has no attribute 'loads'
I'm new to python, so I've been looking for an answer but any of the mistakes I've seen Im not doing.
Any help will be appreciated.
Thanks.
Your function's argument is named json, which shadow's the global json module. Actually since this is the first argument of a method, it get bound to the current MyTest instance, and since unittest test methods only expect the current instance as argument AND you don't have any need for a json argument here, you just have to rename it to self (which is the convention for the first argument of instance methods) and you problem will be solved.
NB : There are a couple other typos / issues with your code but I leave it up to you to find and solve them - that's part of the fun isn't it ?
Related
I'm having an issue when trying to write unit tests for a python3 script. The code is throwing a AttributeError while running inside a test definition, but does not if I run the same code in the same file outside of the test definitions class.
The code:
class TestDataCleaningMethods(unittest.TestCase):
def test_one(self):
data = pd.DataFrame(columns=[
'categoryId',
'regionId',
'districtId',
'jobType',
'contractType',
'payType'])
result = service.__columns_to_snake_case(data)
Throws the following error:
AttributeError: module 'service' has no attribute '_TestDataCleaningMethods__columns_to_snake_case'
I've had a search around, and found a few questions and answers regarding attribute errors on unittest, but haven't seen any that quite match this issue.
Another thing to note is that I've Monkey-patched import to return Mocks, but I can't see it interfering with the functioning of unittest. In the interest of completedness, this is that code:
orig_import = __import__
original_imports = [
"service",
"pandas"
]
def import_mock(name, *args):
if name in original_imports:
print(f"Using original imports for {name}")
return orig_import(name, *args)
print(f"Mocking {name}")
return mock.MagicMock()
with mock.patch('builtins.__import__', side_effect=import_mock):
import service
Any help is greatly appreciated
Solved it, turns out it is an issue with double underscores in function names. Double underscore makes the python interpreter to rename the attribute to prevent conflicts. Changing the function names to remove the double underscore fixes the issue.
Class intSet
I'm trying to understand the following code from the MIT python class. When i create an object of the class intSet as follows i run into some trouble with one of the attributes.
s=intSet()
and try
s.vals()
I get the following error
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
s.vals()
TypeError: 'list' object is not callable
why is this? I've been told i shouldn't try s.vals directly because of data hiding, when i try s.vals the correct list is returned but i get an error when trying s.vals(). Can someone explain this error? I'm new to both OOP and python so i apologise for my poor questioning. Any help is greatly appreciated.
vals is not a method it is an attribute so you can't call it. In python the parentheses indicate you are calling a method. So just do s.vals
When you use s.vals() it tries to call function 'vals' through variable 's' whereas, when you use s.vals it doesnt look for the function just returns the value stored in s.vals.
You are trying to call vals that is a list. You are doing something like this [](), that is not possible.
What you should do in OOP way is to declare getter function like that:
class intSet(object):
def __init__(self):
self.__vals = [] # kinda private class instance
# .... other code
#property
def vals(self):
return self.__vals
intset = intSet()
intset.vals # is that list
More info about private members in python and about properties
I am trying to create some tests for a Python program. I am using Python version 2.7.12 so I had to install mock using sudo pip install mock.
According to the documentation and several other sites, I should be able to use the following code to use patch:
import mock # Also could use from mock import patch
import unittest
class TestCases(unittest.TestCase):
#mock.patch('MyClass.ImportedClass') # If using from mock import patch should just be #patch
def test_patches(self, mock_ImportedClass):
# Test code...
However, the above code throws the following error:
AttributeError: 'module' object has no attribute 'patch'
After some experimenting in the terminal, it seems quite a few things don't work. For example
>>> import mock
>>> mock.MagicMock
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'MagicMock'
>>> mock.patch
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'patch'
>>> mock.Mock
<class mock.Mock at 0x7fdff56b0600>
Interestingly, I can access something called patch using mock.Mock(), but I don't know if this works in the same way and cannot find anything about it in the documentation.
My experience with Python is fairly limited so I'm not sure what might be wrong. I'm fairly certain the right package was installed. Any help on how I can get this working?
Just for the sake of completeness, I wanted to add the answer, but the credit goes to #user2357112.
If you run into this issue check to make sure you don't have another file named mock.py (or whatever file you're trying to import) either in the same directory or in the search path for python. To confirm you've loaded the correct file, you can check mock.__file_, which is an attribute added automatically by python to your imported files. If you're using the terminal, you can just do something like:
>>> import mock
>>> mock.__file__
'/usr/lib/python2.7/...'
If the file path doesn't match what you expect, you should remove the file being imported from your search path or modify your search path so that the file you want is found first. If neither of those are an option, you need to change the name of the file you're importing (if it's one you define and not a library like mock).
So I have a module that I successfully use. But now I added another file to module and it gives me this error.
I have a file generate_bags_uk that has method:
def generate_bags(bags, price):
And I use it like this:
from excelgenerator import generate_bags_uk
...
uk_bag = generate_bags_uk.generate_bags(tshirts, form.cleaned_data['price_uk_bag'])
And I get TypeError: module is not callable. What am I doing wrong here ?
Try the following code instead -
from excelgenerator.generate_bags_uk import generate_bags
...
uk_bag = generate_bags(tshirts, form.cleaned_data['price_uk_bag'])
and make sure excelgenerator folder has a __init__.py inside it, otherwise it will not be dealt as a python package.
Also, I guess the method has a body, if it does not then at least give it a definition -
def generate_bags(bags, price):
pass
COMMENT : From the looks of this error, the error is happening in file /home/marijus/workspace/tshirtnation/excelgenerator/generate_bags_uk.py. I think your other calls are also of similar format and thus causing error. Please change them as I mentioned. The problem should be solved.
I'm relatively new to Python and unit testing in Python. From the Java world I know the concept of mocking but it seem to be much different from what I can see in Python.
I found this guide, which I found very helpful: http://www.voidspace.org.uk/python/mock/index.html
But as I wrote my (a bit more complex) tests with mocked out dependencies I noticed a strage behavior.
I decided to create a reduced, simple example which also does not work as I expect it.
Take a look at this, the result and my expectation I have added as comments:
import unittest
from mock import patch, Mock, MagicMock
class BasicTest(unittest.TestCase):
#patch("StringIO.StringIO")
def testSomethingNotWorkingAsExpected(self, StringIOMock):
StringIOMock.assert_called_once() # asserts, but why?
#patch("StringIO.StringIO")
def testSomethingSomehowWorking(self, StringIOMock):
# self.instantiateStringIO() # intentionally commented out
assert StringIOMock.called # does not assert (leading to failure of this test); as expected. If the above line is not commented, this asserts as expected.
def instantiateStringIO(self):
import StringIO
StringIO.StringIO()
Why is assert_called_once() asserting the instantiation of StringIO even it has not been instantiated yet?
And why does assert ClassMock.called bring the expected results?
Using assert not ... to assert a method has not been called I found here: Assert a function/method was not called using Mock. I inverted this pattern in my case by omitting the not.
Somewhere I found the pattern ClassMock.return_value to reference an instance. But I understand this as a way to manupulate the instance of a Mock before it will be called, not as a way to access the instance that might an underliing code have internally created. Or am I wrong?
My environment:
Python 2.7.3
mock 0.8.8
Fedora 19
Probably my understanding of the mock/patch thing is wrong. Could please someone aditionally explain what a class mock does and how it works?
Edit1: Added output
... and added paraphrase in parens to comment in testSomethingSomehowWorking
This is the output:
.F
======================================================================
FAIL: testSomethingSomehowWorking (test_test.BasicTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/mock.py", line 1224, in patched
return func(*args, **keywargs)
File "test_test.py", line 15, in testSomethingSomehowWorking
assert StringIOMock.called # does not assert; as expected
AssertionError
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
The method assert_called_once does not exist and it does not perform an assertion. It's no different from writing StringIOMock.assert_foo_bar_does_not_exist() or any other method. The mock library doesn't check whether the method called on the mock actually exists.
If you use assert_called_once_with then it fails as expected.
You can use the spec parameter to raise an error when you call a non-existent method:
#patch("StringIO.StringIO", spec=StringIO.StringIO)
def testSomethingNotWorkingAsExpected(self, StringIOMock):
StringIOMock.assert_called_once() # will fail as the method doesn't exist