|
| 1 | +.. _about-fixtures: |
| 2 | + |
| 3 | +About fixtures |
| 4 | +=============== |
| 5 | + |
| 6 | +.. seealso:: :ref:`how-to-fixtures` |
| 7 | +.. seealso:: :ref:`Fixtures reference <reference-fixtures>` |
| 8 | + |
| 9 | + |
| 10 | +What fixtures are |
| 11 | +----------------- |
| 12 | + |
| 13 | +In testing, a `fixture <https://en.wikipedia.org/wiki/Test_fixture#Software>`_ |
| 14 | +provides a defined, reliable and consistent context for the tests. This could |
| 15 | +include environment (for example a database configured with known parameters) |
| 16 | +or content (such as a dataset). |
| 17 | + |
| 18 | +Fixtures define the steps and data that constitute the *arrange* phase of a |
| 19 | +test (see :ref:`test-anatomy`). In pytest, they are functions you define that |
| 20 | +serve this purpose. They can also be used to define a test's *act* phase; this |
| 21 | +is a powerful technique for designing more complex tests. |
| 22 | + |
| 23 | +The services, state, or other operating environments set up by fixtures are |
| 24 | +accessed by test functions through arguments. For each fixture used by a test |
| 25 | +function there is typically a parameter (named after the fixture) in the test |
| 26 | +function's definition. |
| 27 | + |
| 28 | +We can tell pytest that a particular function is a fixture by decorating it with |
| 29 | +:py:func:`@pytest.fixture <pytest.fixture>`. Here's a simple example of |
| 30 | +what a fixture in pytest might look like: |
| 31 | + |
| 32 | +.. code-block:: python |
| 33 | +
|
| 34 | + import pytest |
| 35 | +
|
| 36 | +
|
| 37 | + class Fruit: |
| 38 | + def __init__(self, name): |
| 39 | + self.name = name |
| 40 | +
|
| 41 | + def __eq__(self, other): |
| 42 | + return self.name == other.name |
| 43 | +
|
| 44 | +
|
| 45 | + @pytest.fixture |
| 46 | + def my_fruit(): |
| 47 | + return Fruit("apple") |
| 48 | +
|
| 49 | +
|
| 50 | + @pytest.fixture |
| 51 | + def fruit_basket(my_fruit): |
| 52 | + return [Fruit("banana"), my_fruit] |
| 53 | +
|
| 54 | +
|
| 55 | + def test_my_fruit_in_basket(my_fruit, fruit_basket): |
| 56 | + assert my_fruit in fruit_basket |
| 57 | +
|
| 58 | +Tests don't have to be limited to a single fixture, either. They can depend on |
| 59 | +as many fixtures as you want, and fixtures can use other fixtures, as well. This |
| 60 | +is where pytest's fixture system really shines. |
| 61 | + |
| 62 | + |
| 63 | +Improvements over xUnit-style setup/teardown functions |
| 64 | +----------------------------------------------------------- |
| 65 | + |
| 66 | +pytest fixtures offer dramatic improvements over the classic xUnit |
| 67 | +style of setup/teardown functions: |
| 68 | + |
| 69 | +* fixtures have explicit names and are activated by declaring their use |
| 70 | + from test functions, modules, classes or whole projects. |
| 71 | + |
| 72 | +* fixtures are implemented in a modular manner, as each fixture name |
| 73 | + triggers a *fixture function* which can itself use other fixtures. |
| 74 | + |
| 75 | +* fixture management scales from simple unit to complex |
| 76 | + functional testing, allowing to parametrize fixtures and tests according |
| 77 | + to configuration and component options, or to re-use fixtures |
| 78 | + across function, class, module or whole test session scopes. |
| 79 | + |
| 80 | +* teardown logic can be easily, and safely managed, no matter how many fixtures |
| 81 | + are used, without the need to carefully handle errors by hand or micromanage |
| 82 | + the order that cleanup steps are added. |
| 83 | + |
| 84 | +In addition, pytest continues to support :ref:`xunitsetup`. You can mix |
| 85 | +both styles, moving incrementally from classic to new style, as you |
| 86 | +prefer. You can also start out from existing :ref:`unittest.TestCase |
| 87 | +style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects. |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | +Fixture errors |
| 92 | +-------------- |
| 93 | + |
| 94 | +pytest does its best to put all the fixtures for a given test in a linear order |
| 95 | +so that it can see which fixture happens first, second, third, and so on. If an |
| 96 | +earlier fixture has a problem, though, and raises an exception, pytest will stop |
| 97 | +executing fixtures for that test and mark the test as having an error. |
| 98 | + |
| 99 | +When a test is marked as having an error, it doesn't mean the test failed, |
| 100 | +though. It just means the test couldn't even be attempted because one of the |
| 101 | +things it depends on had a problem. |
| 102 | + |
| 103 | +This is one reason why it's a good idea to cut out as many unnecessary |
| 104 | +dependencies as possible for a given test. That way a problem in something |
| 105 | +unrelated isn't causing us to have an incomplete picture of what may or may not |
| 106 | +have issues. |
| 107 | + |
| 108 | +Here's a quick example to help explain: |
| 109 | + |
| 110 | +.. code-block:: python |
| 111 | +
|
| 112 | + import pytest |
| 113 | +
|
| 114 | +
|
| 115 | + @pytest.fixture |
| 116 | + def order(): |
| 117 | + return [] |
| 118 | +
|
| 119 | +
|
| 120 | + @pytest.fixture |
| 121 | + def append_first(order): |
| 122 | + order.append(1) |
| 123 | +
|
| 124 | +
|
| 125 | + @pytest.fixture |
| 126 | + def append_second(order, append_first): |
| 127 | + order.extend([2]) |
| 128 | +
|
| 129 | +
|
| 130 | + @pytest.fixture(autouse=True) |
| 131 | + def append_third(order, append_second): |
| 132 | + order += [3] |
| 133 | +
|
| 134 | +
|
| 135 | + def test_order(order): |
| 136 | + assert order == [1, 2, 3] |
| 137 | +
|
| 138 | +
|
| 139 | +If, for whatever reason, ``order.append(1)`` had a bug and it raises an exception, |
| 140 | +we wouldn't be able to know if ``order.extend([2])`` or ``order += [3]`` would |
| 141 | +also have problems. After ``append_first`` throws an exception, pytest won't run |
| 142 | +any more fixtures for ``test_order``, and it won't even try to run |
| 143 | +``test_order`` itself. The only things that would've run would be ``order`` and |
| 144 | +``append_first``. |
| 145 | + |
| 146 | + |
| 147 | +Sharing test data |
| 148 | +----------------- |
| 149 | + |
| 150 | +If you want to make test data from files available to your tests, a good way |
| 151 | +to do this is by loading these data in a fixture for use by your tests. |
| 152 | +This makes use of the automatic caching mechanisms of pytest. |
| 153 | + |
| 154 | +Another good approach is by adding the data files in the ``tests`` folder. |
| 155 | +There are also community plugins available to help managing this aspect of |
| 156 | +testing, e.g. `pytest-datadir <https://pypi.org/project/pytest-datadir/>`__ |
| 157 | +and `pytest-datafiles <https://pypi.org/project/pytest-datafiles/>`__. |
0 commit comments