1.. _fixture: 2.. _fixtures: 3.. _`fixture functions`: 4 5pytest fixtures: explicit, modular, scalable 6======================================================== 7 8.. currentmodule:: _pytest.python 9 10.. versionadded:: 2.0/2.3/2.4 11 12.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit 13.. _`purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software 14.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection 15 16The `purpose of test fixtures`_ is to provide a fixed baseline 17upon which tests can reliably and repeatedly execute. pytest fixtures 18offer dramatic improvements over the classic xUnit style of setup/teardown 19functions: 20 21* fixtures have explicit names and are activated by declaring their use 22 from test functions, modules, classes or whole projects. 23 24* fixtures are implemented in a modular manner, as each fixture name 25 triggers a *fixture function* which can itself use other fixtures. 26 27* fixture management scales from simple unit to complex 28 functional testing, allowing to parametrize fixtures and tests according 29 to configuration and component options, or to re-use fixtures 30 across function, class, module or whole test session scopes. 31 32In addition, pytest continues to support :ref:`xunitsetup`. You can mix 33both styles, moving incrementally from classic to new style, as you 34prefer. You can also start out from existing :ref:`unittest.TestCase 35style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects. 36 37 38.. _`funcargs`: 39.. _`funcarg mechanism`: 40.. _`fixture function`: 41.. _`@pytest.fixture`: 42.. _`pytest.fixture`: 43 44Fixtures as Function arguments 45----------------------------------------- 46 47Test functions can receive fixture objects by naming them as an input 48argument. For each argument name, a fixture function with that name provides 49the fixture object. Fixture functions are registered by marking them with 50:py:func:`@pytest.fixture <_pytest.python.fixture>`. Let's look at a simple 51self-contained test module containing a fixture and a test function 52using it:: 53 54 # content of ./test_smtpsimple.py 55 import pytest 56 57 @pytest.fixture 58 def smtp(): 59 import smtplib 60 return smtplib.SMTP("smtp.gmail.com", 587, timeout=5) 61 62 def test_ehlo(smtp): 63 response, msg = smtp.ehlo() 64 assert response == 250 65 assert 0 # for demo purposes 66 67Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest 68will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>` 69marked ``smtp`` fixture function. Running the test looks like this:: 70 71 $ pytest test_smtpsimple.py 72 =========================== test session starts ============================ 73 platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y 74 rootdir: $REGENDOC_TMPDIR, inifile: 75 collected 1 item 76 77 test_smtpsimple.py F [100%] 78 79 ================================= FAILURES ================================= 80 ________________________________ test_ehlo _________________________________ 81 82 smtp = <smtplib.SMTP object at 0xdeadbeef> 83 84 def test_ehlo(smtp): 85 response, msg = smtp.ehlo() 86 assert response == 250 87 > assert 0 # for demo purposes 88 E assert 0 89 90 test_smtpsimple.py:11: AssertionError 91 ========================= 1 failed in 0.12 seconds ========================= 92 93In the failure traceback we see that the test function was called with a 94``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture 95function. The test function fails on our deliberate ``assert 0``. Here is 96the exact protocol used by ``pytest`` to call the test function this way: 97 981. pytest :ref:`finds <test discovery>` the ``test_ehlo`` because 99 of the ``test_`` prefix. The test function needs a function argument 100 named ``smtp``. A matching fixture function is discovered by 101 looking for a fixture-marked function named ``smtp``. 102 1032. ``smtp()`` is called to create an instance. 104 1053. ``test_ehlo(<SMTP instance>)`` is called and fails in the last 106 line of the test function. 107 108Note that if you misspell a function argument or want 109to use one that isn't available, you'll see an error 110with a list of available function arguments. 111 112.. note:: 113 114 You can always issue :: 115 116 pytest --fixtures test_simplefactory.py 117 118 to see available fixtures (fixtures with leading ``_`` are only shown if you add the ``-v`` option). 119 120Fixtures: a prime example of dependency injection 121--------------------------------------------------- 122 123Fixtures allow test functions to easily receive and work 124against specific pre-initialized application objects without having 125to care about import/setup/cleanup details. 126It's a prime example of `dependency injection`_ where fixture 127functions take the role of the *injector* and test functions are the 128*consumers* of fixture objects. 129 130.. _`conftest.py`: 131.. _`conftest`: 132 133``conftest.py``: sharing fixture functions 134------------------------------------------ 135 136If during implementing your tests you realize that you 137want to use a fixture function from multiple test files you can move it 138to a ``conftest.py`` file. 139You don't need to import the fixture you want to use in a test, it 140automatically gets discovered by pytest. The discovery of 141fixture functions starts at test classes, then test modules, then 142``conftest.py`` files and finally builtin and third party plugins. 143 144You can also use the ``conftest.py`` file to implement 145:ref:`local per-directory plugins <conftest.py plugins>`. 146 147Sharing test data 148----------------- 149 150If you want to make test data from files available to your tests, a good way 151to do this is by loading these data in a fixture for use by your tests. 152This makes use of the automatic caching mechanisms of pytest. 153 154Another good approach is by adding the data files in the ``tests`` folder. 155There are also community plugins available to help managing this aspect of 156testing, e.g. `pytest-datadir <https://github.com/gabrielcnr/pytest-datadir>`__ 157and `pytest-datafiles <https://pypi.python.org/pypi/pytest-datafiles>`__. 158 159.. _smtpshared: 160 161Scope: sharing a fixture instance across tests in a class, module or session 162---------------------------------------------------------------------------- 163 164.. regendoc:wipe 165 166Fixtures requiring network access depend on connectivity and are 167usually time-expensive to create. Extending the previous example, we 168can add a ``scope="module"`` parameter to the 169:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation 170to cause the decorated ``smtp`` fixture function to only be invoked once 171per test *module* (the default is to invoke once per test *function*). 172Multiple test functions in a test module will thus 173each receive the same ``smtp`` fixture instance, thus saving time. 174 175The next example puts the fixture function into a separate ``conftest.py`` file 176so that tests from multiple test modules in the directory can 177access the fixture function:: 178 179 # content of conftest.py 180 import pytest 181 import smtplib 182 183 @pytest.fixture(scope="module") 184 def smtp(): 185 return smtplib.SMTP("smtp.gmail.com", 587, timeout=5) 186 187The name of the fixture again is ``smtp`` and you can access its result by 188listing the name ``smtp`` as an input parameter in any test or fixture 189function (in or below the directory where ``conftest.py`` is located):: 190 191 # content of test_module.py 192 193 def test_ehlo(smtp): 194 response, msg = smtp.ehlo() 195 assert response == 250 196 assert b"smtp.gmail.com" in msg 197 assert 0 # for demo purposes 198 199 def test_noop(smtp): 200 response, msg = smtp.noop() 201 assert response == 250 202 assert 0 # for demo purposes 203 204We deliberately insert failing ``assert 0`` statements in order to 205inspect what is going on and can now run the tests:: 206 207 $ pytest test_module.py 208 =========================== test session starts ============================ 209 platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y 210 rootdir: $REGENDOC_TMPDIR, inifile: 211 collected 2 items 212 213 test_module.py FF [100%] 214 215 ================================= FAILURES ================================= 216 ________________________________ test_ehlo _________________________________ 217 218 smtp = <smtplib.SMTP object at 0xdeadbeef> 219 220 def test_ehlo(smtp): 221 response, msg = smtp.ehlo() 222 assert response == 250 223 assert b"smtp.gmail.com" in msg 224 > assert 0 # for demo purposes 225 E assert 0 226 227 test_module.py:6: AssertionError 228 ________________________________ test_noop _________________________________ 229 230 smtp = <smtplib.SMTP object at 0xdeadbeef> 231 232 def test_noop(smtp): 233 response, msg = smtp.noop() 234 assert response == 250 235 > assert 0 # for demo purposes 236 E assert 0 237 238 test_module.py:11: AssertionError 239 ========================= 2 failed in 0.12 seconds ========================= 240 241You see the two ``assert 0`` failing and more importantly you can also see 242that the same (module-scoped) ``smtp`` object was passed into the two 243test functions because pytest shows the incoming argument values in the 244traceback. As a result, the two test functions using ``smtp`` run as 245quick as a single one because they reuse the same instance. 246 247If you decide that you rather want to have a session-scoped ``smtp`` 248instance, you can simply declare it: 249 250.. code-block:: python 251 252 @pytest.fixture(scope="session") 253 def smtp(): 254 # the returned fixture value will be shared for 255 # all tests needing it 256 ... 257 258Finally, the ``class`` scope will invoke the fixture once per test *class*. 259 260 261Higher-scoped fixtures are instantiated first 262--------------------------------------------- 263 264.. versionadded:: 3.5 265 266Within a function request for features, fixture of higher-scopes (such as ``session``) are instantiated first than 267lower-scoped fixtures (such as ``function`` or ``class``). The relative order of fixtures of same scope follows 268the declared order in the test function and honours dependencies between fixtures. 269 270Consider the code below: 271 272.. code-block:: python 273 274 @pytest.fixture(scope="session") 275 def s1(): 276 pass 277 278 279 @pytest.fixture(scope="module") 280 def m1(): 281 pass 282 283 284 @pytest.fixture 285 def f1(tmpdir): 286 pass 287 288 289 @pytest.fixture 290 def f2(): 291 pass 292 293 294 def test_foo(f1, m1, f2, s1): 295 ... 296 297 298The fixtures requested by ``test_foo`` will be instantiated in the following order: 299 3001. ``s1``: is the highest-scoped fixture (``session``). 3012. ``m1``: is the second highest-scoped fixture (``module``). 3023. ``tmpdir``: is a ``function``-scoped fixture, required by ``f1``: it needs to be instantiated at this point 303 because it is a dependency of ``f1``. 3044. ``f1``: is the first ``function``-scoped fixture in ``test_foo`` parameter list. 3055. ``f2``: is the last ``function``-scoped fixture in ``test_foo`` parameter list. 306 307 308.. _`finalization`: 309 310Fixture finalization / executing teardown code 311------------------------------------------------------------- 312 313pytest supports execution of fixture specific finalization code 314when the fixture goes out of scope. By using a ``yield`` statement instead of ``return``, all 315the code after the *yield* statement serves as the teardown code: 316 317.. code-block:: python 318 319 # content of conftest.py 320 321 import smtplib 322 import pytest 323 324 325 @pytest.fixture(scope="module") 326 def smtp(): 327 smtp = smtplib.SMTP("smtp.gmail.com", 587, timeout=5) 328 yield smtp # provide the fixture value 329 print("teardown smtp") 330 smtp.close() 331 332The ``print`` and ``smtp.close()`` statements will execute when the last test in 333the module has finished execution, regardless of the exception status of the 334tests. 335 336Let's execute it:: 337 338 $ pytest -s -q --tb=no 339 FFteardown smtp 340 341 2 failed in 0.12 seconds 342 343We see that the ``smtp`` instance is finalized after the two 344tests finished execution. Note that if we decorated our fixture 345function with ``scope='function'`` then fixture setup and cleanup would 346occur around each single test. In either case the test 347module itself does not need to change or know about these details 348of fixture setup. 349 350Note that we can also seamlessly use the ``yield`` syntax with ``with`` statements: 351 352.. code-block:: python 353 354 # content of test_yield2.py 355 356 import smtplib 357 import pytest 358 359 360 @pytest.fixture(scope="module") 361 def smtp(): 362 with smtplib.SMTP("smtp.gmail.com", 587, timeout=5) as smtp: 363 yield smtp # provide the fixture value 364 365 366The ``smtp`` connection will be closed after the test finished execution 367because the ``smtp`` object automatically closes when 368the ``with`` statement ends. 369 370Note that if an exception happens during the *setup* code (before the ``yield`` keyword), the 371*teardown* code (after the ``yield``) will not be called. 372 373An alternative option for executing *teardown* code is to 374make use of the ``addfinalizer`` method of the `request-context`_ object to register 375finalization functions. 376 377Here's the ``smtp`` fixture changed to use ``addfinalizer`` for cleanup: 378 379.. code-block:: python 380 381 # content of conftest.py 382 import smtplib 383 import pytest 384 385 386 @pytest.fixture(scope="module") 387 def smtp(request): 388 smtp = smtplib.SMTP("smtp.gmail.com", 587, timeout=5) 389 390 def fin(): 391 print("teardown smtp") 392 smtp.close() 393 394 request.addfinalizer(fin) 395 return smtp # provide the fixture value 396 397 398Both ``yield`` and ``addfinalizer`` methods work similarly by calling their code after the test 399ends, but ``addfinalizer`` has two key differences over ``yield``: 400 4011. It is possible to register multiple finalizer functions. 402 4032. Finalizers will always be called regardless if the fixture *setup* code raises an exception. 404 This is handy to properly close all resources created by a fixture even if one of them 405 fails to be created/acquired:: 406 407 @pytest.fixture 408 def equipments(request): 409 r = [] 410 for port in ('C1', 'C3', 'C28'): 411 equip = connect(port) 412 request.addfinalizer(equip.disconnect) 413 r.append(equip) 414 return r 415 416 In the example above, if ``"C28"`` fails with an exception, ``"C1"`` and ``"C3"`` will still 417 be properly closed. Of course, if an exception happens before the finalize function is 418 registered then it will not be executed. 419 420 421.. _`request-context`: 422 423Fixtures can introspect the requesting test context 424------------------------------------------------------------- 425 426Fixture functions can accept the :py:class:`request <FixtureRequest>` object 427to introspect the "requesting" test function, class or module context. 428Further extending the previous ``smtp`` fixture example, let's 429read an optional server URL from the test module which uses our fixture:: 430 431 # content of conftest.py 432 import pytest 433 import smtplib 434 435 @pytest.fixture(scope="module") 436 def smtp(request): 437 server = getattr(request.module, "smtpserver", "smtp.gmail.com") 438 smtp = smtplib.SMTP(server, 587, timeout=5) 439 yield smtp 440 print ("finalizing %s (%s)" % (smtp, server)) 441 smtp.close() 442 443We use the ``request.module`` attribute to optionally obtain an 444``smtpserver`` attribute from the test module. If we just execute 445again, nothing much has changed:: 446 447 $ pytest -s -q --tb=no 448 FFfinalizing <smtplib.SMTP object at 0xdeadbeef> (smtp.gmail.com) 449 450 2 failed in 0.12 seconds 451 452Let's quickly create another test module that actually sets the 453server URL in its module namespace:: 454 455 # content of test_anothersmtp.py 456 457 smtpserver = "mail.python.org" # will be read by smtp fixture 458 459 def test_showhelo(smtp): 460 assert 0, smtp.helo() 461 462Running it:: 463 464 $ pytest -qq --tb=short test_anothersmtp.py 465 F [100%] 466 ================================= FAILURES ================================= 467 ______________________________ test_showhelo _______________________________ 468 test_anothersmtp.py:5: in test_showhelo 469 assert 0, smtp.helo() 470 E AssertionError: (250, b'mail.python.org') 471 E assert 0 472 ------------------------- Captured stdout teardown ------------------------- 473 finalizing <smtplib.SMTP object at 0xdeadbeef> (mail.python.org) 474 475voila! The ``smtp`` fixture function picked up our mail server name 476from the module namespace. 477 478.. _`fixture-factory`: 479 480Factories as fixtures 481------------------------------------------------------------- 482 483The "factory as fixture" pattern can help in situations where the result 484of a fixture is needed multiple times in a single test. Instead of returning 485data directly, the fixture instead returns a function which generates the data. 486This function can then be called multiple times in the test. 487 488Factories can have have parameters as needed:: 489 490 @pytest.fixture 491 def make_customer_record(): 492 493 def _make_customer_record(name): 494 return { 495 "name": name, 496 "orders": [] 497 } 498 499 return _make_customer_record 500 501 502 def test_customer_records(make_customer_record): 503 customer_1 = make_customer_record("Lisa") 504 customer_2 = make_customer_record("Mike") 505 customer_3 = make_customer_record("Meredith") 506 507If the data created by the factory requires managing, the fixture can take care of that:: 508 509 @pytest.fixture 510 def make_customer_record(): 511 512 created_records = [] 513 514 def _make_customer_record(name): 515 record = models.Customer(name=name, orders=[]) 516 created_records.append(record) 517 return record 518 519 yield _make_customer_record 520 521 for record in created_records: 522 record.destroy() 523 524 525 def test_customer_records(make_customer_record): 526 customer_1 = make_customer_record("Lisa") 527 customer_2 = make_customer_record("Mike") 528 customer_3 = make_customer_record("Meredith") 529 530 531.. _`fixture-parametrize`: 532 533Parametrizing fixtures 534----------------------------------------------------------------- 535 536Fixture functions can be parametrized in which case they will be called 537multiple times, each time executing the set of dependent tests, i. e. the 538tests that depend on this fixture. Test functions do usually not need 539to be aware of their re-running. Fixture parametrization helps to 540write exhaustive functional tests for components which themselves can be 541configured in multiple ways. 542 543Extending the previous example, we can flag the fixture to create two 544``smtp`` fixture instances which will cause all tests using the fixture 545to run twice. The fixture function gets access to each parameter 546through the special :py:class:`request <FixtureRequest>` object:: 547 548 # content of conftest.py 549 import pytest 550 import smtplib 551 552 @pytest.fixture(scope="module", 553 params=["smtp.gmail.com", "mail.python.org"]) 554 def smtp(request): 555 smtp = smtplib.SMTP(request.param, 587, timeout=5) 556 yield smtp 557 print ("finalizing %s" % smtp) 558 smtp.close() 559 560The main change is the declaration of ``params`` with 561:py:func:`@pytest.fixture <_pytest.python.fixture>`, a list of values 562for each of which the fixture function will execute and can access 563a value via ``request.param``. No test function code needs to change. 564So let's just do another run:: 565 566 $ pytest -q test_module.py 567 FFFF [100%] 568 ================================= FAILURES ================================= 569 ________________________ test_ehlo[smtp.gmail.com] _________________________ 570 571 smtp = <smtplib.SMTP object at 0xdeadbeef> 572 573 def test_ehlo(smtp): 574 response, msg = smtp.ehlo() 575 assert response == 250 576 assert b"smtp.gmail.com" in msg 577 > assert 0 # for demo purposes 578 E assert 0 579 580 test_module.py:6: AssertionError 581 ________________________ test_noop[smtp.gmail.com] _________________________ 582 583 smtp = <smtplib.SMTP object at 0xdeadbeef> 584 585 def test_noop(smtp): 586 response, msg = smtp.noop() 587 assert response == 250 588 > assert 0 # for demo purposes 589 E assert 0 590 591 test_module.py:11: AssertionError 592 ________________________ test_ehlo[mail.python.org] ________________________ 593 594 smtp = <smtplib.SMTP object at 0xdeadbeef> 595 596 def test_ehlo(smtp): 597 response, msg = smtp.ehlo() 598 assert response == 250 599 > assert b"smtp.gmail.com" in msg 600 E AssertionError: assert b'smtp.gmail.com' in b'mail.python.org\nPIPELINING\nSIZE 51200000\nETRN\nSTARTTLS\nAUTH DIGEST-MD5 NTLM CRAM-MD5\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8' 601 602 test_module.py:5: AssertionError 603 -------------------------- Captured stdout setup --------------------------- 604 finalizing <smtplib.SMTP object at 0xdeadbeef> 605 ________________________ test_noop[mail.python.org] ________________________ 606 607 smtp = <smtplib.SMTP object at 0xdeadbeef> 608 609 def test_noop(smtp): 610 response, msg = smtp.noop() 611 assert response == 250 612 > assert 0 # for demo purposes 613 E assert 0 614 615 test_module.py:11: AssertionError 616 ------------------------- Captured stdout teardown ------------------------- 617 finalizing <smtplib.SMTP object at 0xdeadbeef> 618 4 failed in 0.12 seconds 619 620We see that our two test functions each ran twice, against the different 621``smtp`` instances. Note also, that with the ``mail.python.org`` 622connection the second test fails in ``test_ehlo`` because a 623different server string is expected than what arrived. 624 625pytest will build a string that is the test ID for each fixture value 626in a parametrized fixture, e.g. ``test_ehlo[smtp.gmail.com]`` and 627``test_ehlo[mail.python.org]`` in the above examples. These IDs can 628be used with ``-k`` to select specific cases to run, and they will 629also identify the specific case when one is failing. Running pytest 630with ``--collect-only`` will show the generated IDs. 631 632Numbers, strings, booleans and None will have their usual string 633representation used in the test ID. For other objects, pytest will 634make a string based on the argument name. It is possible to customise 635the string used in a test ID for a certain fixture value by using the 636``ids`` keyword argument:: 637 638 # content of test_ids.py 639 import pytest 640 641 @pytest.fixture(params=[0, 1], ids=["spam", "ham"]) 642 def a(request): 643 return request.param 644 645 def test_a(a): 646 pass 647 648 def idfn(fixture_value): 649 if fixture_value == 0: 650 return "eggs" 651 else: 652 return None 653 654 @pytest.fixture(params=[0, 1], ids=idfn) 655 def b(request): 656 return request.param 657 658 def test_b(b): 659 pass 660 661The above shows how ``ids`` can be either a list of strings to use or 662a function which will be called with the fixture value and then 663has to return a string to use. In the latter case if the function 664return ``None`` then pytest's auto-generated ID will be used. 665 666Running the above tests results in the following test IDs being used:: 667 668 $ pytest --collect-only 669 =========================== test session starts ============================ 670 platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y 671 rootdir: $REGENDOC_TMPDIR, inifile: 672 collected 10 items 673 <Module 'test_anothersmtp.py'> 674 <Function 'test_showhelo[smtp.gmail.com]'> 675 <Function 'test_showhelo[mail.python.org]'> 676 <Module 'test_ids.py'> 677 <Function 'test_a[spam]'> 678 <Function 'test_a[ham]'> 679 <Function 'test_b[eggs]'> 680 <Function 'test_b[1]'> 681 <Module 'test_module.py'> 682 <Function 'test_ehlo[smtp.gmail.com]'> 683 <Function 'test_noop[smtp.gmail.com]'> 684 <Function 'test_ehlo[mail.python.org]'> 685 <Function 'test_noop[mail.python.org]'> 686 687 ======================= no tests ran in 0.12 seconds ======================= 688 689.. _`fixture-parametrize-marks`: 690 691Using marks with parametrized fixtures 692-------------------------------------- 693 694:func:`pytest.param` can be used to apply marks in values sets of parametrized fixtures in the same way 695that they can be used with :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>`. 696 697Example:: 698 699 # content of test_fixture_marks.py 700 import pytest 701 @pytest.fixture(params=[0, 1, pytest.param(2, marks=pytest.mark.skip)]) 702 def data_set(request): 703 return request.param 704 705 def test_data(data_set): 706 pass 707 708Running this test will *skip* the invocation of ``data_set`` with value ``2``:: 709 710 $ pytest test_fixture_marks.py -v 711 =========================== test session starts ============================ 712 platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5 713 cachedir: .pytest_cache 714 rootdir: $REGENDOC_TMPDIR, inifile: 715 collecting ... collected 3 items 716 717 test_fixture_marks.py::test_data[0] PASSED [ 33%] 718 test_fixture_marks.py::test_data[1] PASSED [ 66%] 719 test_fixture_marks.py::test_data[2] SKIPPED [100%] 720 721 =================== 2 passed, 1 skipped in 0.12 seconds ==================== 722 723.. _`interdependent fixtures`: 724 725Modularity: using fixtures from a fixture function 726---------------------------------------------------------- 727 728You can not only use fixtures in test functions but fixture functions 729can use other fixtures themselves. This contributes to a modular design 730of your fixtures and allows re-use of framework-specific fixtures across 731many projects. As a simple example, we can extend the previous example 732and instantiate an object ``app`` where we stick the already defined 733``smtp`` resource into it:: 734 735 # content of test_appsetup.py 736 737 import pytest 738 739 class App(object): 740 def __init__(self, smtp): 741 self.smtp = smtp 742 743 @pytest.fixture(scope="module") 744 def app(smtp): 745 return App(smtp) 746 747 def test_smtp_exists(app): 748 assert app.smtp 749 750Here we declare an ``app`` fixture which receives the previously defined 751``smtp`` fixture and instantiates an ``App`` object with it. Let's run it:: 752 753 $ pytest -v test_appsetup.py 754 =========================== test session starts ============================ 755 platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5 756 cachedir: .pytest_cache 757 rootdir: $REGENDOC_TMPDIR, inifile: 758 collecting ... collected 2 items 759 760 test_appsetup.py::test_smtp_exists[smtp.gmail.com] PASSED [ 50%] 761 test_appsetup.py::test_smtp_exists[mail.python.org] PASSED [100%] 762 763 ========================= 2 passed in 0.12 seconds ========================= 764 765Due to the parametrization of ``smtp`` the test will run twice with two 766different ``App`` instances and respective smtp servers. There is no 767need for the ``app`` fixture to be aware of the ``smtp`` parametrization 768as pytest will fully analyse the fixture dependency graph. 769 770Note, that the ``app`` fixture has a scope of ``module`` and uses a 771module-scoped ``smtp`` fixture. The example would still work if ``smtp`` 772was cached on a ``session`` scope: it is fine for fixtures to use 773"broader" scoped fixtures but not the other way round: 774A session-scoped fixture could not use a module-scoped one in a 775meaningful way. 776 777 778.. _`automatic per-resource grouping`: 779 780Automatic grouping of tests by fixture instances 781---------------------------------------------------------- 782 783.. regendoc: wipe 784 785pytest minimizes the number of active fixtures during test runs. 786If you have a parametrized fixture, then all the tests using it will 787first execute with one instance and then finalizers are called 788before the next fixture instance is created. Among other things, 789this eases testing of applications which create and use global state. 790 791The following example uses two parametrized fixture, one of which is 792scoped on a per-module basis, and all the functions perform ``print`` calls 793to show the setup/teardown flow:: 794 795 # content of test_module.py 796 import pytest 797 798 @pytest.fixture(scope="module", params=["mod1", "mod2"]) 799 def modarg(request): 800 param = request.param 801 print (" SETUP modarg %s" % param) 802 yield param 803 print (" TEARDOWN modarg %s" % param) 804 805 @pytest.fixture(scope="function", params=[1,2]) 806 def otherarg(request): 807 param = request.param 808 print (" SETUP otherarg %s" % param) 809 yield param 810 print (" TEARDOWN otherarg %s" % param) 811 812 def test_0(otherarg): 813 print (" RUN test0 with otherarg %s" % otherarg) 814 def test_1(modarg): 815 print (" RUN test1 with modarg %s" % modarg) 816 def test_2(otherarg, modarg): 817 print (" RUN test2 with otherarg %s and modarg %s" % (otherarg, modarg)) 818 819 820Let's run the tests in verbose mode and with looking at the print-output:: 821 822 $ pytest -v -s test_module.py 823 =========================== test session starts ============================ 824 platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5 825 cachedir: .pytest_cache 826 rootdir: $REGENDOC_TMPDIR, inifile: 827 collecting ... collected 8 items 828 829 test_module.py::test_0[1] SETUP otherarg 1 830 RUN test0 with otherarg 1 831 PASSED TEARDOWN otherarg 1 832 833 test_module.py::test_0[2] SETUP otherarg 2 834 RUN test0 with otherarg 2 835 PASSED TEARDOWN otherarg 2 836 837 test_module.py::test_1[mod1] SETUP modarg mod1 838 RUN test1 with modarg mod1 839 PASSED 840 test_module.py::test_2[mod1-1] SETUP otherarg 1 841 RUN test2 with otherarg 1 and modarg mod1 842 PASSED TEARDOWN otherarg 1 843 844 test_module.py::test_2[mod1-2] SETUP otherarg 2 845 RUN test2 with otherarg 2 and modarg mod1 846 PASSED TEARDOWN otherarg 2 847 848 test_module.py::test_1[mod2] TEARDOWN modarg mod1 849 SETUP modarg mod2 850 RUN test1 with modarg mod2 851 PASSED 852 test_module.py::test_2[mod2-1] SETUP otherarg 1 853 RUN test2 with otherarg 1 and modarg mod2 854 PASSED TEARDOWN otherarg 1 855 856 test_module.py::test_2[mod2-2] SETUP otherarg 2 857 RUN test2 with otherarg 2 and modarg mod2 858 PASSED TEARDOWN otherarg 2 859 TEARDOWN modarg mod2 860 861 862 ========================= 8 passed in 0.12 seconds ========================= 863 864You can see that the parametrized module-scoped ``modarg`` resource caused an 865ordering of test execution that lead to the fewest possible "active" resources. 866The finalizer for the ``mod1`` parametrized resource was executed before the 867``mod2`` resource was setup. 868 869In particular notice that test_0 is completely independent and finishes first. 870Then test_1 is executed with ``mod1``, then test_2 with ``mod1``, then test_1 871with ``mod2`` and finally test_2 with ``mod2``. 872 873The ``otherarg`` parametrized resource (having function scope) was set up before 874and teared down after every test that used it. 875 876 877.. _`usefixtures`: 878 879Using fixtures from classes, modules or projects 880---------------------------------------------------------------------- 881 882.. regendoc:wipe 883 884Sometimes test functions do not directly need access to a fixture object. 885For example, tests may require to operate with an empty directory as the 886current working directory but otherwise do not care for the concrete 887directory. Here is how you can use the standard `tempfile 888<http://docs.python.org/library/tempfile.html>`_ and pytest fixtures to 889achieve it. We separate the creation of the fixture into a conftest.py 890file:: 891 892 # content of conftest.py 893 894 import pytest 895 import tempfile 896 import os 897 898 @pytest.fixture() 899 def cleandir(): 900 newpath = tempfile.mkdtemp() 901 os.chdir(newpath) 902 903and declare its use in a test module via a ``usefixtures`` marker:: 904 905 # content of test_setenv.py 906 import os 907 import pytest 908 909 @pytest.mark.usefixtures("cleandir") 910 class TestDirectoryInit(object): 911 def test_cwd_starts_empty(self): 912 assert os.listdir(os.getcwd()) == [] 913 with open("myfile", "w") as f: 914 f.write("hello") 915 916 def test_cwd_again_starts_empty(self): 917 assert os.listdir(os.getcwd()) == [] 918 919Due to the ``usefixtures`` marker, the ``cleandir`` fixture 920will be required for the execution of each test method, just as if 921you specified a "cleandir" function argument to each of them. Let's run it 922to verify our fixture is activated and the tests pass:: 923 924 $ pytest -q 925 .. [100%] 926 2 passed in 0.12 seconds 927 928You can specify multiple fixtures like this: 929 930.. code-block:: python 931 932 @pytest.mark.usefixtures("cleandir", "anotherfixture") 933 def test(): 934 ... 935 936and you may specify fixture usage at the test module level, using 937a generic feature of the mark mechanism: 938 939.. code-block:: python 940 941 pytestmark = pytest.mark.usefixtures("cleandir") 942 943Note that the assigned variable *must* be called ``pytestmark``, assigning e.g. 944``foomark`` will not activate the fixtures. 945 946Lastly you can put fixtures required by all tests in your project 947into an ini-file: 948 949.. code-block:: ini 950 951 # content of pytest.ini 952 [pytest] 953 usefixtures = cleandir 954 955 956.. _`autouse`: 957.. _`autouse fixtures`: 958 959Autouse fixtures (xUnit setup on steroids) 960---------------------------------------------------------------------- 961 962.. regendoc:wipe 963 964Occasionally, you may want to have fixtures get invoked automatically 965without declaring a function argument explicitly or a `usefixtures`_ decorator. 966As a practical example, suppose we have a database fixture which has a 967begin/rollback/commit architecture and we want to automatically surround 968each test method by a transaction and a rollback. Here is a dummy 969self-contained implementation of this idea:: 970 971 # content of test_db_transact.py 972 973 import pytest 974 975 class DB(object): 976 def __init__(self): 977 self.intransaction = [] 978 def begin(self, name): 979 self.intransaction.append(name) 980 def rollback(self): 981 self.intransaction.pop() 982 983 @pytest.fixture(scope="module") 984 def db(): 985 return DB() 986 987 class TestClass(object): 988 @pytest.fixture(autouse=True) 989 def transact(self, request, db): 990 db.begin(request.function.__name__) 991 yield 992 db.rollback() 993 994 def test_method1(self, db): 995 assert db.intransaction == ["test_method1"] 996 997 def test_method2(self, db): 998 assert db.intransaction == ["test_method2"] 999 1000The class-level ``transact`` fixture is marked with *autouse=true* 1001which implies that all test methods in the class will use this fixture 1002without a need to state it in the test function signature or with a 1003class-level ``usefixtures`` decorator. 1004 1005If we run it, we get two passing tests:: 1006 1007 $ pytest -q 1008 .. [100%] 1009 2 passed in 0.12 seconds 1010 1011Here is how autouse fixtures work in other scopes: 1012 1013- autouse fixtures obey the ``scope=`` keyword-argument: if an autouse fixture 1014 has ``scope='session'`` it will only be run once, no matter where it is 1015 defined. ``scope='class'`` means it will be run once per class, etc. 1016 1017- if an autouse fixture is defined in a test module, all its test 1018 functions automatically use it. 1019 1020- if an autouse fixture is defined in a conftest.py file then all tests in 1021 all test modules below its directory will invoke the fixture. 1022 1023- lastly, and **please use that with care**: if you define an autouse 1024 fixture in a plugin, it will be invoked for all tests in all projects 1025 where the plugin is installed. This can be useful if a fixture only 1026 anyway works in the presence of certain settings e. g. in the ini-file. Such 1027 a global fixture should always quickly determine if it should do 1028 any work and avoid otherwise expensive imports or computation. 1029 1030Note that the above ``transact`` fixture may very well be a fixture that 1031you want to make available in your project without having it generally 1032active. The canonical way to do that is to put the transact definition 1033into a conftest.py file **without** using ``autouse``:: 1034 1035 # content of conftest.py 1036 @pytest.fixture 1037 def transact(request, db): 1038 db.begin() 1039 yield 1040 db.rollback() 1041 1042and then e.g. have a TestClass using it by declaring the need:: 1043 1044 @pytest.mark.usefixtures("transact") 1045 class TestClass(object): 1046 def test_method1(self): 1047 ... 1048 1049All test methods in this TestClass will use the transaction fixture while 1050other test classes or functions in the module will not use it unless 1051they also add a ``transact`` reference. 1052 1053Overriding fixtures on various levels 1054------------------------------------- 1055 1056In relatively large test suite, you most likely need to ``override`` a ``global`` or ``root`` fixture with a ``locally`` 1057defined one, keeping the test code readable and maintainable. 1058 1059Override a fixture on a folder (conftest) level 1060^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1061 1062Given the tests file structure is: 1063 1064:: 1065 1066 tests/ 1067 __init__.py 1068 1069 conftest.py 1070 # content of tests/conftest.py 1071 import pytest 1072 1073 @pytest.fixture 1074 def username(): 1075 return 'username' 1076 1077 test_something.py 1078 # content of tests/test_something.py 1079 def test_username(username): 1080 assert username == 'username' 1081 1082 subfolder/ 1083 __init__.py 1084 1085 conftest.py 1086 # content of tests/subfolder/conftest.py 1087 import pytest 1088 1089 @pytest.fixture 1090 def username(username): 1091 return 'overridden-' + username 1092 1093 test_something.py 1094 # content of tests/subfolder/test_something.py 1095 def test_username(username): 1096 assert username == 'overridden-username' 1097 1098As you can see, a fixture with the same name can be overridden for certain test folder level. 1099Note that the ``base`` or ``super`` fixture can be accessed from the ``overriding`` 1100fixture easily - used in the example above. 1101 1102Override a fixture on a test module level 1103^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1104 1105Given the tests file structure is: 1106 1107:: 1108 1109 tests/ 1110 __init__.py 1111 1112 conftest.py 1113 # content of tests/conftest.py 1114 @pytest.fixture 1115 def username(): 1116 return 'username' 1117 1118 test_something.py 1119 # content of tests/test_something.py 1120 import pytest 1121 1122 @pytest.fixture 1123 def username(username): 1124 return 'overridden-' + username 1125 1126 def test_username(username): 1127 assert username == 'overridden-username' 1128 1129 test_something_else.py 1130 # content of tests/test_something_else.py 1131 import pytest 1132 1133 @pytest.fixture 1134 def username(username): 1135 return 'overridden-else-' + username 1136 1137 def test_username(username): 1138 assert username == 'overridden-else-username' 1139 1140In the example above, a fixture with the same name can be overridden for certain test module. 1141 1142 1143Override a fixture with direct test parametrization 1144^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1145 1146Given the tests file structure is: 1147 1148:: 1149 1150 tests/ 1151 __init__.py 1152 1153 conftest.py 1154 # content of tests/conftest.py 1155 import pytest 1156 1157 @pytest.fixture 1158 def username(): 1159 return 'username' 1160 1161 @pytest.fixture 1162 def other_username(username): 1163 return 'other-' + username 1164 1165 test_something.py 1166 # content of tests/test_something.py 1167 import pytest 1168 1169 @pytest.mark.parametrize('username', ['directly-overridden-username']) 1170 def test_username(username): 1171 assert username == 'directly-overridden-username' 1172 1173 @pytest.mark.parametrize('username', ['directly-overridden-username-other']) 1174 def test_username_other(other_username): 1175 assert other_username == 'other-directly-overridden-username-other' 1176 1177In the example above, a fixture value is overridden by the test parameter value. Note that the value of the fixture 1178can be overridden this way even if the test doesn't use it directly (doesn't mention it in the function prototype). 1179 1180 1181Override a parametrized fixture with non-parametrized one and vice versa 1182^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1183 1184Given the tests file structure is: 1185 1186:: 1187 1188 tests/ 1189 __init__.py 1190 1191 conftest.py 1192 # content of tests/conftest.py 1193 import pytest 1194 1195 @pytest.fixture(params=['one', 'two', 'three']) 1196 def parametrized_username(request): 1197 return request.param 1198 1199 @pytest.fixture 1200 def non_parametrized_username(request): 1201 return 'username' 1202 1203 test_something.py 1204 # content of tests/test_something.py 1205 import pytest 1206 1207 @pytest.fixture 1208 def parametrized_username(): 1209 return 'overridden-username' 1210 1211 @pytest.fixture(params=['one', 'two', 'three']) 1212 def non_parametrized_username(request): 1213 return request.param 1214 1215 def test_username(parametrized_username): 1216 assert parametrized_username == 'overridden-username' 1217 1218 def test_parametrized_username(non_parametrized_username): 1219 assert non_parametrized_username in ['one', 'two', 'three'] 1220 1221 test_something_else.py 1222 # content of tests/test_something_else.py 1223 def test_username(parametrized_username): 1224 assert parametrized_username in ['one', 'two', 'three'] 1225 1226 def test_username(non_parametrized_username): 1227 assert non_parametrized_username == 'username' 1228 1229In the example above, a parametrized fixture is overridden with a non-parametrized version, and 1230a non-parametrized fixture is overridden with a parametrized version for certain test module. 1231The same applies for the test folder level obviously. 1232