We can create unit tests using a library that provides a common framework for the test scenarios, along with a test runner to execute the tests and log results. Unit tests focus on testing the least amount of code possible in any one test. The standard library includes the unittest package. While widely used, this package tends to force us to create a fair amount of boilerplate code for each test case.

One of the more popular alternatives to the standard library unittest is pytest. This has the advantage of letting us write smaller, and more clear, test cases. The lack of overheads makes this a desirable alternative.

The distinctive features of pytest

The pytest tool can use a substantially different test layout from the unittest module. It doesn’t require test cases to be subclasses of unittest.TestCase. Instead, it takes advantage of the fact that Python functions are first-class objects and allows any properly named function to behave like a test. Rather than providing a bunch of custom methods for asserting equality, it uses the assert statement to verify results. This makes tests simpler, more readable, and, consequently, easier to maintain.

When we run pytest, it starts in the current folder and searches for any modules or sub-packages with names beginning with the characters test_. (Including the _ character.) If any functions in this module also start with test (no _ required), they will be executed as individual tests. Furthermore, if there are any classes in the module whose name starts with Test, any methods on that class that start with test_ will also be executed in the test environment.

It also searches in a folder named—unsurprisingly—tests. Because of this, it’s common to have code broken up into two folders: the src/ directory contains the working module, library, or application, while the tests/ directory contains all the test cases.

Using the following code, let’s port the simple unittest example we wrote earlier to pytest:

Get hands-on with 1200+ tech skills courses.