===================================== Python test function arguments ===================================== py.test enables a new way to separate test configuration and test setup from actual test code in test functions. When it runs a test functions it will lookup function arguments by name and provide a value. Here is a simple example for such a test function: def test_function(mysetup): # work with mysetup To provide a value py.test looks for a ``pytest_funcargs`` dictionary in the test module, for example:: class MySetup: def __init__(self, pyfuncitem): self.pyfuncitem = pyfuncitem pytest_funcargs = {'mysetup': MySetup} This is already enough to run the test. Of course up until now our ``mysetup`` does not provide much value. But it is now easy to add new methods on the ``MySetup`` class that have full access to the test collection process. Plugins can register their funcargs via the config object, usually upon initial configure:: class ConftestPlugin: def pytest_configure(self, config): config.register_funcargs(mysetup=MySetup) If you provide a "funcarg" from a plugin you can easily make methods depend on command line options or environment settings. Here is a complete example that allows to run tests involving an SSH connection if an ssh host is specified:: class ConftestPlugin: def pytest_addoption(self, parser): parser.addoption("--ssh", action="store", default=None, help="specify ssh host to run tests with") def pytest_configure(self, config): config.register_funcargs(mysetup=MySetup) class MySetup: def __init__(self, pyfuncitem): self.pyfuncitem = pyfuncitem def ssh_gateway(self): host = pyfuncitem.config.option.ssh if host is None: py.test.skip("specify ssh host with --ssh to run this test") return py.execnet.SshGateway(host) Now any test functions can use the "mysetup" object, for example:: class TestClass: def test_function(self, mysetup): ssh_gw = mysetup.ssh_gateway() # work with ssh_gw Without specifying a command line option the output looks like this:: ... Lookup rules ====================== In order to run this test function a value for the ``mysetup`` needs to be found. Here is how py.test finds a matching provider function: 1. see if there is a ``pytest_funcargs`` dictionary which maps ``mysetup`` to a provider function. if so, call the provider function. XXX example ===================== You can run a test file ``test_some.py`` with this content: pytest_funcargs = {'myarg': (lambda pyfuncitem: 42)} def test_something(myarg): assert myarg == 42 You can also put this on a class: class TestClass: pytest_funcargs = {'myarg': (lambda pyfuncitem: 42)} def test_something(self, myarg): assert myarg == 42 To separate funcarg setup you can also put a funcarg definition into a conftest.py:: pytest_funcargs = {'myarg': decorate_myarg} def decorate_myarg(pyfuncitem): result = pyfuncitem.call_next_provider() return result + 1 for registering funcargs from a plugin, talk to the test configuration object like this:: class MyPlugin: def pytest_configure(self, config): config.register_funcargs( myarg=decorate_myarg ) a local helper funcarg for doing acceptance tests maybe by running shell commands could look like this:: class MyPlugin: def pytest_option(self, parser): group = parser.addgroup("myproject acceptance tests") group.addoption("-A", dest="acceptance", action="store_true", help="run (slow) acceptance tests") def pytest_configure(self, config): config.register_funcargs(accept=AcceptFuncarg) class AcceptFuncarg: def __init__(self, pyfuncitem): if not pyfuncitem.config.option.acceptance: py.test.skip("specify -A to run acceptance tests") self.tmpdir = pyfuncitem.config.maketempdir(pyfuncitem.name) self._old = self.tmpdir.chdir() pyfuncitem.addfinalizer(self.finalize) def run(self): return py.process.cmdexec("echo hello") def finalize(self): self._old.chdir() # cleanup any other resources and the actual test function example: def test_some_acceptance_aspect(accept): accept.tmpdir.mkdir("somesub") result = accept.run() assert result for registering funcargs from a plugin, talk to the test configuration object like this:: XXX