Pytest Testing Idioms
External
Internal
Overview
Test files start with test_
(?)
A function that starts with test
is automatically considered a test to be executed. A function that does NOT start with test
is ignored as test, so if one tries to specifically execute it, they get:
ERROR: not found: /Users/ovidiu/src/.../test_template.py::null_template_variables
A test function can be injected with a test fixture: Available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory.
Tested Code is Supposed to Throw Exception
import pytest
def test_something_that_should_throw_exception():
with pytest.raises(Exception) as info:
my_method()
If the tested code raises a more specific exception, you can use that instead:
def test_something_that_should_throw_exception():
with pytest.raises(ValueError) as info:
my_method()
This tests the exception arguments. ⚠️ In this case, it is very import to place the assert
statements outside the with
block, otherwise they will be silently ignored.
def test_something_that_should_throw_exception():
with pytest.raises(ValueError) as info:
my_method()
# important: interaction with 'info' must take place outside the with block
assert info.value.args[0] == "some message"
assert "some message" in str(info.value)
Also see:
xunit-Style Setup
def setup_function(function):
"""setup any state tied to the execution of the given function.
Invoked for every test function in the module.
'function' is optional.
"""
Path(Path(__file__).parent, './data/tmp').mkdir()
def teardown_function(function):
"""teardown any state that was previously setup with a setup_function
call.
'function' is optional.
"""
shutil.rmtree(str(Path(Path(__file__).parent, './data/tmp/')))
Failing a Test
from _pytest.outcomes import fail
def test_something():
fail("this test failed because I wanted it to")
Mocking
Hierarchical Tests
Find a solution for hierarchical tests for class hierarchies: the test hierarchy should match the class hierarchy and each layer in the hierarchy should test the behavior implemented by its corresponding class hierarchy level. This works well in Java and Junit.
Skipping Tests in Python
from unittest import skip
@skip(reason="TODO 23jLP")
def test_something():
[...]
@pytest.mark.skip(reason="TODO 23jLP")
def test_something():
[...]