Skipping a test based on the pass of a previous test - django

I'm using the django test suite with nose and trying to figure out how I can run a followup test if a previous test fails. Is that possible?

Here is how I'd do it:
Have a global variable called test_condition_a = False shared among test cases.
Try/catch assert in test_a and catch the exception when it fails so that you can set test_condition_a = True before the test exits.
Use #unittest.skipIf(test_condition_a) on all other test cases that you want run only if test_a fails.
EDIT On second thought, the above is not going to work as the test order is random. Your best bet would be to do something like this
class Test(TestCase):
def setUp(self):
...
#unittest.skip("Skip by default")
def testB(self):
#test code
def testA(self):
try:
#test code
return True
except Error:
return False
def testA_then_B(self):
if (self.testA()):
self.testB()

Related

Pytest keep missing return line in the same function that has been ran multiple time

I'm doing a project in django and I have 2 serializer like this:
parent_serializer.py
class ParentSerializer(serializer.Serializers):
action = ChildSerializer()
child_serializer.py
class ChildSerializer(serializer.Serializers):
...
def validate(self, attrs):
...
**return attrs**
There is an if statement in the validate function and i wrote all the tests needed for the if statement, but pytest coverage keep saying that it missed the return statement line (return attrs), which imo, supposed to run in every test case.
I did try everything possible but nothing works. Please help me on that one
I found the solution.
So basically I have to cover else case in the validate function. I have a statement look like if action in: ... which actually never happened in real case, but coverage still call missing for it.

Django Model function behavior changes based on how many tests being run

I have a need for a uniqueID within my Django code. I wrote a simple model like this
class UniqueIDGenerator(models.Model):
nextID = models.PositiveIntegerField(blank=False)
#classmethod
def getNextID(self):
if(self.objects.filter(id=1).exists()):
idValue = self.objects.get(id=1).nextID
idValue += 1
self.objects.filter(id=1).update(nextID=idValue)
return idValue
tempObj = self(nextID=1)
tempObj.save()
return tempObj.nextID
Then I wrote a unit test like this:
class ModelWorking(TestCase):
def setUp(self):
return None
def test_IDGenerator(self):
returnValue = UniqueIDGenerator.getNextID()
self.assertEqual(returnValue, 1)
returnValue = UniqueIDGenerator.getNextID()
self.assertEqual(returnValue, 2)
return None
When I run this test by itself, it runs fine. No issues.
When I run this test as a suite, which includes a bunch of other unit tests as well (which include calls to getNextID() as well), this test fails. The getNextID() always returns 1. Why would that be happening?
I figured it out.
Django runs each test in a transaction to provide isolation. Doc link.
Since my other tests make a call to getNextID(), the first row gets deleted after the first test that makes such a call is complete. Subsequent tests never find (id=1), due to which all subsequent calls return the value 1.
Even though I don't think I would face that situation in production, I went I ahead and changed my code to use .first() instead of (id=1). Like this
def getNextID(self):
firstRow = self.objects.first()
if(firstRow):
That way I believe it would better handle any future scenario when the database table might be emptied.

Using mock to test if directory exists or not

I have been exploring mock and pytest for a few days now.
I have the following method:
def func():
if not os.path.isdir('/tmp/folder'):
os.makedirs('/tmp/folder')
In order to unit test it, I have decided to patch os.path.isdir and os.makedirs, as shown:
#patch('os.path.isdir')
#patch('os.makedirs')
def test_func(patch_makedirs, patch_isdir):
patch_isdir.return_value = False
assert patch_makedirs.called == True
The assertion fails, irrespective of the return value from patch_isdir. Can someone please help me figure out where I am going wrong?
Can't say for sure having the complete code, but I have the feeling it's related to where you're patching.
You should patch the os module that was imported by the module under test.
So, if you have it like this:
mymodule.py:
def func():
if not os.path.isdir('/tmp/folder'):
os.makedirs('/tmp/folder')
you should make your _test_mymodule.py_ like this:
#patch('mymodule.os')
def test_func(self, os_mock):
os_mock.path.isdir.return_value = False
assert os_mock.makedirs.called
Note that this specific test is not that useful, since it's essentially testing if the module os works -- and you can probably assume that is well tested. ;)
Your tests would probably be better if focused on your application logic (maybe, the code that calls func?).
You are missing the call to func().
#patch('os.path.isdir')
#patch('os.makedirs')
def test_func(patch_makedirs, patch_isdir):
patch_isdir.return_value = False
yourmodule.func()
assert patch_makedirs.called == True

Assert that logging has been called with specific string

