import pytest
pytest.__path__Disclaimer: this course is adapted from the following sources:
- Python, git & testing by Andreas Müller.
 - VSCode documentation Python testing.
 
Tests
Tests are small pieces of code ensuring that a part of a program is working as expected.
Why tests are useful
This is why we place the uttermost importance on implementing tests along the development steps. It will help you to ensure:
- that code works correctly.
 - that changes do not break anything.
 - that bugs are not reintroduced.
 - robustness to user errors.
 - code is reachable (i.e., it will actually be executed)
 - etc.
 
Types of tests
There are different kinds of tests, with the more important ones being:
- Unit tests: test whether a simple unit element (function, class, etc.) does the right thing.
 - Integration tests: test whether the different parts used by your software work well together.
 - Non-regression tests: test whether a new or modified functionality works correctly and that previous functionalities were not affected (e.g., removing a bug does not alter the rest of the code).
 
How to test?
Many coding languages come with their own test framework. In python, we will focus on pytest. It is simple though powerful. pytest searches for all test*.py files and runs all test* methods found. It outputs a nice error report.
Get the path to pytest binary as follows with python:
This outputs a directory containing the pytest binary, say /path/to/pytest. Then, to add the path containing pytest in your (Linux) system, you have to type the following command in your terminal:
$ export PATH=$PATH:/path/to/pytest
$ pytest --helpExample
Let us assume we have a file inc.py containing
def inc1(x):
    return x + 1
def inc2(x):
    return x + 2Thence, the content of test_inc.py is
from inc import inc1, inc2
# This test will work
def test_inc1():
    assert inc1(3) == 4
# This test will fail
def test_inc2():
    assert inc2(-1) == 4To run these tests:
$ pytest test_inc.pyCode coverage
pytest comes with some useful plugins. In particular, we will use the coverage report plugin.
A test coverage is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs. A program with high test coverage, measured as a percentage, has had more of its source code executed during testing: this suggests it has a lower chance of containing undetected software bugs compared to a program with low test coverage.
To install the coverage plugin simply run the pip command:
$ pip install pytest-covAssuming the inc_cov.py contains:
def inc(x):
    if x < 0:
        return 0
    return x + 1
def dec(x):
     return x - 1and a single test is performed through the file test_inc_cov.py
from inc_cov import inc
def test_inc():
     assert inc(3) == 4then
pytest test_inc_cov.py --cov
============================= test session starts =============================
platform linux -- Python 3.10.10, pytest-7.4.2, pluggy-1.0.0
rootdir: /home/jsalmon/Documents/Mes_cours/Montpellier/HAX712X/Courses/Test
plugins: dash-2.9.3, cov-4.1.0, anyio-3.6.2
collected 1 item
test_inc_cov.py                                                          [100%]
---------- coverage: platform linux, python 3.10.10-final-0 ----------
Name              Stmts   Miss  Cover
-------------------------------------
inc_cov.py            6      2    67%
test_inc_cov.py       3      0   100%
-------------------------------------
TOTAL                 9      2    78%
===============================================================================
1 passed in 0.02s
===============================================================================Two lines in inc_cov module were not used. See
pytest --cov --cov-report=html test_inc_cov.py
============================= test session starts =============================
platform linux -- Python 3.10.10, pytest-7.4.2, pluggy-1.0.0
rootdir: /home/jsalmon/Documents/Mes_cours/Montpellier/HAX712X/Courses/Test
plugins: dash-2.9.3, cov-4.1.0, anyio-3.6.2
collected 1 item
test_inc_cov.py                                                          [100%]
---------- coverage: platform linux, python 3.10.10-final-0 ----------
Coverage HTML written to dir htmlcovfor details.
import hashlib
def md5(fname):
    hash_md5 = hashlib.md5()
    with open(fname, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_md5.update(chunk)
    return hash_md5.hexdigest()By running the following line in the biketrauma/biketrauma location:
pytest --cov-report=html --cov=biketrauma tests/you should reach 79% of code coverage, and the report should look like this (see the htmlcov/index.html file for an interactive report):
---------- coverage: platform linux, python 3.10.10-final-0 ----------
Name                                    Stmts   Miss  Cover
----------------------------------------------------------------------
biketrauma/__init__.py                      4      0   100%
biketrauma/io/Load_db.py                   22      5    77%
biketrauma/io/__init__.py                   3      0   100%
biketrauma/preprocess/__init__.py           0      0   100%
biketrauma/preprocess/get_accident.py       7      0   100%
biketrauma/vis/__init__.py                  0      0   100%
biketrauma/vis/plot_location.py             6      4    33%
----------------------------------------------------------------------
TOTAL                                      42      9    79%