Chapter 10: Debugging and testing

Assert statement

face Josiah Wang

Earlier, we have loosely introduced the concept of automated testing via a ‘test-first’ approach.

In this style of development, testing is part of the design and coding process, rather than just an afterthought.

More precisely, rather than “write your function, now test your code to make sure that the function works correctly”, you now “write the test code to understand what we expect of our function, and then implement the function, and then make sure that our implementation passes all the tests”.

So you can use tests as a way to really understand how you want your function to behave, as well as making sure what you implemented is correct.

So, let’s go back to our example of implementing a Euclidean distance function.

1
2
def euclidean_distance(x1, y1, x2, y2):
    pass

Now, we write our test again, this time as a function (because we want everything to be modular!) It is convention to prefix test_ to your test functions.

1
2
3
4
5
6
7
8
def test_euclidean_distance():
    distance = euclidean_distance(2, 3, -2, 1)
    expected_answer = 4.4721
    epsilon = 0.000001
    if abs(distance - expected_answer) < epsilon:
        print("Test passed")
    else:
        print(f"Test failed. {expected_answer} expected, but {distance} returned.")

The test code in Lines 5 - 8 is quite wordy though.

Python provides the assert keyword to make it easier to write tests.

1
2
3
4
5
def test_euclidean_distance():
    distance = euclidean_distance(2, 3, -2, 1)
    expected_answer = 4.4721
    epsilon = 0.000001
    assert abs(distance - expected_answer) < epsilon

An assert statement basically says “make sure that the condition is True. If not, stop the program with an error message”.

You can add a custom error message that displays if the test fails.

assert abs(distance - expected_answer) < epsilon, f"Test failed. {expected_answer} expected, but {distance} returned."

assert statements can also be used as a defensive programming technique to make sure that the input of a function is valid.

def calculate(x, y):
    assert x > 0, "x must be positive."
    assert y != 0, "y must be nonzero."
    return -3*x / y