Skip to content

Baseline

pytest 6.0.0 - 6.0.2 - A plain test suite with no conftest and no plugins.

These 3 releases produced an identical flow, so they share one page. Identical as far as this scenario can measure - a scenario exercising more hooks may tell them apart.

The reference shape of a pytest run: parametrised tests, a yield fixture, a finalizer fixture, a skip, and one intentional failure. Every other scenario should be read as a diff against this one.

How this was produced

  • Source: scenarios/baseline/ - the project this diagram was traced from
  • Invocation: pytest -p hook_atlas_pytest . -q
  • Traced against: pytest 6.0.2, pluggy 0.13.1, Python 3.9.25
  • Covers: 3 releases - pytest 6.0.0 - 6.0.2, which produced an identical flow
  • Observed: 313 hook calls, 39 distinct hooks

The project is test_dummy.py. Browse it in the repository rather than inline here - scenarios grow directory trees, and GitHub renders them better than a collapsed block can.

The whole run

Phases left to right, steps top to bottom. Colour says which phase a hook belongs to; how dark a step is says how often it was called. Click a column heading to jump to that phase in full detail, or any hook to open its pytest documentation. Why it looks like this

%3 cluster_phase_startup STARTUP AND CONFIGURATION cluster_startup_n1 pytest_load_initial_conftests cluster_startup_n3 pytest_configure historic · 2x in run cluster_startup_n6 pytest_sessionstart cluster_phase_collection COLLECTION cluster_collection_n1 pytest_collection firstresult cluster_phase_runtest THE RUN-TEST PROTOCOL cluster_runtest_n1 pytest_runtest_protocol firstresult · 8x in run cluster_phase_finish SESSION FINISH cluster_finish_n1 pytest_sessionfinish startup_n2 pytest_plugin_registered historic · 75x in run startup_n4 pytest_configure historic · 2x in run startup_n2->startup_n4 startup_n5 pytest_plugin_registered historic · x36 startup_n4->startup_n5 startup_n7 pytest_plugin_registered historic · x36 startup_n5->startup_n7 collection_n2 pytest_collectstart 2x in run collection_n3 pytest_make_collect_report firstresult · 2x in run collection_n2->collection_n3 collection_n4 pytest_collectreport 2x in run collection_n3->collection_n4 collection_n5 pytest_collectstart 2x in run collection_n4->collection_n5 collection_n6 pytest_make_collect_report firstresult · 2x in run collection_n5->collection_n6 collection_n7 pytest_itemcollected x8 collection_n6->collection_n7 collection_n8 pytest_collectreport 2x in run collection_n7->collection_n8 collection_n9 pytest_collection_modifyitems collection_n8->collection_n9 collection_n10 pytest_collection_finish collection_n9->collection_n10 collection_n11 pytest_warning_captured historic · 2x in run collection_n10->collection_n11 collection_n12 pytest_warning_recorded historic · 2x in run collection_n11->collection_n12 runtest_n2 pytest_runtest_logstart 8x in run runtest_n3 pytest_runtest_setup 8x in run runtest_n2->runtest_n3 runtest_n4 pytest_runtest_makereport firstresult · 23x in run runtest_n3->runtest_n4 runtest_n5 pytest_runtest_logreport 23x in run runtest_n4->runtest_n5 runtest_n6 pytest_runtest_call 7x in run runtest_n5->runtest_n6 runtest_n7 pytest_runtest_makereport firstresult · 23x in run runtest_n6->runtest_n7 runtest_n8 pytest_runtest_logreport 23x in run runtest_n7->runtest_n8 runtest_n9 pytest_runtest_teardown 8x in run runtest_n8->runtest_n9 runtest_n10 pytest_runtest_makereport firstresult · 23x in run runtest_n9->runtest_n10 runtest_n11 pytest_runtest_logreport 23x in run runtest_n10->runtest_n11 runtest_n12 pytest_runtest_logfinish 8x in run runtest_n11->runtest_n12 finish_n2 pytest_terminal_summary finish_n3 pytest_unconfigure finish_n2->finish_n3

Startup and configuration

Everything before collection begins: initial conftests are loaded, plugins register, and the session is configured.

Collection

Finding tests. Note that pytest_make_collect_report recurses - directories contain directories contain files.

The run-test protocol

pytest_runtestloop runs this once per collected test. Note the rhythm: setup, call and teardown are each followed by their own makereport and logreport pair - three reports per test, not one.

The path 5 of 8 took.

The others differed:

  • 1 test also called pytest_exception_interact
  • 1 test skipped pytest_fixture_post_finalizer, pytest_fixture_setup, pytest_pyfunc_call, pytest_runtest_call
  • 1 test also called pytest_warning_captured, pytest_warning_recorded and skipped pytest_fixture_post_finalizer, pytest_fixture_setup

Session finish

Summary reporting and teardown of the session.

Every hook observed

