Python unittest, how to display a better group/test name? - python

Using Python Unittest, here's an example of a test suite :
import unittest
# Here's our "unit".
def IsOdd(n):
return n % 2 == 1
# Here's our "unit tests".
class IsOddTests(unittest.TestCase):
def testOne(self):
self.failUnless(IsOdd(1))
def testTwo(self):
self.failIf(IsOdd(2))
def main():
unittest.main(verbosity=2)
if __name__ == '__main__':
main()
And the result :
testOne (__main__.IsOddTests) ... ok
testTwo (__main__.IsOddTests) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Is it possible to enhance the display of the tests, something like :
Testing ODD method
Testing with value is 1 (__main__.IsOddTests) ... ok
Testing with value is 2 (__main__.IsOddTests) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
What I'm trying to do, is in case of a lot of tests, displaying a Group name for each TestCase (that contains multiple tests), and a name for each tests (that should be more explicit than just the function name).

To do this simply set a docstring for your tests:
def testOne(self):
"""Test IsOdd(1)"""
self.failUnless(IsOdd(1))
def testTwo(self):
"""Test IsOdd(2)"""
self.failIf(IsOdd(2))
There's a bit of an art to picking docstrings for your tests that will make sense later. Don't be afraid to go back and refactor your things.

Related

How to use unittest.TestSuite in VS Code?

In the future, I'll need to add many identical tests with different parameters. Now I am making a sample test suite:
import unittest
class TestCase(unittest.TestCase):
def __init__(self, methodName='runTest', param=None):
super(TestCase, self).__init__(methodName)
self.param = param
def test_something(self):
print '\n>>>>>> test_something: param =', self.param
self.assertEqual(1, 1)
if __name__ == "__main__":
suite = unittest.TestSuite()
testloader = unittest.TestLoader()
testnames = testloader.getTestCaseNames(TestCase)
for name in testnames:
suite.addTest(TestCase(name, param=42))
unittest.TextTestRunner(verbosity=2).run(suite)
It gets discovered by VS Code:
start
test.test_navigator.TestCase.test_something
When I run the tests, I don't receive the parameter:
test_something (test.test_navigator.TestCase) ...
>>>>>> test_something: param = None
ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
If I run this file directly, everything works as expected (note param = 42 part)
test_something (__main__.TestCase) ...
>>>>>> test_something: param = 42
ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
So it looks like VS Code is running the tests on its own just by using the discovered classes and ignoring TestSuite completely?
What am I doing wrong?
Thanks.
The problem is your code is in a if __name__ == "__main__" block which is only executed when you point Python directly at the file. So when the extension asks unittest to get all the tests and then run them for us it doesn't run the code in your if __name__ == "__main__" block (which is why it can find it but it doesn't do anything magical).
If you can get it to work using unittest's command-line interface then the extension should run it as you want it to.
The key is to implement the load_tests function:
def load_tests(loader, tests, pattern):
suite = unittest.TestSuite()
testnames = loader.getTestCaseNames(TestCase)
for name in testnames:
suite.addTest(TestCase(name, param=42))
suite.addTest(TestCase(name, param=84))
return suite
The documentation says:
If load_tests exists then discovery does not recurse into the package, load_tests is responsible for loading all tests in the package.
Now my tests run as expected.
P.S. Thanks to Brett Cannon for pointing me to Unit testing framework documentation

