Skip to content

Pytest - the basics

What is PyTest?

Pytest is a modern framework for running automated tests in Python. It can be used for unit tests, but it also works very well for creating complex higher-level tests (integration, end-to-end) for entire applications or libraries.

PyTest documentation

Extensive Pytest documentation, with numerous and well-described examples, is available on the official website of the Pytest project - https://docs.pytest.org/en/latest/contents.html

Why PyTest?

  • allows you to write small and easy tests
  • has a multitude of plugins to make testing even easier
  • UnitTest can also be run there
  • we only use the word assert for comparison, and we get very detailed information about the errors
  • we have fixture - dependency injection
  • we have the ability to create markers: pytest.mark.skipif or pytest.mark.xfail
  • we can parameterize tests, reducing the amount of code written
  • automatically discovers test modules, classes, and functions without unnecessary class inheritance

Installation

After switching to your virtualenv, the PyTest library can be installed with the command:

$ pip install pytest

Running tests

Run the pytest for a specific file:

$ pytest test_mymodule.py

Run whatever has special_run in the name

$ pytest -k 'special_run'

Run tests that are decorated with the selected marker_name

$ pytest -m 'marker_name'

First test

Code

We have a function:

def add_numbers(a: int, b: int):
    return a + b

a test for it could look like this:

def test_add_numbers():
    a = 4
    b = 7
    expected = 11

    assert add_numbers(a, b) == expected

In it, we test whether the result of the add_numbers function is as we expect.

We can also, and even should, test less obvious test cases, e.g.:

def test_add_numbers_with_negative_values():
    a = -20
    b = 3
    expected = -17

    assert add_numbers(a, b) == expected

There are several ways to check the expected value, e.g.:

assert result < 5
assert 5 == result
assert result is True
assert result is False or result == 34
assert result
assert result is not 22
assert not result

Running the test

Assuming our file looks like this and is named tests.py :

def add_numbers(a: int, b: int):
    return a + b


def test_add_numbers():
    a = 4
    b = 7
    expected = 11

    assert add_numbers(a, b) == expected


def test_add_numbers_with_negative_values():
    a = -20
    b = 3
    expected = -17

    assert add_numbers(a, b) == expected

we can run the tests with the command

$ pytest tests.py

Which will end with the result:

$ pytest tests.py 
========================== test session starts ===========================
platform linux -- Python 3.7.7, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: /home/mmazurek/testy
collected 2 items                                                                                                                                                                                                                            

tests.py ..                                                         [100%]

=========================== 2 passed in 0.01s ============================

Running tests from PyCharm

Configuration

In the top "File" menu, select "Settings". On the left side select "Tools" and "Python Integrated Tools"

tdd

Then in this window you can select the default runner for testing:

tdd

And click OK.

Launching tests from the Pycharm level

PyCharm recognizes which files contain tests by filename. To work comfortably and efficiently with this tool, let's divide the previous file into two files:

main.py:

def add_numbers(a: int, b: int):
    return a + b

i test_main.py:

from main import add_numbers


def test_add_numbers():
    a = 4
    b = 7
    expected = 11

    assert add_numbers(a, b) == expected


def test_add_numbers_with_negative_values():
    a = -20
    b = 3
    expected = -17

    assert add_numbers(a, b) == expected

What has changed after these treatments is the ability to run individual tests:

tdd

By clicking on the green icon next to the names of the functions that are tests and selecting "Run Pytest for test_main .." you can run a single test. The result will appear at the bottom of the screen:

tdd

If we want to run all the tests from a given file, we can right-click on the * test_main.py * file and select "Run Pytest for test_main ..". The result will also be at the bottom of the screen:

tdd