Calling TestCase class cause functions to run twice - python

I was trying to dynamically create test functions when I notice a weird behavior that I do not understand. I have reduced the code to this for simple understanding. I am running it on python 3.6.7
Code:
import unittest
class MyTestCase(unittest.TestCase):
#classmethod
def setUpClass(cls):
print('SET UP')
def test_x(self):
print('hi')
x = MyTestCase # <-This causes the test function to run twice, Why???
if __name__ == "__main__":
print('test start')
unittest.main()
print('test end') # <- This does not get printed
Output:
test start
SET UP
hi
.hi
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
As you can see, the test function test_x is being run twice and the last print statement is not executed
So my questions are:
why does the test function run twice?
why is the print statement print('test end') not executed?

1. why does the test function run twice?
Because the unittest code finds two objects in the module's namespace that are unittest.TestCase classes, MyTestCase and x. It doesn't check that these are actually the same object. (Well, it has some awareness of this, in that it doesn't treat x as a new class to be tested, so it doesn't call setUpClass again; see "Class and Module Fixtures".)
2. why is the print statement print('test end') not executed?
By default, unittest.main() calls sys.exit() after running the tests. You can disable this by adding the argument exit=False:
if __name__ == "__main__":
print('test start')
unittest.main(exit=False)
print('test end')

Related

How to exit the script in a unittest test case

Here is a sample script that checks for a precondition in the very first test case and my intention is to abort the script if the precondition is not met.
#!/usr/bin/python
import unittest
import sys
class TestMyScript(unittest.TestCase):
def test_000_prerequisite(self):
a = 0
if not a:
sys.exit()
return
def test_001_test1(self):
print "Inside test 1"
return
def test_002_test2(self):
print "Inside test 2"
return
if __name__ == "__main__":
unittest.main()
However, the sys.exit() only exits from the individual test case of the suite. It doesn't exit the whole script.
I understand that unittest treats each test case individually which is why any exceptions caused by any testcase are handled by the test runner and it proceeds to the next test case.
But I want the script to kill itself. How do I do that?
Here is the output of my script:
./temp.py
EInside test 1
.Inside test 2
.
======================================================================
ERROR: test_000_prerequisite (__main__.TestMyScript)
----------------------------------------------------------------------
Traceback (most recent call last):
File "./temp.py", line 9, in test_000_prerequisite
sys.exit()
SystemExit
----------------------------------------------------------------------
Ran 3 tests in 0.000s
FAILED (errors=1)
My guess is that I have to mess around with TestRunner and kill the script if a test case returns some signal. But I am not sure how to really achieve it.
Here is the answer:
Stop testsuite if a testcase find an error
Here is the change I need to make when calling unittest.main(). The failfast keyword argument stops the script after the first failure.
if __name__ == "__main__":
unittest.main(failfast=True)
p.s. failfast keyword argument is only available for python 2.7+
p.p.s. you can also use failfast on unittest.TextTestRunner()

Python Unit-Testing: In Nose is there a way to skip a test case from nose.run()?

I am writing a set of test cases say Test1, Test2 in a test module.
Is there a way to skip Test1 or selectively execute only Test2 in that module using the command nose.main()?
My module contains,
test_module.py,
class Test1:
setUp(self):
print('setup')
tearDown(self):
print('teardown')
test(self):
print('test1')
class Test2:
setUp(self):
print('setup')
tearDown(self):
print('teardown')
test(self):
print('test2')
I run it from a different python file using,
if __name__ == '__main__':
nose.main('test_module')
The notion of skipping test and not running a test are different in the context of nose: skipped tests will be reported as skipped at the end of the test result. If you want to skip the test you would have to monkey patch your test module with decorators or do some other dark magic.
But if you want to just not run a test, you can do it the same way you would do it from the command line: using --exclude option. It takes a regular expression of the test you do not want to run. Something like this:
import sys
import nose
def test_number_one():
pass
def test_number_two():
pass
if __name__ == '__main__':
module_name = sys.modules[__name__].__file__
nose.main(argv=[sys.argv[0],
module_name,
'--exclude=two',
'-v'
])
Running the test will give you:
$ python stackoverflow.py
stackoverflow.test_number_one ... ok
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK

Python Define Unit Test Classes Together with Code

