= Python Unittest = '''`unittest`''' is a module for unit testing code. It is ''by design'' a basic and minimal tool; it was designed for use within Python and requiring no external libraries or tools. <> ---- == Module == === Usage === {{{ import unittest class Test1(unittest.TestCase): """This is a class docstring.""" def test_1(self): #This will print "test_1 (__main__.Test1) ... ok" return def test_2(self): #This will print "test_1 (__main__.Test1) ... FAIL" self.fail() def test_3(self): #This will print "test_3 (__main__.Test1) ... ERROR" raise AttributeError @u.skip('foo bar') def test_4(self): #This will print "test_3 (__main__.Test1) ... skipped 'foo bar'" return if __name__ == '__main__': unittest.main() }}} Any methods with a docstring print both the method's name and the docstring. All failures or errors print tracebacks, the only difference being the label ('FAIL' or 'ERROR'). ==== Setup and Teardown ==== The most common reason for grouping a set of tests into a test case is shared objects. These can be generated using the `TestCase.setUp()` method. (A `tearDown()` method is also available if needed.) {{{ class TestWidget(unittest.TestCase): def setUp(self): self.widget = Widget('The widget')\ def tearDown(self): self.widget.dispose() }}} ==== Subtests ==== Sometimes a test needs to be run iteratively, as to test multiple possible inputs. Rather than requiring redundant coding, the subtests context will provide this functionality. {{{ class TestEven(unittest.TestCase): def test_1(self): for i in range(0, 6): with self.subTest(i=i): self.assertEqual(i % 2, 0) }}} The `i=i` may seem redundant, but it will cause the subtest's value of `i` to print on execution. ==== Conditional Testing ==== Tests can be skipped conditionally. This can be used to prevent trivial test failures. {{{ class TestVersion(unittest.TestCase): @unittest.skipIf(mylib.__version__ < (1, 3)) def test_1(self): return }}} ---- === Test Methods === ||'''Method''' ||'''Equivalent to...''' ||'''Usage''' || ||`assertEqual` ||`a == b` ||`self.assertEqual(a,b,msg=m)` || ||`assertNotEqual` ||`a != b` ||`self.assertNotEqual(a,b,msg=m)` || ||`assertGreater` ||`a > b` ||`self.assertGreater(a,b,msg=m)` || ||`assertGreaterEqual` ||`a >= b` ||`self.assertGreaterEqual(a,b,msg=m)` || ||`assertLesser` ||`a < b` ||`self.assertLesser(a,b,msg=m)` || ||`assertLesserEqual` ||`a <= b` ||`self.assertLesserEqual(a,b,msg=m)` || ||`assertTrue` ||`bool(a) == True` ||`self.assertTrue(a,msg=m)` || ||`assertFalse` ||`bool(a) == False` ||`self.assertFalse(a,msg=m)` || ||`assertIs` ||`a is b` ||`self.assertIs(a,b,msg=m)` || ||`assertIsNot` ||`a is not` ||`self.assertIsNot(a,b,msg=m)` || ||`assertIsNone` ||`a is None` ||`self.assertIsNone(a,b,msg=m)` || ||`assertIsNotNone` ||`a is not None` ||`self.assertIsNotNone(a,b,msg=m)` || ||`assertIn` ||`a in b` ||`self.assertIn(a,b,msg=m)` || ||`assertNotIn` ||`a not in b` ||`self.assertNotIn(a,b,msg=m)` || ||`assertRegex` ||`re.search(b,a)` ||`self.assertRegex(a,b)` || ||`assertNotRegex` ||`not re.search(b,a)` ||`self.assertNotRegex(a,b)` || ||`assertIsInstance` ||`isinstance(a,b)` ||`self.assertIsInstance(a,b,msg=m)` || ||`assertIsNotInstance` ||`not isinstance(a,b)` ||`self.assertIsNotInstance(a,b,msg=m)` || ||`assertRaises` || ||`with self.assertRaises(e,msg=m): ...`|| ---- === CLI Execution === Verbosity is set with `--quiet` (`-q`) and `--verbose` (`-v`) flags. The `discover` subcommand searches for files names matching the pattern `test*.py`. A search directory can be optionally supplied using `--start-directory` (`-s`). An alternate pattern can be optionally supplied using `--pattern` (`-p`). {{{ $ python -m unittest discover -s tests/ -v }}} ---- == Writing Unit Tests == === Bad File Inputs === To create a file with a bad encoding, try: {{{ def write_bad_file(fn): with open(fn, 'w') as f: f.write('fooß'.encode('utf-8')) f.write('barß'.encode('cp1252')) }}} ---- == See also == [[https://docs.python.org/3/library/unittest.html|Python unittest module documentation]] [[https://pymotw.com/3/unittest/|Python Module of the Day article for unittest]] ---- CategoryRicottone