I have the following unit test, which tests if a function returns true or not.
import unittest
from connection import *
class TestConnection(unittest.TestCase):
def test_connection_ok(self):
assertTrue(testConnection())
if __name__ == '__main__':
unittest.main()
It prints
<function testConnectionat 0x7fa5c0845790>
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Why does it print <function testConnectionat 0x7fa5c0845790>? Printing the result of testConnection() does not print <function testConnectionat 0x7fa5c0845790>, unless it's called on the unit test.
Related
I am trying to run some unittest tests via a Python Invoke library, but my poor knowledge of Python prevents me from doing so.
This is the sample code I have:
my_tests.py
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# check that s.split fails when the separator is not a string
with self.assertRaises(TypeError):
s.split(2)
def main():
unittest.main()
if __name__ == '__main__':
main()
tasks.py
from invoke import task
#task
def tests(ctx):
main()
#task
def other_task(ctx):
print("This is fine")
def main():
import my_tests
import unittest
unittest.main(module='my_tests')
if __name__ == '__main__':
main()
And this is what I get:
C:\ittle_projects\invoke_unittest>python my_tests.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.002s
OK
C:\ittle_projects\invoke_unittest>python tasks.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
C:\ittle_projects\invoke_unittest>inv tests
E
======================================================================
ERROR: tests (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module 'my_tests' has no attribute 'tests'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
The tests run fine from my_tests.py and from tasks.py, but when I use invoke stuff breaks.
How can I make it work or where should I look next?
The issue you are running into is that unittest.main() uses the command line arguments your program is called with to determine which tests to run. Since your program is being executed as inv tests, the first argument to your program is tests, so unittest is attempting to run tests for a module name tests which does not exist.
You can get around this by popping the last argument (tests) from the system arguments list:
import sys
from invoke import task
#task
def tests(ctx):
# Pop "tests" off the end of the system arguments
sys.argv.pop()
main()
#task
def other_task(ctx):
print("This is fine")
def main():
import my_tests
import unittest
unittest.main(module='my_tests')
if __name__ == '__main__':
main()
I have multiple test classes in one module ops_tests.py.
class TestExecuteProc(unittest.TestCase):
def test(self):
<commands>
class TestSetupJobs(unittest.TestCase):
def test(self):
<commands>
Now I just want to test the second class, so I have the following in main
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestSetupJobs)
unittest.TextTestRunner.run(suite)
However, it still runs both test. What is the right way to pick classes to test?
You missed the instantiation of the TextTestRunner:
import unittest
class TestExecuteProc(unittest.TestCase):
def test(self):
self.assertTrue(False)
class TestSetupJobs(unittest.TestCase):
def test(self):
self.assertTrue(False)
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestSetupJobs)
unittest.TextTestRunner().run(suite)
Outputs:
F
======================================================================
FAIL: test (__main__.TestSetupJobs)
----------------------------------------------------------------------
Traceback (most recent call last):
File "ops_tests.py", line 9, in test
self.assertTrue(False)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
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()
I am just trying to understand the behavior of unittest's subclasses and methods. In the following code, I want to just run test_add method and not test_sub. Can someone please explain to me what I am doing wrong since the output proves that both the methods are being executed:
import unittest
def add(a,b):
x=a+b
return x
def sub(x,y):
z=x-y
return z
class addnum():
def calladd(self, a, b):
sum1 = add(a, b)
return sum1
def callsub(self,x,y):
diff = sub(x , y)
print "subtraction succ"
return diff
class test(addnum, unittest.TestCase):
def setup(self):
pass
def teardown(self):
pass
def test_add(self):
a1=addnum()
if a1.calladd(1, 2) ==3:
print "add successful"
assert addnum().calladd(1,2) == 3
def test_sub(self):
assert addnum().callsub(5, 3) == 2
print "abc"
#suite = unittest.TestSuite()
#suite.addTest(test('test_add'))
runner = unittest.TextTestRunner(verbosity=2)
runner.run(test(methodName='test_add'))
The output is as follows:
Finding files... done.
Importing test modules ... add successful
done.
add successful
subtraction succ
abc
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
test_add (trial2.test) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Please help. I admit my knowledge is pretty limited at this point.
First of all, you should not place those lines at the end of your module alone. Otherwise, every time you import the module, this test will be run. You should wrap them like this:
if __name__ == "__main__":
#suite = unittest.TestSuite()
#suite.addTest(test('test_add'))
runner = unittest.TextTestRunner(verbosity=2)
runner.run(test(methodName='test_add'))
In this way, your code will be run only when the .py module is called alone and not imported. Once like that seems to work just fine and only runs the requested test.
test_add (__main__.test) ... ok
add successful
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Always wrap it like that so it does not matter if you forget to remove your test.
So let's say I have the following:
import unittest
class MyTests(unittest.TestCase):
def test001(self):
print 'This is test001'
def test002(self):
print 'This is test002'
if __name__ == '__main__':
unittest.main()
print 'Done'
And the output is:
>> This is test001
>> This is test002
>> ----------------------------------------------------------------------
>> Ran 2 tests in 0.001s
>> OK
And I was wondering why doesn't get to print 'Done' (or anything that comes after)?
Pass exit=False to the unittest.main() call (documentation):
unittest.main(exit=False)
Here's what I'm getting on the console:
$ python test.py
This is test001
.This is test002
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Done
FYI, under the hood unittest's TestProgram.runTests() calls sys.exit() if the value of exit is True (which is by default):
def runTests(self):
...
if self.exit:
sys.exit(not self.result.wasSuccessful())