Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to disable capture from within a test #1599

Closed
nicoddemus opened this issue Jun 8, 2016 · 13 comments
Closed

Ability to disable capture from within a test #1599

nicoddemus opened this issue Jun 8, 2016 · 13 comments
Labels
plugin: capture related to the capture builtin plugin type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature

Comments

@nicoddemus
Copy link
Member

(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 nicoddemus added type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature plugin: capture related to the capture builtin plugin labels Jun 8, 2016
nicoddemus added a commit to nicoddemus/pytest that referenced this issue Jun 8, 2016
nicoddemus added a commit to nicoddemus/pytest that referenced this issue Jun 9, 2016
nicoddemus added a commit to nicoddemus/pytest that referenced this issue Jun 19, 2016
@wkerzendorf
Copy link

@nicoddemus The with syntax is very nice - but only works on a function level and not a class level. Can this be changed?

@nicoddemus
Copy link
Member Author

It works just fine on methods as well. Could you post an example of what you are seeing?

@wkerzendorf
Copy link

@nicoddemus

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)```

@nicoddemus
Copy link
Member Author

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.

@wkerzendorf
Copy link

@nicoddemus so how can I do this now? is there a way instead of using -s for this purpose?

@nicoddemus
Copy link
Member Author

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.

@wkerzendorf
Copy link

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).

@nicoddemus
Copy link
Member Author

Oh I see. I can't think of a workaround for that, sorry.

@wkerzendorf
Copy link

@nicoddemus thanks for looking into this. Well, can I somehow enable -s when I switch on a different command line option within the code?

@nicoddemus
Copy link
Member Author

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.

@wkerzendorf
Copy link

@nicoddemus thanks - that's the one!!

@bilderbuchi
Copy link
Contributor

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.

@earonesty
Copy link
Contributor

@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")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: capture related to the capture builtin plugin type: proposal proposal for a new feature, often to gather opinions or design the API around the new feature
Projects
None yet
Development

No branches or pull requests

4 participants