quicklinks

home contents
install changelog
examples customize
issues[bb] contact

Table Of Contents

Previous topic

doctest integration for modules and test files

Next topic

Talks and Tutorials

Working with plugins and conftest files

py.test implements all aspects of configuration, collection, running and reporting by calling well specified hooks. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a pytest_ prefix, making hook functions easy to distinguish and find. There are three basic locations types:

conftest.py: local per-directory plugins

local conftest.py plugins contain directory-specific hook implementations. Session and test running activities will invoke all hooks defined in conftest.py files closer to the root of the filesystem. Example: Assume the following layout and content of files:

a/conftest.py:
    def pytest_runtest_setup(item):
        # called for running each test in 'a' directory
        print ("setting up", item)

a/test_in_subdir.py:
    def test_sub():
        pass

test_flat.py:
    def test_flat():
        pass

Here is how you might run it:

py.test test_flat.py   # will not show "setting up"
py.test a/test_sub.py  # will show "setting up"

Note

If you have conftest.py files which do not reside in a python package directory (i.e. one containing an __init__.py) then “import conftest” can be ambiguous because there might be other conftest.py files as well on your PYTHONPATH or sys.path. It is thus good practise for projects to either put conftest.py under a package scope or to never import anything from a conftest.py file.

Installing External Plugins / Searching

Installing a plugin happens through any usual Python installation tool, for example:

pip install pytest-NAME
pip uninstall pytest-NAME

If a plugin is installed, py.test automatically finds and integrates it, there is no need to activate it. Here is a list of known plugins:

You may discover more plugins through a pytest- pypi.python.org search.

Writing a plugin by looking at examples

If you want to write a plugin, there are many real-life examples you can copy from:

All of these plugins implement the documented well specified hooks to extend and add functionality.

Making your plugin installable by others

If you want to make your plugin externally available, you may define a so-called entry point for your distribution so that py.test finds your plugin module. Entry points are a feature that is provided by setuptools or Distribute. py.test looks up the pytest11 entrypoint to discover its plugins and you can thus make your plugin available by definig it in your setuptools/distribute-based setup-invocation:

# sample ./setup.py file
from setuptools import setup

setup(
    name="myproject",
    packages = ['myproject']

    # the following makes a plugin available to py.test
    entry_points = {
        'pytest11': [
            'name_of_plugin = myproject.pluginmodule',
        ]
    },
)

If a package is installed this way, py.test will load myproject.pluginmodule as a plugin which can define well specified hooks.

Plugin discovery order at tool startup

py.test loads plugin modules at tool startup in the following way:

  • by loading all builtin plugins
  • by loading all plugins registered through setuptools entry points.
  • by pre-scanning the command line for the -p name option and loading the specified plugin before actual command line parsing.
  • by loading all conftest.py files as inferred by the command line invocation (test files and all of its parent directories). Note that conftest.py files from sub directories are by default not loaded at tool startup.
  • by recursively loading all plugins specified by the pytest_plugins variable in conftest.py files

Requiring/Loading plugins in a test module or conftest file

You can require plugins in a test module or a conftest file like this:

pytest_plugins = "name1", "name2",

When the test module or conftest plugin is loaded the specified plugins will be loaded as well. You can also use dotted path like this:

pytest_plugins = "myapp.testsupport.myplugin"

which will import the specified module as a py.test plugin.

Accessing another plugin by name

If a plugin wants to collaborate with code from another plugin it can obtain a reference through the plugin manager like this:

plugin = config.pluginmanager.getplugin("name_of_plugin")

If you want to look at the names of existing plugins, use the --traceconfig option.

Finding out which plugins are active

If you want to find out which plugins are active in your environment you can type:

py.test --traceconfig

and will get an extended test header which shows activated plugins and their names. It will also print local plugins aka conftest.py files when they are loaded.

deactivate / unregister a plugin by name

You can prevent plugins from loading or unregister them:

py.test -p no:NAME

This means that any subsequent try to activate/load the named plugin will it already existing. See Finding out which plugins are active for how to obtain the name of a plugin.

py.test default plugin reference

You can find the source code for the following plugins in the pytest repository.

_pytest.assertion support for presenting detailed information in failing assertions.
_pytest.capture per-test stdout/stderr capturing mechanisms, capsys and capfd function arguments.
_pytest.config command line options, ini-file and conftest.py processing.
_pytest.doctest discover and run doctests in modules and test files.
_pytest.genscript generate a single-file self-contained version of py.test
_pytest.helpconfig version info, help messages, tracing configuration.
_pytest.junitxml report test results in JUnit-XML format, for use with Hudson and build integration servers.
_pytest.mark generic mechanism for marking and selecting python functions.
_pytest.monkeypatch monkeypatching and mocking functionality.
_pytest.nose run test suites written for nose.
_pytest.pastebin submit failure or test session information to a pastebin service.
_pytest.pdb interactive debugging with PDB, the Python Debugger.
_pytest.pytester (disabled by default) support for testing py.test and py.test plugins.
_pytest.python Python test discovery, setup and run of test functions.
_pytest.recwarn recording warnings during test function execution.
_pytest.resultlog (disabled by default) create result information in a plain text file.
_pytest.runner basic collect and runtest protocol implementations
_pytest.main core implementation of testing process: init, session, runtest loop.
_pytest.skipping support for skip/xfail functions and markers.
_pytest.terminal terminal reporting of the full testing process.
_pytest.tmpdir support for providing temporary directories to test functions.
_pytest.unittest discovery and running of std-library “unittest” style tests.

py.test hook reference

hook specification and validation

py.test calls hook functions to implement initialization, running, test execution and reporting. When py.test loads a plugin it validates that each hook function conforms to its respective hook specification. Each hook function name and its argument names need to match a hook specification. However, a hook function may accept fewer parameters by simply not specifying them. If you mistype argument names or the hook name itself you get an error showing the available arguments.

