Chapter 8: Unit testing

assert methods

face Josiah Wang

Recall that your test output from earlier looked something like this.

======================================================================
FAIL: test_negative_input (__main__.EuclideanTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "euclidean_test.py", line 16, in test_negative_input
    assert abs(dist - expected_answer) < epsilon
AssertionError
...

Would it not be nicer to get some more useful information about the AssertionError, like what the computed answer and the expected answer were?

The TestCase class actually provides a bunch of custom assert() methods to provide more useful information about any assertion errors.

Some examples include .assertEqual(), .assertTrue(), .assertIsInstance(), .assertIn(), .assertIsNone(), .assertLess(), and .assertAlmostEqual(). Please see the official documentation for more methods - there is no point in me listing them all here!

For our example, I’ve replaced the generic Python assert statements with some of these superclass methods (Lines 13, 18 and 24). The self.assertAlmostEqual() method is probably the most suitable one in this case (Line 18), but I am just including other methods to demonstrate how each reveal different information.

In Line 13, I’ve also provided a custom error message. This will be shown when a test fails.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import unittest

from euclidean import euclidean_distance

class EuclideanTest(unittest.TestCase):
    def test_positive_input(self):
        dist = euclidean_distance(3, 2, 5, 6)
        expected_answer = 2.828427
        epsilon = 0.000001
        error_message = f"For start point (-3, -2) and end point (5, 6), " \
            f"the function produced {dist} instead of the expected {expected_answer}."

        self.assertLess(abs(dist - expected_answer), epsilon, msg=error_message)

    def test_negative_input(self):
        dist = euclidean_distance(-3, -2, 5, 6)
        expected_answer = 10
        self.assertAlmostEqual(dist, expected_answer)

    def test_zero_input(self):
        dist = euclidean_distance(0, 0, 0, 0)
        expected_answer = 0
        epsilon = 0.000001
        self.assertTrue(abs(dist - expected_answer) < epsilon)

if __name__ == '__main__':
    unittest.main()

Running the tests, you should now get more information about your errors to help you debug your code! Note that I’m running the tests via python -m unittest test_euclidean this time.

user@MACHINE:~$ python3 -m unittest test_euclidean
FF.
======================================================================
FAIL: test_negative_input (__main__.EuclideanTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/xx/xx/test_euclidean.py", line 18, in test_negative_input
    self.assertAlmostEqual(dist, expected_answer)
AssertionError: 0 != 10 within 7 places (10 difference)

======================================================================
FAIL: test_positive_input (__main__.EuclideanTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/xx/xx/test_euclidean.py", line 13, in test_positive_input
    self.assertLess(abs(dist - expected_answer), epsilon,
AssertionError: 2.828427 not less than 1e-06 : For start point (-3, -2) and end point (5, 6), the function produced 0 instead of the expected 2.828427.
----------------------------------------------------------------------
Ran 3 tests in 0.003s

FAILED (failures=2)
user@MACHINE:~$