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"
Then in this window you can select the default runner for testing:
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:
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:
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: