[svn r63990] * adding XXXed funcargs docs, moving release announcements to own subdir
--HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									7cc9419ab0
								
							
						
					
					
						commit
						9f30ca6688
					
				|  | @ -7,6 +7,6 @@ Contents: | |||
| .. toctree:: | ||||
|    :maxdepth: 1 | ||||
| 
 | ||||
|    release-1.0.0 | ||||
|    release-0.9.2 | ||||
|    release-0.9.0 | ||||
|    announce/release-1.0.0 | ||||
|    announce/release-0.9.2 | ||||
|    announce/release-0.9.0 | ||||
|  |  | |||
|  | @ -110,6 +110,11 @@ name.  Given a filesystem ``fspath`` it is constructed as follows: | |||
| Plugin hooks and events   | ||||
| ======================================= | ||||
| 
 | ||||
| See definitions at  | ||||
| .. automodule:: py.__.test.plugin.api | ||||
| 
 | ||||
| .. autoclass:: PluginHooks | ||||
|     :members: | ||||
| 
 | ||||
| .. autoclass:: Events | ||||
|     :members: | ||||
| 
 | ||||
| http://codespeak.net/svn/py/trunk/py/test/plugin/api.py | ||||
|  |  | |||
|  | @ -0,0 +1,160 @@ | |||
| 
 | ||||
| ===================================== | ||||
| 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 | ||||
| 
 | ||||
| 
 | ||||
		Loading…
	
		Reference in New Issue