Python: Testing Your Work
Preamble: I am currently undergoing my Masters of Data Science and I am taking two preliminary courses in Python and R. I will be documenting journey in a series of journals that I will post on Medium
One of the underlying goal of this course is to develop strong developer habits. One of these habits is testing your code to ensure your code is correct and using the right tools to test for accuracy. These tools must be easy to use. We want to develop the habit of testing as soon as possible to detect any potential error and fixing immediately.
We will discuss different strategies for testing your code.
Doctest: Basic examples in Docstring
Coding beginners in often test their code in Python Interpreter by copy and pasting their examples in bits and pieces, running it and comparing it to their desired results in the docstring. Although this is effective — it is time consuming and lead to more errors (human errors) whilst copying and pasting. Surely, there must be an easier and faster way of testing.
So what are the other options:
Doctest:
We just simply import the doctest library which will look for examples in your docstring and automatically converts them to runnable tests.
How do we add it?
Simply do the following code to the bottom of your Python file
if __name__ == '__main__':
import doctest # import the doctest library
doctest.testmod() # run the testsAfter this is run, you will receive a report on all the tests that failed
Creating Test Suites with pytest
The one drawback of the DocTest is that we have to include examples in our docstring which will make it far too long for any reader to read.
So we will include a few basic doctest in our docstring — in this course, we will primarily test with pytest.
Get Stephen Ayeni’s stories in your inbox
Join Medium for free to get updates from this writer.
Why:
- It allows you to create a test on a separate file so that your py files is not crowded or too dense
- Because you are creating your tests in a different file — you can be as comprehensive as you would like to be
They are two important points you must note with pytest :
- Each function that begins with “test” is a separate test and they are run independently of each other and in random order
- The test use the
assertstatement as the actual action that would verify the correctness of your code. This is how it will be use:
assert <expression>The test need to give a boolean answer. So it will be like:
x == 3The test has to check certain actions of your function and see if it equivalent with the desired results. If theassert function is true, then we will say it passed the test but if the if theassert function is false, we will say it failed the test.
Choosing Test Cases:
As we said earlier, writing our tests in a separate file from our source code helps use to write a more comprehensive test package without worrying about the length but what does a “comprehensive” test look like?
It is pretty tricky to know what to include in your comprehensive test file. You have to balance two acts:
- Being aware of every potential use cases for your function and testing for them
- Being succinct in your tests and not have any redundant tests
A basic rule of thumb is to structure your tests around the properties of your inputs. For example:
- Integers: 0, 1, postive, negative, smal, large
- Lists: empty, length 1, no duplicates, duplicates, sorted and unsorted
- Strings: empty, length 1, alphanumeric characters only, special characters like punctuation marks.
What if the function takes on multiple inputs? What do we do then?
We choose the properties based on the relationship between the inputs
For example:
- A function that takes on two integers as inputs: Test the function when the inputs are the same, the 1st number is larger than the 2nd, the 2nd number is larger than the 1st
- A function that takes on an object and a list: Test the function when the object is inside the list as well and when the object is not inside the list
Fundamentally, to create a comprehensive testing file for your function — you must understand the goal of the function and what inputs truly matter to the function. Then you build a testing file from there.
Recap:
We use two testing strategies to test for the accuracy of our function and to catch error as early as possible
- Doctest: This will simply turn the examples in your docstring into runnable test. It is effective but it will crowd your docstring and make it too long for your reader.
- PyTest: We create a separate file from our source code and this allows for a more comprehensive testing for the functions in your source code.








