I want to run additional setup and teardown checks before and after each test in my test suite. I've looked at fixtures but not sure on whether they are the correct approach. I need to run the setup code prior to each test and I need to run the teardown checks after each test.
My use-case is checking for code that doesn't cleanup correctly: it leaves temporary files. In my setup, I will check the files and in the teardown I also check the files. If there are extra files I want the test to fail.
# content of conftest.py def pytest_configure(config): """ Allows plugins and conftest files to perform initial configuration. This hook is called for every plugin and initial conftest file after command line options have been parsed.
pytest is a very robust framework that comes with lots of features. One such feature is the autouse fixtures, a.k.a xUnit setup on steroids. They are a special type of fixture that gets invoked automatically, and its main use case is to act as a setup/teardown function.
conftest.py is where you setup test configurations and store the testcases that are used by test functions. The configurations and the testcases are called fixture in pytest. The test_*. py files are where the actual test functions reside.
py.test fixtures are a technically adequate method to achieve your purpose.
You just need to define a fixture like that:
@pytest.fixture(autouse=True) def run_around_tests(): # Code that will run before your test, for example: files_before = # ... do something to check the existing files # A test function will be run at this point yield # Code that will run after your test, for example: files_after = # ... do something to check the existing files assert files_before == files_after
By declaring your fixture with autouse=True
, it will be automatically invoked for each test function defined in the same module.
That said, there is one caveat. Asserting at setup/teardown is a controversial practice. I'm under the impression that the py.test main authors do not like it (I do not like it either, so that may colour my own perception), so you might run into some problems or rough edges as you go forward.
You can use a fixture
in oder to achieve what you want.
import pytest @pytest.fixture(autouse=True) def run_before_and_after_tests(tmpdir): """Fixture to execute asserts before and after a test is run""" # Setup: fill with any logic you want yield # this is where the testing happens # Teardown : fill with any logic you want
@pytest.fixture(autouse=True)
, from the docs: "Occasionally, you may want to have fixtures get invoked automatically without declaring a function argument explicitly or a usefixtures decorator." Therefore, this fixture will run every time a test is executed.
# Setup: fill with any logic you want
, this logic will be executed before every test is actually run. In your case, you can add your assert statements that will be executed before the actual test.
yield
, as indicated in the comment, this is where testing happens
# Teardown : fill with any logic you want
, this logic will be executed after every test. This logic is guaranteed to run regardless of what happens during the tests.
Note: in pytest
there is a difference between a failing test and an error while executing a test. A Failure indicates that the test failed in some way. An Error indicates that you couldn't get to the point of doing a proper test.
Consider the following examples:
import pytest @pytest.fixture(autouse=True) def run_around_tests(): assert False # This will generate an error when running tests yield assert True def test(): assert True
import pytest @pytest.fixture(autouse=True) def run_around_tests(): assert True yield assert False def test(): assert True
import pytest @pytest.fixture(autouse=True) def run_around_tests(): assert True yield assert True def test(): assert Fail
import pytest @pytest.fixture(autouse=True) def run_around_tests(): assert True yield assert True def test(): assert True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With