14. Testing with Pytest
By Bernd Klein. Last modified: 08 Mar 2024.
Introduction
pytest can be used for all types and levels of software testing. Many projects – amongst them Mozilla and Dropbox - switched from unittest or nose to pytest.
Live Python training
See our Python training courses
A Simple First Example with Pytest
Test files which pytest will use for testing have to start with test_ or end with _test.py We will demonstrate the way of working by writing a test file test_fibonacci.py for a file fibonacci.py. Both files are in one directory:
The first file is the file which should be tested. We assume that it is saved as fibonacci_p.py:
def fib(n):
old, new = 0, 1
for _ in range(n):
old, new = new, old + new
return old
Now, we have to provide the code for the file test_fibonacci.py. This file will be used by 'pytest':
from fibonacci_p import fib
def test_fib():
assert fib(0) == 0
assert fib(1) == 1
assert fib(10) == 55
We call pytest in a command shell in the directory where the two file shown above reside:
pytest
The result of this code can be seen in the following:
============================= test session starts ============================== platform linux -- Python 3.7.1, pytest-4.0.2, py-1.7.0, pluggy-0.8.0 rootdir: /home/bernd/, inifile: plugins: remotedata-0.3.1, openfiles-0.3.1, doctestplus-0.2.0, arraydiff-0.3 collected 1 item test_fibonacci.py . [100%] =========================== 1 passed in 0.01 seconds ===========================
We create now an erroneous version of fib. We change the two start values from 0 and 1 to the values 2 and 1. This is the beginning of the Lucas sequence, but as we want to implement the Fibonacci sequence this is wrong. This way, we can study how pytest behaves in this case:
def fib(n):
old, new = 2, 1
for _ in range(n):
old, new = new, old + new
return old
Calling 'pytest' with this erroneous implementation of fibonacci gives us the following results:
$ pytest ============================= test session starts ==============================
platform linux -- Python 3.7.1, pytest-4.0.2, py-1.7.0, pluggy-0.8.0
rootdir: /home/bernd/, inifile:
plugins: remotedata-0.3.1, openfiles-0.3.1, doctestplus-0.2.0, arraydiff-0.3
collected 1 item
test_fibonacci.py F [100%]
=================================== FAILURES ===================================
___________________________________ test_fib ___________________________________
def test_fib():
> assert fib(0) == 0
E assert 2 == 0
E + where 2 = fib(0)
test_fibonacci.py:5: AssertionError
=========================== 1 failed in 0.03 seconds ===========================
Another Pytest Example (1)
We will get closer to 'reality' in our next example. In a real life scenario, we will usually have more than one file and for each file we may have a corresponding test file. Each test file may contain various tests. We have various files in our example folder ex2:
The files to be tested:
- fibonacci.py
- foobar_plus.py
- foobar.py
The test files:
- test_fibonacci.py
- test_foobar_plus.py
- test_foobar.py
We start 'pytest' in the directory 'ex2' and get the following results:
$ pytest ==================== test session starts ====================== platform linux -- Python 3.7.3, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 rootdir: /home/bernd/ex2, inifile: plugins: remotedata-0.3.1, openfiles-0.3.2, doctestplus-0.3.0, arraydiff-0.3 collected 4 items test_fibonacci.py . [ 25%] test_foobar.py .. [ 75%] test_foobar_plus.py . [100%] ==================== 4 passed in 0.05 seconds =================
