The recommended practice for installing dependencies is to create a virtualenv. A virtualenv (https://packaging.python.org/guides/installing-using-pip-and-virtualenv/) acts like a complete separate Python installation from the one that comes with your operating system, making it safe to install the packages required by your application without risk of breaking your system Python or tools.
Now we will learn how to create a virtual environment and install pytest using pip. If you are already familiar with virtualenv and pip, you can skip this section:
Using pytest, all you need to do to start writing tests is to create a new file named test_*.py and write test functions that start with test:
# contents of test_player_mechanics.py
def test_player_hit():
player = create_player()
assert player.health == 100
undead = create_undead()
undead.hit(player)
assert player.health == 80
To execute this test, simply execute pytest, passing the name of the file:
λ pytest test_player_mechanics.py
If you don't pass anything, pytest will look for all of the test files from the current directory recursively and execute them automatically.
You might encounter examples on the internet that use py.test in the command line instead of pytest. The reason for that is historical: pytest used to be part of the py package, which provided several general purpose utilities, including tools that followed the convention of starting with py.<TAB> for tab completion, but since then, it has been moved into its own project. The old py.test command is still available and is an alias to pytest, but the latter is the recommended modern usage.
Note that there's no need to create classes; just simple functions and plain assert statements are enough, but if you want to use classes to group tests you can do so:
class TestMechanics:
def test_player_hit(self):
...
def test_player_health_flask(self):
...
Grouping tests can be useful when you want to put a number of tests under the same scope: you can execute tests based on the class they are in, apply markers to all of the tests in a class (Chapter 3, Markers and Parametrization), and create fixtures bound to a class (Chapter 4, Fixtures).
Pytest can run your tests in a number of ways. Let's quickly get into the basics now and, later on in the chapter, we will move on to more advanced options.
You can start by just simply executing the pytest command:
λ pytest
This will find all of the test_*.py and *_test.py modules in the current directory and below recursively, and will run all of the tests found in those files:
- You can reduce the search to specific directories:
λ pytest tests/core tests/contrib
- You can also mix any number of files and directories:
λ pytest tests/core tests/contrib/test_text_plugin.py
- You can execute specific tests by using the syntax <test-file>::<test-function-name>:
λ pytest tests/core/test_core.py::test_regex_matching
- You can execute all of the test methods of a test class:
λ pytest tests/contrib/test_text_plugin.py::TestPluginHooks
- You can execute a specific test method of a test class using the syntax <test-file>::<test-class>::<test-method-name>:
λ pytest tests/contrib/
test_text_plugin.py::TestPluginHooks::test_registration
The syntax used above is created internally by pytest, is unique to each test collected, and is called a node id or item id. It basically consists of the filename of the testing module, class, and functions joined together by the :: characters.
Pytest will show a more verbose output, which includes node IDs, with the -v flag:
λ pytest tests/core -v
======================== test session starts ========================
...
collected 6 items
tests\core\test_core.py::test_regex_matching PASSED [ 16%]
tests\core\test_core.py::test_check_options FAILED [ 33%]
tests\core\test_core.py::test_type_checking FAILED [ 50%]
tests\core\test_parser.py::test_parse_expr PASSED [ 66%]
tests\core\test_parser.py::test_parse_num PASSED ...