summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorholger krekel <holger@merlinux.eu>2010-11-21 23:17:59 +0100
committerholger krekel <holger@merlinux.eu>2010-11-21 23:17:59 +0100
commitbc42cf8ffbc72a702b3e4e1dd040d39138e1b715 (patch)
treed2b5c9c87aab38af089f96979b0a3e3a7ada58d3
parentf456e376b99722f8e094ac52698e0fa9252ae686 (diff)
downloadpytest-bc42cf8ffbc72a702b3e4e1dd040d39138e1b715.tar.gz
add a way to mark hooks as "tryfirst" or "trylast" to influence its position in a hook chain.
Use 'tryfirst' for capturing hooks so they can start capturing as early as possible, including when conftests add output in runtest_setup hooks.
-rw-r--r--_pytest/capture.py6
-rw-r--r--_pytest/core.py12
-rw-r--r--_pytest/pdb.py6
-rw-r--r--_pytest/python.py4
-rw-r--r--pytest.py2
-rw-r--r--setup.py2
-rw-r--r--testing/test_capture.py10
-rw-r--r--testing/test_core.py29
8 files changed, 62 insertions, 9 deletions
diff --git a/_pytest/capture.py b/_pytest/capture.py
index 013da9b81..b35eef4b7 100644
--- a/_pytest/capture.py
+++ b/_pytest/capture.py
@@ -1,6 +1,6 @@
""" per-test stdout/stderr capturing mechanisms, ``capsys`` and ``capfd`` function arguments. """
-import py
+import pytest, py
import os
def pytest_addoption(parser):
@@ -143,13 +143,16 @@ class CaptureManager:
addouterr(rep, outerr)
return rep
+ @pytest.mark.tryfirst
def pytest_runtest_setup(self, item):
self.resumecapture_item(item)
+ @pytest.mark.tryfirst
def pytest_runtest_call(self, item):
self.resumecapture_item(item)
self.activate_funcargs(item)
+ @pytest.mark.tryfirst
def pytest_runtest_teardown(self, item):
self.resumecapture_item(item)
@@ -168,6 +171,7 @@ class CaptureManager:
if hasattr(self, '_capturing'):
self.suspendcapture()
+ @pytest.mark.tryfirst
def pytest_runtest_makereport(self, __multicall__, item, call):
self.deactivate_funcargs()
rep = __multicall__.execute()
diff --git a/_pytest/core.py b/_pytest/core.py
index 1f01a243b..ec511af9b 100644
--- a/_pytest/core.py
+++ b/_pytest/core.py
@@ -12,7 +12,7 @@ assert py.__version__.split(".")[:2] >= ['2', '0'], ("installation problem: "
"%s is too old, remove or upgrade 'py'" % (py.__version__))
default_plugins = (
- "config session terminal runner python pdb capture unittest mark skipping "
+ "config mark session terminal runner python pdb unittest capture skipping "
"tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript "
"junitxml doctest").split()
@@ -272,11 +272,19 @@ class PluginManager(object):
if plugins is None:
plugins = self._plugins
l = []
+ last = []
for plugin in plugins:
try:
- l.append(getattr(plugin, attrname))
+ meth = getattr(plugin, attrname)
+ if hasattr(meth, 'tryfirst'):
+ last.append(meth)
+ elif hasattr(meth, 'trylast'):
+ l.insert(0, meth)
+ else:
+ l.append(meth)
except AttributeError:
continue
+ l.extend(last)
return l
def call_plugin(self, plugin, methname, kwargs):
diff --git a/_pytest/pdb.py b/_pytest/pdb.py
index 2c4681e1f..04fe82f68 100644
--- a/_pytest/pdb.py
+++ b/_pytest/pdb.py
@@ -1,6 +1,6 @@
""" interactive debugging with PDB, the Python Debugger. """
-import py
+import pytest, py
import sys
def pytest_addoption(parser):
@@ -45,9 +45,11 @@ class PdbInvoke:
def pytest_sessionfinish(self, session):
# don't display failures again at the end
session.config.option.tbstyle = "no"
+
+ @pytest.mark.tryfirst
def pytest_runtest_makereport(self, item, call, __multicall__):
if not call.excinfo or \
- call.excinfo.errisinstance(py.test.skip.Exception) or \
+ call.excinfo.errisinstance(pytest.skip.Exception) or \
call.excinfo.errisinstance(py.std.bdb.BdbQuit):
return
rep = __multicall__.execute()
diff --git a/_pytest/python.py b/_pytest/python.py
index 6f4777f68..d6560d57a 100644
--- a/_pytest/python.py
+++ b/_pytest/python.py
@@ -19,8 +19,8 @@ def pytest_cmdline_main(config):
showfuncargs(config)
return 0
-def pytest_namespace(__multicall__):
- __multicall__.execute()
+@pytest.mark.trylast
+def pytest_namespace():
raises.Exception = pytest.fail.Exception
return {
'raises' : raises,
diff --git a/pytest.py b/pytest.py
index 8cc9ec5fa..e553791b7 100644
--- a/pytest.py
+++ b/pytest.py
@@ -5,7 +5,7 @@ see http://pytest.org for documentation and details
(c) Holger Krekel and others, 2004-2010
"""
-__version__ = '2.0.0.dev31'
+__version__ = '2.0.0.dev32'
__all__ = ['main']
from _pytest.core import main, UsageError, _preloadplugins
diff --git a/setup.py b/setup.py
index 5af4732ee..c7b62fe70 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@ def main():
name='pytest',
description='py.test: simple powerful testing with Python',
long_description = long_description,
- version='2.0.0.dev31',
+ version='2.0.0.dev32',
url='http://pytest.org',
license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
diff --git a/testing/test_capture.py b/testing/test_capture.py
index 0ea2df6b5..113bd562f 100644
--- a/testing/test_capture.py
+++ b/testing/test_capture.py
@@ -377,3 +377,13 @@ def test_fdfuncarg_skips_on_no_osdup(testdir):
result.stdout.fnmatch_lines([
"*1 skipped*"
])
+
+def test_capture_conftest_runtest_setup(testdir):
+ testdir.makeconftest("""
+ def pytest_runtest_setup():
+ print ("hello19")
+ """)
+ testdir.makepyfile("def test_func(): pass")
+ result = testdir.runpytest()
+ assert result.ret == 0
+ assert 'hello19' not in result.stdout.str()
diff --git a/testing/test_core.py b/testing/test_core.py
index ccf514975..55a6d2dc0 100644
--- a/testing/test_core.py
+++ b/testing/test_core.py
@@ -418,6 +418,35 @@ class TestPytestPluginInteractions:
assert not pluginmanager.listattr("hello")
assert pluginmanager.listattr("x") == [42]
+ def test_listattr_tryfirst(self):
+ class P1:
+ @pytest.mark.tryfirst
+ def m(self):
+ return 17
+
+ class P2:
+ def m(self):
+ return 23
+ class P3:
+ def m(self):
+ return 19
+
+ pluginmanager = PluginManager()
+ p1 = P1()
+ p2 = P2()
+ p3 = P3()
+ pluginmanager.register(p1)
+ pluginmanager.register(p2)
+ pluginmanager.register(p3)
+ methods = pluginmanager.listattr('m')
+ assert methods == [p2.m, p3.m, p1.m]
+ del P1.m.__dict__['tryfirst']
+
+ pytest.mark.trylast(getattr(P2.m, 'im_func', P2.m))
+ methods = pluginmanager.listattr('m')
+ assert methods == [p2.m, p1.m, p3.m]
+
+
def test_namespace_has_default_and_env_plugins(testdir):
p = testdir.makepyfile("""
import pytest