Trouble accessing captured stderr
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
(I somehow missed to reply to the list) On Tuesday 4 June 2013 at 07:03, Nikolaus Rath wrote:
@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)
Hi, This might not be the answer to your question, but you should be aware of this issue: https://bitbucket.org/hpk42/pytest/issue/287/fixture-finalizer-failure-cause... Raising exceptions in the fixture teardown will make other fixtures not being teared down, which can cause other tests to fail. Cheers Andreas
participants (2)
-
Andreas Pelme -
Nikolaus Rath