(This was discussed #167 but got side-tracked)
Proposal to disable capturing from within a test:
def test_foo(capsys):
print('captured')
with capsys.disabled():
print('directly to stdout, regardless of the "-s" flag')
print('captured again')
Optionally, provide a marker which does the same job:
@pytest.mark.capture_disabled
def test_foo():
print('directly to stdout, regardless of the "-s" flag')
@nicoddemus The with syntax is very nice - but only works on a function level and not a class level. Can this be changed?
It works just fine on methods as well. Could you post an example of what you are seeing?
@nicoddemus
python
ScopeMismatch: You tried to access the 'function' scoped fixture 'capsys' with a 'class' scoped request object, involved factories
lib.macosx-10.6-x86_64-2.7/tardis/tests/integration_tests/test_integration.py:24: def setup(self, request, reference, data_path, capsys)
Ahh sorry I though you meant functions vs methods. 馃槄
Unfortunately no. We plan to have a new scope for fixtures called "invocation" which would allow this kind of thing (#1794), but unfortunately it had to be pulled off at the last minute because it contained a serious flaw on it.
@nicoddemus so how can I do this now? is there a way instead of using -s for this purpose?
I thought on a workaround: copy pytest's implementation, name it capsys_class and change the scope of the fixture to class. But unfortunately it didn't work.
Could you describe in more details why you need that functionality in a class-scoped fixture? We might have other suggestions on how to accomplish it.
We are testing data generated with this function: https://github.com/tardis-sn/tardis/blob/master/tardis/tests/integration_tests/test_integration.py#L77 and want to make sure that we see what happens when it runs (it takes a long time to run).
Oh I see. I can't think of a workaround for that, sorry.
@nicoddemus thanks for looking into this. Well, can I somehow enable -s when I switch on a different command line option within the code?
Found a solution 馃榿
class Test:
@pytest.fixture(scope='class')
def setup(self, pytestconfig):
capmanager = pytestconfig.pluginmanager.getplugin('capturemanager')
capmanager.suspendcapture()
print('hello from class')
capmanager.resumecapture()
def test_foo(self, setup):
print('cannot see me')
============================= test session starts =============================
platform win32 -- Python 3.5.0, pytest-3.1.0.dev0, py-1.4.31, pluggy-0.4.0
rootdir: C:\pytest, inifile: tox.ini
plugins: hypothesis-3.5.0
collected 1 items
.tmp\demo-b\test_foo3.py hello from class
.
========================== 1 passed in 0.01 seconds ===========================
Caveats: uses internal pytest objects, so this may break in the future. Other than that, is exactly what pytest does internally so it should work fine.
@nicoddemus thanks - that's the one!!
Whoever may stumble on this useful technique, please be aware that in the meantime capmanager.suspendcapture and capmanager.resumecapture were renamed to capmanager.suspend_global_capture and capmanager.resume_global_capture, respectively.
@pytest.fixture(scope='class')
def suspend_capture(pytestconfig):
class suspend_guard:
def __init__(self):
self.capmanager = pytestconfig.pluginmanager.getplugin('capturemanager')
def __enter__(self):
self.capmanager.suspend_global_capture(in_=True)
pass
def __exit__(self, _1, _2, _3):
self.capmanager.resume_global_capture()
yield suspend_guard()
def test_input(suspend_capture):
with suspend_capture:
input("hello")
Most helpful comment
Found a solution 馃榿
Caveats: uses internal pytest objects, so this may break in the future. Other than that, is exactly what pytest does internally so it should work fine.