Test-driven development in Jupyter Notebook

In the blog post “5 reasons why jupyter notebooks suckAlexander Mueller complained that code written in notebooks is difficult to test.

Unfortunately, that is true, but I want to show you how to work around that issue and get something that resembles test-driven development in notebooks.

First of all, we must get used to the fact that there is no support for any testing library used in Python. The only things we can use, are the testing capabilities built-in Python, which means the “assert” keyword.

That’s it. The only thing we have is the ability to check if an expression returns True.

The second problem is the way Jupyter displays assertion errors. It looks like every other type of error. We must get used to that too.

There are dozens of books about test-driven development itself, so I am not going to focus on the method. Instead of that, I will show you the tools.



The “assert” keyword

How does the “assert” work? The assert’s parameters consist of two parts. The first part is the boolean expression that is supposed to be True. The second parameter is the error message to be displayed if the boolean expression evaluates to False. We can use the second parameter to give the test a name or describe what should happen.

Let’s look at an example. In this case, the assertion fails, and we get an error.

1
2
3
4
def multiplyByTwo(x):
    return x * 3

assert multiplyByTwo(2) == 4, "2 multiplied by 2 should be equal 4"

Unfortunately, there is no way to get the value returned by the function and display it with the error message unless you call the same function twice.

1
2
3
4
def multiplyByTwo(x):
    return x * 3

assert multiplyByTwo(2) == 4, "2 multiplied by 2 should be equal 4, but the function returned: " +  str(multiplyByTwo(2))

It is trivial in this case, but if the function does some heavy computation may take some time to get the error message. You can avoid this problem by assigning the output to a variable and using the variable in the assert clause.

1
2
3
4
5
def multiplyByTwo(x):
    return x * 3

result = multiplyByTwo(2)
assert result == 4, "2 multiplied by 2 should be equal 4, but the function returned: " +  str(result)

What happens if the test passes? That is kind of sad, but it does not display anything.

You won’t see a green progress bar or an encouraging message like: “All tests passed.” If you have done everything right, all you get is an empty output.


Remember to share on social media!
If you like this text, please share it on Facebook/Twitter/LinkedIn/Reddit or other social media.

If you watch programming live streams, check out my YouTube channel.
You can also follow me on Twitter: @mikulskibartosz

If you want to hire me, send me a message on LinkedIn or Twitter.


Bartosz Mikulski
Bartosz Mikulski * big data engineer * conference speaker * co-founder of Software Craftsmanship Poznan & Poznan Scala User Group