Hook Calls Semantics Implemented by, in call order
pytest_cmdline_main 1 firstresult _pytest.setupplan [tryfirst]
_pytest.setuponly [tryfirst]
_pytest.mark [tryfirst]
_pytest.python
_pytest.helpconfig
_pytest.main
pytest_cmdline_preparse 1 -
pytest_collect_file 4 _pytest.doctest
_pytest.python
pytest_collection 1 firstresult _pytest.logging.LoggingPlugin (logging-plugin) [hookwrapper, tryfirst]
_pytest.warnings [hookwrapper, tryfirst]
_pytest.terminal.TerminalReporter
_pytest.assertion
_pytest.main
pytest_collection_finish 1 _pytest.terminal.TerminalReporter
pytest_collection_modifyitems 1 _pytest.fixtures.FixtureManager (funcmanage)
_pytest.main
_pytest.mark
pytest_collectreport 2 _pytest.main.Session.pytest_runtest_logreport (session) [tryfirst]
_pytest.terminal.TerminalReporter
pytest_collectstart 2 _pytest.main.Session [tryfirst]
pytest_configure 2 historic _pytest.faulthandler
_pytest.warnings
_pytest.resultlog
_pytest.junitxml
_pytest.tmpdir
_pytest.skipping
_pytest.debugging
_pytest.terminal
_pytest.python
_pytest.mark
_pytest.config.PytestPluginManager (<anonymous>)
_pytest.pastebin [trylast]
_pytest.logging [trylast]
_pytest.faulthandler.FaultHandlerHooks (faulthandler-hooks)
pytest_exception_interact 1 _pytest.faulthandler.FaultHandlerHooks (faulthandler-hooks) [tryfirst]
pytest_fixture_post_finalizer 11 _pytest.setuponly
pytest_fixture_setup 11 firstresult _pytest.setuponly [hookwrapper]
_pytest.setupplan [tryfirst]
_pytest.fixtures
pytest_generate_tests 4 _pytest.fixtures.FixtureManager (funcmanage)
_pytest.python
pytest_ignore_collect 4 firstresult _pytest.main
pytest_itemcollected 8 -
pytest_load_initial_conftests 1 _pytest.capture [hookwrapper]
_pytest.config.Config (pytestconfig) [trylast]
pytest_make_collect_report 2 firstresult _pytest.capture.CaptureManager [hookwrapper]
_pytest.runner
pytest_make_parametrize_id 5 firstresult -
pytest_plugin_registered 75 historic _pytest.terminal.TerminalReporter
_pytest.fixtures.FixtureManager (funcmanage)
pytest_pycollect_makeitem 41 firstresult _pytest.unittest
_pytest.python [trylast]
pytest_pycollect_makemodule 1 firstresult _pytest.python
pytest_pyfunc_call 7 firstresult _pytest.python [trylast]
pytest_report_collectionfinish 1 -
pytest_report_teststatus 24 firstresult _pytest.skipping
_pytest.runner
_pytest.terminal [trylast]
pytest_runtest_call 7 _pytest.logging.LoggingPlugin (logging-plugin) [hookwrapper]
_pytest.capture.CaptureManager [hookwrapper]
_pytest.skipping [hookwrapper]
_pytest.runner
pytest_runtest_logfinish 8 _pytest.logging.LoggingPlugin (logging-plugin)
_pytest.terminal.TerminalReporter
pytest_runtest_logreport 23 _pytest.main.Session [tryfirst]
_pytest.logging.LoggingPlugin (logging-plugin)
_pytest.terminal.TerminalReporter
pytest_runtest_logstart 8 _pytest.logging.LoggingPlugin (logging-plugin)
_pytest.terminal.TerminalReporter
pytest_runtest_makereport 23 firstresult _pytest.skipping [hookwrapper]
_pytest.unittest [tryfirst]
_pytest.runner
pytest_runtest_protocol 8 firstresult _pytest.warnings [hookwrapper, tryfirst]
_pytest.assertion [hookwrapper, tryfirst]
_pytest.unittest [hookwrapper]
_pytest.faulthandler.FaultHandlerHooks (faulthandler-hooks) [hookwrapper, trylast]
_pytest.runner
pytest_runtest_setup 8 _pytest.logging.LoggingPlugin (logging-plugin) [hookwrapper]
_pytest.capture.CaptureManager [hookwrapper]
_pytest.skipping [tryfirst]
_pytest.runner
_pytest.nose [trylast]
pytest_runtest_teardown 8 _pytest.logging.LoggingPlugin (logging-plugin) [hookwrapper]
_pytest.capture.CaptureManager [hookwrapper]
_pytest.runner
pytest_runtestloop 1 firstresult _pytest.logging.LoggingPlugin (logging-plugin) [hookwrapper]
_pytest.main
pytest_sessionfinish 1 _pytest.logging.LoggingPlugin (logging-plugin) [hookwrapper, tryfirst]
_pytest.terminal.TerminalReporter [hookwrapper]
_pytest.warnings [hookwrapper]
_pytest.assertion
_pytest.runner
pytest_sessionstart 1 _pytest.logging.LoggingPlugin (logging-plugin) [hookwrapper, tryfirst]
_pytest.fixtures
_pytest.runner
_pytest.terminal.TerminalReporter [trylast]
pytest_terminal_summary 1 _pytest.terminal.TerminalReporter [hookwrapper]
_pytest.warnings [hookwrapper]
_pytest.pastebin
_pytest.runner
pytest_unconfigure 1 _pytest.logging.LoggingPlugin (logging-plugin)
_pytest.terminal.TerminalReporter
_pytest.faulthandler.FaultHandlerHooks (faulthandler-hooks)
_pytest.doctest
_pytest.resultlog
_pytest.junitxml
_pytest.pastebin
_pytest.mark
pytest_warning_captured 2 historic -
pytest_warning_recorded 2 historic _pytest.terminal.TerminalReporter