I am rapid prototyping so for now I would like to write unit tests together with the code I am testing - rather than putting the tests in a separate file. However, I would only like to build the test an invoke them if we run the code in the containing file as main. As follows:
class MyClass:
def __init(self)__:
# do init stuff here
def myclassFunction():
# do something
if __name__ == '__main__':
import unittest
class TestMyClass(unittest.TestCase):
def test_one(self):
# test myclassFunction()
suite = unittest.TestLoader().loadTestsFromTestCase(TestMyClass)
unittest.TextTestRunner(verbosity=2).run(suite)
This of course doesn't run as unittest is unable to find or make use of the test class, TestMyClass. Is there a way to get this arrangement to work or do I have to pull everything out of the if __name__ == '__main__' scope except the invocation to unittest?
Thanks!
If you move your TestMyClass above of if __name__ == '__main__'
you will get exactly what you want:
Tests will run only when file executed as main
Something like this
import unittest
class MyClass:
def __init(self)__:
# do init stuff here
def myclassFunction():
# do something
class TestMyClass(unittest.TestCase):
def test_one(self):
if __name__ == '__main__':
unittest.main()

Controlling the order tests are run in Selenium

Here is my code:
class MyTestCase(Base):
def setUp(self):
#some code here
def test_B(self):
#some code here
def test_C(self):
#some code here
def test_A(self):
#some code here
def tearDown(self):
#some code here
if __name__ == "__main__":
unittest.main()
My problem here is that all my tests are executed in alphabetical order, i.e. test_A is first executed, then test_B and then test_C. I want it to execute in the order I have written, i.e. test_B -> test_C -> test_A.
How do I change the order in which the tests are executed?
If your tests need to be in a specific order I think they should be in the same function, but thats just my opinion, check out changing order of unit tests in Python

Problem's running unittest test suite OO

I have a test suite to perform smoke tests. I have all my script stored in various classes but when I try and run the test suite I can't seem to get it working if it is in a class. The code is below: (a class to call the tests)
from alltests import SmokeTests
class CallTests(SmokeTests):
def integration(self):
self.suite()
if __name__ == '__main__':
run = CallTests()
run.integration()
And the test suite:
class SmokeTests():
def suite(self): #Function stores all the modules to be tested
modules_to_test = ('external_sanity', 'internal_sanity')
alltests = unittest.TestSuite()
for module in map(__import__, modules_to_test):
alltests.addTest(unittest.findTestCases(module))
return alltests
if __name__ == '__main__':
unittest.main(defaultTest='suite')
This output's an error:
Attribute Error: 'module' object has no attribute 'suite'
So I can see how to call a normal function defined but I'm finding it difficult calling in the suite. In one of the tests the suite is set up like so:
class InternalSanityTestSuite(unittest.TestSuite):
# Tests to be tested by test suite
def makeInternalSanityTestSuite():
suite = unittest.TestSuite()
suite.addTest(TestInternalSanity("BasicInternalSanity"))
suite.addTest(TestInternalSanity("VerifyInternalSanityTestFail"))
return suite
def suite():
return unittest.makeSuite(TestInternalSanity)
If I have someSuite() inside the class SmokeTests python cannot find the attribute suite but if I remove the class it work's. I run this as a script and call in variables into the tests. I do not want to have to run the tests by os.system('python tests.py'). I was hoping to call the tests through the class I have like any other function
Can anyone help me with getting this running?
Thanks for any help in advance.
I know this is not the answer, but I'd suggest using library that can use test discovery, like nose or unittest capability from Python 2.7+.
Possibility to do
nosetests module.submodule
or
nosetests module.submodule:TestCase.test_method
is priceless :)
This can't work:
class SmokeTests():
def suite(self): #Function stores all the modules to be tested
modules_to_test = ('external_sanity', 'internal_sanity')
alltests = unittest.TestSuite()
for module in map(__import__, modules_to_test):
alltests.addTest(unittest.findTestCases(module))
return alltests
if __name__ == '__main__':
unittest.main(defaultTest='suite')
This output's an error: Attribute Error: 'module' object has no attribute 'suite'.
Your suite the value of the SmokeTests().suite() method. Note a variable named suite, since you have no such variable.
It's easier to use a simple function for your suite.
def someSuite():
modules_to_test
...
return alltests
if __name__ == "__main__":
unittest.main( defaultTest= someSuite() )
Something like that would be closer to correct.

Categories

Resources