Run skipped tests by nosetest (no-skip doesn't work)

I have a lot of legacy test like this. Tests are skipped with unittest but are run with nosetests.
import unittest
import nose
import time
class BaseTestClass(unittest.TestCase):
#unittest.skip("Skipped")
def test_add(self):
"""Test 1"""
print "Execute test 1"
time.sleep(5)
def test_sub(self):
"""Test 2"""
print "Execute test 2"
time.sleep(5)
if __name__ == '__main__':
nose.run(argv=["nose", ".", "--verbosity=2", "--nocapture", '--no-skip'])
I want to run all skipped tests.
Looks like "no-skip" - option not works, become I have output
Execute test 2
Test 1 ... Test 2 ... ok
----------------------------------------------------------------------
Ran 2 tests in 5.001s
OK
looks like test is present in output but doesn't execute code inside.
I expected to see:
Test 1 ... ok
Execute test 1
Test 2 ... ok
Execute test 2
----------------------------------------------------------------------
Ran 2 tests in 10 s
OK
I got a similar problem, and after some research the issue seems to be that --no-skip does not have anything to do with unittests.skip but with the handling the exception nose.SkipTest.
I ended up with a hacky solution that does the job in my case. Maybe it can help somebody. It consists of using your own custom skip function so that it "piggybacks" the --no-skip flag and reacts accordingly.
import sys
import unittest
no_skip_mode = '--no-skip' in sys.argv
def skip(reason):
if no_skip_mode:
# Don't decorate the test function. Just return as is.
def dummy_wrapper(fn):
return fn
return dummy_wrapper
return unittest.skip(reason)
I guess you could try to monkeypatch unittest.skip.

Why does python only run a single test_method in my TestCase?

I have a set of unit tests that look basically like this:
import unittest
class MyTestCase(unittest.TestCase):
def test_one(self):
self.assertEqual(1,1)
def test_two(self):
self.assertEqual(2,2)
if __name__ == '__main__':
unittest.main()
When I run the tests, I would expect to see results from both test_methods (test_one and test_two), but I only get results for one:
$ python -m unittest -v tests.test_dummy
test_one (tests.test_dummy.MyTestCase) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
What's going on here?
Oh, this is mortifying.
It was an indentation problem. The test file had a combination of tabs and spaces, so the second test wasn't being identified.
I copied the invisible glitch from my real code, to the simplified MyTestCase class I used to replicate the error. But stackoverflow stripped out the tabs, so no one else was able to replicate.
Here's the bug that was killing my code. Tabs are shown with hyphens: ----
import unittest
class MyTestCase(unittest.TestCase):
def test_one(self):
self.assertEqual(1,1)
----def test_two(self):
--------self.assertEqual(2,2)
if __name__ == '__main__':
unittest.main()

Python doesn't detect my unittest

I have following code snippet -
import unittest
class SimpleWidgetTestCase(unittest.TestCase):
def setUp(self):
print 'setup'
def method_test(self):
print 'test method'
def tearDown(self):
print 'tear down'
if __name__ == "__main__":
unittest.main()
Output -
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
test method name should start with test. Replace method_test to test_method, and try again.
From unittest documentation:
A testcase is created by subclassing unittest.TestCase. The three
individual tests are defined with methods whose names start with the
letters test. This naming convention informs the test runner about
which methods represent tests.

python unittest methods

Can I call a test method from within the test class in python? For example:
class Test(unittest.TestCase):
def setUp(self):
#do stuff
def test1(self):
self.test2()
def test2(self):
#do stuff
update: I forgot the other half of my question. Will setup or teardown be called only after the method that the tester calls? Or will it get called between test1 entering and after calling test2 from test1?
This is pretty much a Do Not Do That. If you want tests run in a specific order define a runTest method and do not name your methods test....
class Test_Some_Condition( unittest.TestCase ):
def setUp( self ):
...
def runTest( self ):
step1()
step2()
step3()
def tearDown( self ):
...
This will run the steps in order with one (1) setUp and one (1) tearDown. No mystery.
Try running the following code:
import unittest
class Test(unittest.TestCase):
def setUp(self):
print 'Setting Up'
def test1(self):
print 'In test1'
self.test2()
def test2(self):
print 'In test2'
def tearDown(self):
print 'Tearing Down'
if __name__ == '__main__':
unittest.main()
And the results is:
Setting Up
In test1
In test2
Tearing Down
.Setting Up
In test2
Tearing Down
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Now you see, setUp get called before a test method get called by unittest, and tearDown is called after the call.
All methods whose name begins with the string 'test' are considered unit tests (i.e. they get run when you call unittest.main()). So you can call methods from within the Test class, but you should name it something that does not start with the string 'test' unless you want it to be also run as a unit test.
sure, why not -- however that means test2 will be called twice -- once by test1 and then again as its own test, since all functions named test will be called.
Yes to both:
setUp will be called between each test
test2 will be called twice.
If you would like to call a function inside a test, then omit the test prefix.

Categories