Hello, I have a problem accessing the captured stderr. I have set up the following test:
$ ls mytest/ conftest.py test_one.py $ cat mytest/conftest.py import pytest @pytest.fixture(autouse=True) def add_stderr_check(request, capsys): def check_stderr(): stderr = capsys.readouterr()[1] if 'exception' in stderr.lower(): raise AssertionError('Suspicious output to stderr') request.addfinalizer(check_stderr) $ cat mytest/test_one.py import threading def test_thread(): def fail(): raise RuntimeError('Do not call me!') t = threading.Thread(target=fail) t.start() t.join() def test_del(): d = ImmortalObject() assert d.value == 2 del d class ImmortalObject: def __init__(self): self.value = 2 def __del__(self): raise RuntimeError('You cannot kill me!') As long as I call the tests individually, they behave exactly as expected: > $ py.test mytest/ -v -k test_thread > =========================================== test session starts > ============================================ > platform linux -- Python 3.3.2 -- pytest-2.3.5 -- /usr/bin/python3.3 > collected 2 items > > mytest/test_one.py:3: test_thread PASSED > mytest/test_one.py:3: test_thread ERROR > > ================================================== ERRORS > ================================================== > _____________________________________ ERROR at teardown of test_thread > _____________________________________ > > def check_stderr(): > stderr = capsys.readouterr()[1] > if 'exception' in stderr.lower(): >> raise AssertionError('Suspicious output to stderr') > E AssertionError: Suspicious output to stderr > > mytest/conftest.py:8: AssertionError > --------------------------------------------- Captured stderr > ---------------------------------------------- > Exception in thread Thread-1: > Traceback (most recent call last): > File "/usr/lib/python3.3/threading.py", line 637, in _bootstrap_inner > self.run() > File "/usr/lib/python3.3/threading.py", line 594, in run > self._target(*self._args, **self._kwargs) > File "/home/nikratio/in-progress/s3ql/mytest/test_one.py", line 5, in fail > raise RuntimeError('Do not call me!') > RuntimeError: Do not call me! > > ================================== 1 tests deselected by '-ktest_thread' > =================================== > ============================= 1 passed, 1 deselected, 1 error in 0.01 seconds > ============================== and: > [1] nikratio@vostro:~/in-progress/s3ql$ py.test mytest/ -v -k test_del > =========================================== test session starts > ============================================ > platform linux -- Python 3.3.2 -- pytest-2.3.5 -- /usr/bin/python3.3 > collected 2 items > > mytest/test_one.py:10: test_del PASSED > mytest/test_one.py:10: test_del ERROR > > ================================================== ERRORS > ================================================== > ______________________________________ ERROR at teardown of test_del > _______________________________________ > > def check_stderr(): > stderr = capsys.readouterr()[1] > if 'exception' in stderr.lower(): >> raise AssertionError('Suspicious output to stderr') > E AssertionError: Suspicious output to stderr > > mytest/conftest.py:8: AssertionError > --------------------------------------------- Captured stderr > ---------------------------------------------- > Exception RuntimeError: RuntimeError('You cannot kill me!',) in <bound method > ImmortalObject.__del__ of <test_one.ImmortalObject object at 0x7f9fb945fb90>> > ignored > ==================================== 1 tests deselected by '-ktest_del' > ==================================== > ============================= 1 passed, 1 deselected, 1 error in 0.01 seconds > ============================== However, if I attempt to run both tests, I get a very long and (to me) confusing error: > $ py.test mytest/ -v > =========================================== test session starts > ============================================ > platform linux -- Python 3.3.2 -- pytest-2.3.5 -- /usr/bin/python3.3 > collected 2 items > > mytest/test_one.py:3: test_thread PASSED > mytest/test_one.py:3: test_thread ERROR > mytest/test_one.py:10: test_del FAILED > > ================================================== ERRORS > ================================================== > _____________________________________ ERROR at teardown of test_thread > _____________________________________ > > def check_stderr(): > stderr = capsys.readouterr()[1] > if 'exception' in stderr.lower(): >> raise AssertionError('Suspicious output to stderr') > E AssertionError: Suspicious output to stderr > > mytest/conftest.py:8: AssertionError > --------------------------------------------- Captured stderr > ---------------------------------------------- > Exception in thread Thread-1: > Traceback (most recent call last): > File "/usr/lib/python3.3/threading.py", line 637, in _bootstrap_inner > self.run() > File "/usr/lib/python3.3/threading.py", line 594, in run > self._target(*self._args, **self._kwargs) > File "/home/nikratio/in-progress/s3ql/mytest/test_one.py", line 5, in fail > raise RuntimeError('Do not call me!') > RuntimeError: Do not call me! > > ================================================= FAILURES > ================================================= > _________________________________________________ test_del > _________________________________________________ > > self = <CallInfo when='call' exception: 'CaptureFixture' object has no > attribute 'capture'> > func = <function call_runtest_hook.<locals>.<lambda> at 0x7f413dfc5950>, when > = 'call' > > def __init__(self, func, when): > #: context of invocation: one of "setup", "call", > #: "teardown", "memocollect" > self.when = when > self.start = time() > try: > try: >> self.result = func() > > ../../.local/lib/python3.3/site-packages/_pytest/runner.py:129: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > >> return CallInfo(lambda: ihook(item=item, **kwds), when=when) > > ../../.local/lib/python3.3/site-packages/_pytest/runner.py:116: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > kwargs = {'item': <Function 'test_del'>} > plugins = [<Session 's3ql'>, <_pytest.core.PluginManager object at > 0x7f413eb6dfd0>, <module '_pytest.config' from '/home/nikrati...in.py'>, > <module '_pytest.terminal' from > '/home/nikratio/.local/lib/python3.3/site-packages/_pytest/terminal.py'>, ...] > > def call_matching_hooks(**kwargs): > plugins = self.config._getmatchingplugins(self.fspath) >> return hookmethod.pcall(plugins, **kwargs) > > ../../.local/lib/python3.3/site-packages/_pytest/main.py:159: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > self = <HookCaller 'pytest_runtest_call'> > plugins = [<Session 's3ql'>, <_pytest.core.PluginManager object at > 0x7f413eb6dfd0>, <module '_pytest.config' from '/home/nikrati...in.py'>, > <module '_pytest.terminal' from > '/home/nikratio/.local/lib/python3.3/site-packages/_pytest/terminal.py'>, ...] > kwargs = {'item': <Function 'test_del'>} > methods = [<function pytest_runtest_call at 0x7f413e9314d0>, <function > pdbitem at 0x7f413e9544d0>, <bound method CaptureManager.pytest_runtest_call > of <_pytest.capture.CaptureManager object at 0x7f413eb77710>>] > > def pcall(self, plugins, **kwargs): > methods = self.hookrelay._pm.listattr(self.name, plugins=plugins) >> return self._docall(methods, kwargs) > > ../../.local/lib/python3.3/site-packages/_pytest/core.py:445: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > self = <HookCaller 'pytest_runtest_call'> > methods = [<function pytest_runtest_call at 0x7f413e9314d0>, <function > pdbitem at 0x7f413e9544d0>, <bound method CaptureManager.pytest_runtest_call > of <_pytest.capture.CaptureManager object at 0x7f413eb77710>>] > kwargs = {'item': <Function 'test_del'>} > > def _docall(self, methods, kwargs): > self.trace(self.name, kwargs) > self.trace.root.indent += 1 > mc = MultiCall(methods, kwargs, firstresult=self.firstresult) > try: >> res = mc.execute() > > ../../.local/lib/python3.3/site-packages/_pytest/core.py:452: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > self = <MultiCall 0 results, 2 meths, kwargs={'item': <Function 'test_del'>}> > > def execute(self): > while self.methods: > method = self.methods.pop() > kwargs = self.getkwargs(method) >> res = method(**kwargs) > > ../../.local/lib/python3.3/site-packages/_pytest/core.py:370: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > self = <_pytest.capture.CaptureManager object at 0x7f413eb77710>, item = > <Function 'test_del'> > > @pytest.mark.tryfirst > def pytest_runtest_call(self, item): > self.resumecapture_item(item) >> self.activate_funcargs(item) > > ../../.local/lib/python3.3/site-packages/_pytest/capture.py:158: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > self = <_pytest.capture.CaptureManager object at 0x7f413eb77710>, pyfuncitem > = <Function 'test_del'> > > def activate_funcargs(self, pyfuncitem): > funcargs = getattr(pyfuncitem, "funcargs", None) > if funcargs is not None: > for name, capfuncarg in funcargs.items(): > if name in ('capsys', 'capfd'): > assert not hasattr(self, '_capturing_funcarg') > self._capturing_funcarg = capfuncarg >> capfuncarg._start() > > ../../.local/lib/python3.3/site-packages/_pytest/capture.py:128: > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > > self = <_pytest.capture.CaptureFixture object at 0x7f413ea47f10> > > def _start(self): >> self.capture.startall() > E AttributeError: 'CaptureFixture' object has no attribute 'capture' > > ../../.local/lib/python3.3/site-packages/_pytest/capture.py:209: > AttributeError > =============================== 1 failed, 1 passed, 1 error in 0.03 seconds > ================================ Can someone explain what's happening here? Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C _______________________________________________ Pytest-dev mailing list Pytest-dev@python.org http://mail.python.org/mailman/listinfo/pytest-dev