Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/07-Errors and Exception Handling/04-Unit Testing.ipynb
Views: 648
Unit Testing
Equally important as writing good code is writing good tests. Better to find bugs yourself than have them reported to you by end users!
For this section we'll be working with files outside the notebook. We'll save our code to a .py file, and then save our test script to another .py file. Normally we would code these files using a text editor like Brackets or Atom, or inside an IDE like Spyder or Pycharm. But, since we're here, let's use Jupyter!
Recall that with some IPython magic we can write the contents of a cell to a file using %%writefile
.
Something we haven't seen yet; you can run terminal commands from a jupyter cell using !
Testing tools
There are dozens of good testing libraries out there. Most are third-party packages that require an install, such as:
These are simple tools that merely look at your code, and they'll tell you if there are style issues or simple problems like variable names being called before assignment.
A far better way to test your code is to write tests that send sample data to your program, and compare what's returned to a desired outcome.
Two such tools are available from the standard library:
Let's look at pylint first, then we'll do some heavier lifting with unittest.
pylint
pylint
tests for style as well as some very basic program logic.
First, if you don't have it already (and you probably do, as it's part of the Anaconda distribution), you should install pylint
.
Once that's done feel free to comment out the cell, you won't need it anymore.
Let's save a very simple script:
Now let's check it using pylint
Pylint first lists some styling issues - it would like to see an extra newline at the end, modules and function definitions should have descriptive docstrings, and single characters are a poor choice for variable names.
More importantly, however, pylint identified an error in the program - a variable called before assignment. This needs fixing.
Note that pylint scored our program a negative 12.5 out of 10. Let's try to improve that!
Much better! Our score climbed to 8.33 out of 10. Unfortunately, the final newline has to do with how jupyter writes to a file, and there's not much we can do about that here. Still, pylint helped us troubleshoot some of our problems. But what if the problem was more complex?
pylint tells us there's an unused variable in line 10, but it doesn't know that we might get an unexpected output from line 12! For this we need a more robust set of tools. That's where unittest
comes in.
unittest
unittest
lets you write your own test programs. The goal is to send a specific set of data to your program, and analyze the returned results against an expected result.
Let's generate a simple script that capitalizes words in a given string. We'll call it cap.py.
Now we'll write a test script. We can call it whatever we want, but test_cap.py seems an obvious choice.
When writing test functions, it's best to go from simple to complex, as each function will be run in order. Here we'll test simple, one-word strings, followed by a test of multiple word strings.
What happened? It turns out that the .capitalize()
method only capitalizes the first letter of the first word in a string. Doing a little research on string methods, we find that .title()
might give us what we want.
Hey, it passed! But have we tested all cases? Let's add another test to test_cap.py to see if it handles words with apostrophes, like don't.
In a text editor this would be easy, but in Jupyter we have to start from scratch.
Now we have to find a solution that handles apostrophes! There is one (look up capwords
from the string
module) but we'll leave that as an exercise for the reader.
Great! Now you should have a basic understanding of unit testing!