I'm trying to use unittest to test some functions of a SimpleXMLRPCServer I made. Togethere with Mock, I'm now trying to assert that a specific message has been logged when an if statement is reached, but I can't get it to work. I've tried implementing various answers I found here on StackOverflow or by Googling, but still no luck. The calls I make in the Test Case are as follows:
def test_listen_for_tasks(self):
el = {'release': 'default', 'component': None}
for i in range(50):
self.server._queue.put(el)
ServerThread.listen_for_tasks(self.server, 'bla', 'blabla')
with mock.patch('queue_server.logging') as mock_logging:
mock_logging.warning.assert_called_with('There are currently {}'
' items in the queue'.format(
str(len(self.server._queue.queue))))
The function in the server is as follows:
def listen_for_tasks(self, release, component):
item = {'release': release, 'component': component}
for el in list(self._queue.queue):
if self.is_request_duplicate(el, item):
logger.debug('Already have a request'
' for this component: {}'.format(item))
return
self._queue.put(item, False)
if len(self._queue.queue) > 50:
logger.warning('There are currently {}'
' items in the queue'.format(
str(len(self._queue.queue))))
Any idea why this is not working? I'm new to unit testing in Python and asserting that a logger has done something seems the biggest problem one could face, so I might have screwed up with something really simple in the code. Any kind of help will be greatly appreciated!
EDIT: for completeness, here's the test output and failure:
.No handlers could be found for logger "queue_server"
F
FAIL: test_listen_for_tasks (__main__.TestQueueServer)
Traceback (most recent call last):
File "artifacts_generator/test_queue_server.py", line 46, in test_listen_for_tasks
str(len(self.server._queue.queue))))
File "/home/lugiorgi/Desktop/Code/publisher/env/local/lib/python2.7/site-packages/mock/mock.py", line 925, in assert_called_with
raise AssertionError('Expected call: %s\nNot called' % (expected,))
AssertionError: Expected call: warning('There are currently 51 items in the queue')
Not called
Ran 2 tests in 0.137s
FAILED (failures=1)
Since python 3.4 you can use unittest.TestCase class method assertLogs
import logging
import unittest
class LoggingTestCase(unittest.TestCase):
def test_logging(self):
with self.assertLogs(level='INFO') as log:
logging.info('Log message')
self.assertEqual(len(log.output), 1)
self.assertEqual(len(log.records), 1)
self.assertIn('Log message', log.output[0])
You need to first mock the object, then call the function you want to test.
When mocking the object, you also need to provide the full package and object/function name of the object you are mocking, not a variable name.
Finally, it's often more convenient to use the decorator form of patch.
So, for example:
logger = logging.getLogger(__name__)
def my_fancy_function():
logger.warning('test')
#patch('logging.Logger.warning')
def test_my_fancy_function(mock):
my_fancy_function()
mock.assert_called_with('test')
# if you insist on using with:
def test_my_fancy_function_with_with():
with patch('logging.Logger.warning') as mock:
my_fancy_function()
mock.assert_called_with('test')

Classical unit test as Groovy Spock method

I have a Groovy Spock method that has the following pattern:
def "My test"() {
def a = createA();
assert a.fieldLevel1.isValid()
def b = a.fieldLevel1
assert b.fieldLevel2.isValid()
def c = b.fieldLevel2
assert c.fieldLevel3.isValid()
...
}
As you can see it's hard to break it on blocks as assertions and variables definitions are mixed together. What would be the "spock" approach to write such kind of test?
UPDATE:
The test has the following structure because c.fieldLevel3.isValid() is actually c.fieldLevel3 instanceof A, so I can't proceed if the field is invalid.
The "classical" way of unit testing is keeping tests unitary. That is, testing one thing per test, which seems not to be the case in this example.
That being said, however, you could group all the assertions in an expect block after all the setup code in a setup block:
def "My test"() {
setup:
def b = createA().fieldLevel1
def c = b.fieldLevel2
def d = c.fieldLevel3
expect:
b.valid
c.valid
d.valid
}
Notice that i've shortened the assertions by using Groovy's goodies to access isValid() as valid and calling that method on the auxiliary objects directly.
Also, i haven't used the usual when/then Spock blocks because this test case doesn't seems to align very well with being a stimuli/response on a given system. But you could also use many when and then alternated blocks if you so desire:
def "My test"() {
when: def b = createA().fieldLevel1
then: b.valid
when: def c = b.fieldLevel2
then: c.valid
when: def d = c.fieldLevel3
then: d.valid
}
Not sure why you did not accept the answer above it looks quite good.
As a minor difference, you could also do:
def "My test of creating an A"() {
when:
def a = createA()
then:
a.fieldLevel1.isValid()
a.fieldLevel1.fieldLevel2.isValid()
a.fieldLevel1.fieldLevel2.fieldLevel3.isValid()
}
Whether or not you 'like' this depends upon how closely you follow Demeter's 'Law' - Groovy seems to make that less relevant than in the past.
If the complexity of the actual underlying objects is such that this is not an effective approach at validating them, then they might deserve their own Unit Tests.