title | description | slideOptions | ||
---|---|---|---|---|
ESWN 2021 - Writing unit tests |
Tutorial for 2021 ESWN PyGMT workshop |
|
Because tested code is code that you can trust
P.S. Slides are at https://hackmd.io/@pygmt/eswn-2021-writing-unit-tests
Imagine choosing two vaccines 💉:
- Vaccine 1 comes with the exact biochemical equations on how it works
- How vaccine 2 works is a mystery, but it has been extensively tested on thousands of people, across diverse populations, with little side effects
Which one would you choose :thinking_face:?
- Ensure functions work as expected 💚 (even if they seem like a black box)
- Prevent bugs 🐛 from popping up over time
- Give us confidence when refactoring ♻️ (i.e. rewriting) code to be more efficient, while keeping the same functionality
Let's start with a simple Python function that adds two numbers:
def add(x, y):
return x + y
Now let's check that this function works on two input numbers. We'll use a testing framework/library called pytest
that allows us to easily check the output using assert
statements.
def test_add():
value = add(x=1.0, y=2.0)
assert value == 3.0
In a Python project using pytest
, we usually structure our code in folders like so:
projectname/
├──__init__.py
├──src/
│ └──calc.py (contains 'add' function)
└──tests/
├──test_calc.py (contains 'test_add' function)
└──__init__.py
The 'test_calc.py' file would contain:
from projectname.src.calc import add
def test_add():
value = add(x=1.0, y=2.0)
assert value == 3.0
Run tests using pytest
By default, pytest
automatically searches for test_*.py
files in the tests
folder, and runs functions that start with a test_
.
cd projectname/ # navigate to project folder
pytest # run tests in tests/test_*.py files
will produce an output like so:
==================== test session starts =====================
platform linux -- Python 3.8.10, pytest-6.2.4
rootdir: /home/user/projectname
collected 1 item
tests/test_calc.py . [100%]
===================== 1 passed in 0.03s ======================
Projects can have >100 tests which take a long time to run. You can also run just one test file instead:
pytest projectname/tests/test_calc.py
Maybe that file has other functions like add/subtract/multiply/divide. You can be even more specific and run just the one that matches a keyword:
pytest -k add projectname/tests/test_calc.py
That's the basics of using pytest
in a nutshell!
PyGMT's testing guidelines
Basics of testing in Python
- https://automationpanda.com/2017/03/14/python-testing-101-pytest
- https://realpython.com/python-testing and https://realpython.com/pytest-python-testing/
Test driven development
- https://realpython.com/courses/test-driven-development-pytest/
- https://dev.to/cheukting_ho/python-zero-to-hero-ep-13-test-driven-development-1g9l