9.3. AssertionError: Found longer than expected

9.3.1. FAIL: test_wrong_results (__main__.HelperTestCase)

Traceback (most recent call last):
File "helper_test.py", line 52, in test_wrong_results

self.verify_complex_case(values, expected)

File "helper_test.py", line 24, in verify_complex_case

f'Index {i} is wrong')

AssertionError: 36.3 != 16.939999999999998 : Index 2 is wrong

FAILED (failures=2)

I usually define one TestCase subclass for each set of related tests. Sometimes, I have one TestCase subclass for each function that has many edge cases. Other times, a TestCase subclass spans all functions in a single module. I often create one TestCase subclass for testing each basic class and all of its methods.

The TestCase class also provides a subTest helper method that enables you to avoid boilerplate by defining multiple tests within a single test method. This is especially helpful for writing data-driven tests, and it allows the test method to continue testing other cases even after one of them fails (similar to the behavior of TestCase with its contained test methods). To show this, here I define an example data-driven test:

# data_driven_test.py from unittest import TestCase, main from utils import to_str

class DataDrivenTestCase(TestCase):
def test_good(self):
good_cases = [

(b'my bytes', 'my bytes'), ('no error', b'no error'), # This one will fail ('other str', 'other str'), ...

] for value, expected in good_cases:

with self.subTest(value):

self.assertEqual(expected, to_str(value))

def test_bad(self):
bad_cases = [

(object(), TypeError), (b'xfaxfa', UnicodeDecodeError), ...

]
for value, exception in bad_cases:
with self.subTest(value):
with self.assertRaises(exception):

to_str(value)

if __name__ == '__main__':

main()

The ‘no error’ test case fails, printing a helpful error message, but all of the other cases are still tested and confirmed to pass:

$ python3 data_driven_test.py . =============================================================== FAIL: test_good (__main__.DataDrivenTestCase) [no error] --------------------------------------------------------------- Traceback (most recent call last):

File "testing/data_driven_test.py", line 18, in test_good

self.assertEqual(expected, to_str(value))

AssertionError: b'no error' != 'no error'

FAILED (failures=1)

Note

Depending on your project’s complexity and testing requirements, the pytest (https://pytest.org) open source package and its large number of community plug-ins can be especially useful.

9.3.2. Things to Remember

✦ You can create tests by subclassing the TestCase class from the unittest built-in module and defining one method per behavior you’d like to test. Test methods on TestCase classes must start with the word test.

✦ Use the various helper methods defined by the TestCase class, such as assertEqual, to confirm expected behaviors in your tests instead of using the built-in assert statement.

✦ Consider writing data-driven tests using the subTest helper method in order to reduce boilerplate.