initialisation, command line and configuration hooks

_pytest.hookspec.pytest_cmdline_preparse(config, args)[source]

modify command line arguments before option parsing.

_pytest.hookspec.pytest_cmdline_parse(pluginmanager, args)[source]

return initialized config object, parsing the specified args.

_pytest.hookspec.pytest_namespace()[source]

return dict of name->object to be made globally available in the py.test/pytest namespace. This hook is called before command line options are parsed.

_pytest.hookspec.pytest_addoption(parser)[source]

add optparse-style options and ini-style config values via calls to parser.addoption and parser.addini(...).

_pytest.hookspec.pytest_cmdline_main(config)[source]

called for performing the main command line action. The default implementation will invoke the configure hooks and runtest_mainloop.

_pytest.hookspec.pytest_configure(config)[source]

called after command line options have been parsed. and all plugins and initial conftest files been loaded.

_pytest.hookspec.pytest_unconfigure(config)[source]

called before test process is exited.

generic “runtest” hooks

All all runtest related hooks receive a pytest.Item object.

_pytest.hookspec.pytest_runtest_protocol(item)[source]

implements the standard runtest_setup/call/teardown protocol including capturing exceptions and calling reporting hooks on the results accordingly.

Return boolean:True if no further hook implementations should be invoked.
_pytest.hookspec.pytest_runtest_setup(item)[source]

called before pytest_runtest_call(item).

_pytest.hookspec.pytest_runtest_call(item)[source]

called to execute the test item.

_pytest.hookspec.pytest_runtest_teardown(item)[source]

called after pytest_runtest_call.

_pytest.hookspec.pytest_runtest_makereport(item, call)[source]

return a _pytest.runner.TestReport object for the given pytest.Item and _pytest.runner.CallInfo.

For deeper understanding you may look at the default implementation of these hooks in _pytest.runner and maybe also in _pytest.pdb which interacts with _pytest.capture and its input/output capturing in order to immediately drop into interactive debugging when a test failure occurs.

The _pytest.terminal reported specifically uses the reporting hook to print information about a test run.

collection hooks

py.test calls the following hooks for collecting files and directories:

_pytest.hookspec.pytest_ignore_collect(path, config)[source]

return True to prevent considering this path for collection. This hook is consulted for all files and directories prior to calling more specific hooks.

_pytest.hookspec.pytest_collect_directory(path, parent)[source]

called before traversing a directory for collection files.

_pytest.hookspec.pytest_collect_file(path, parent)[source]

return collection Node or None for the given path. Any new node needs to have the specified parent as a parent.

For influencing the collection of objects in Python modules you can use the following hook:

_pytest.hookspec.pytest_pycollect_makeitem(collector, name, obj)[source]

return custom item/collector for a python object in a module, or None.

reporting hooks

Session related reporting hooks:

And here is the central hook for reporting about test execution:

Reference of important objects involved in hooks

class _pytest.config.Config(pluginmanager=None)[source]

access to configuration values, pluginmanager and plugin hooks.

classmethod fromdictargs(option_dict, args)[source]

constructor useable for subprocesses.

getini(name)[source]

return configuration value from an ini file. If the specified name hasn’t been registered through a prior parse.addini call (usually from a plugin), a ValueError is raised.

getvalue(name, path=None)[source]

return name value looked set from command line options.

(deprecated) if we can’t find the option also lookup the name in a matching conftest file.

getvalueorskip(name, path=None)[source]

(deprecated) return getvalue(name) or call py.test.skip if no value exists.

option

command line option values, usually added via parser.addoption(...) or parser.getgroup(...).addoption(...) calls

pluginmanager

a pluginmanager instance

class _pytest.config.Parser(usage=None, processopt=None)[source]

Parser for command line arguments.

addini(name, help, type=None, default=None)[source]

add an ini-file option with the given name and description.

addoption(*opts, **attrs)[source]

add an optparse-style option.

getgroup(name, description='', after=None)[source]

get (or create) a named option Group.

Name :unique name of the option group.
Description :long description for –help output.
After :name of other group, used for ordering –help output.
class _pytest.main.Node(name, parent)[source]

base class for all Nodes in the collection tree. Collector subclasses have children, Items are terminal nodes.

Class

deprecated attribute ‘Class’, use pytest.Class

File

deprecated attribute ‘File’, use pytest.File

Function

deprecated attribute ‘Function’, use pytest.Function

Instance

deprecated attribute ‘Instance’, use pytest.Instance

Item

deprecated attribute ‘Item’, use pytest.Item

Module

deprecated attribute ‘Module’, use pytest.Module

config

the test config object

fspath

filesystem path where this node was collected from

listchain()[source]

return list of all parent collectors up to self, starting from root of collection tree.

name

a unique name with the scope of the parent

parent

the parent collector node.

session

the collection this node is part of

class _pytest.runner.CallInfo(func, when)[source]

Result/Exception info a function invocation.

excinfo

None or ExceptionInfo object.

when

context of invocation: one of “setup”, “call”, “teardown”, “memocollect”

class _pytest.runner.TestReport(nodeid, location, keywords, outcome, longrepr, when)[source]

Basic test report object (also used for setup and teardown calls if they fail).

keywords

a name -> value dictionary containing all keywords and markers associated with a test invocation.

location

a (filesystempath, lineno, domaininfo) tuple indicating the actual location of a test item - it might be different from the collected one e.g. if a method is inherited from a different module.

longrepr

None or a failure representation.

nodeid

normalized collection node id

outcome

test outcome, always one of “passed”, “failed”, “skipped”.

when

one of ‘setup’, ‘call’, ‘teardown’ to indicate runtest phase.