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

Using capsys in fixtures: AttributeError: 'CaptureFixture' object has no attribute '_capture' #2709

Closed
hroncok opened this Issue Aug 22, 2017 · 6 comments

Comments

Projects
None yet
4 participants
@hroncok
Member

hroncok commented Aug 22, 2017

Recently, I had a workshop about parametric tests and fixtures in pytest. As one of the examples I tried to use the capsys fixture inside my own and failed. I wonder if it's a bug or documented behavior I couldn't find.

First, working code

def test_print(capsys):
    print(123, 456, 789)
    out, err = capsys.readouterr()
    assert not err.strip()
    assert '5' in out
$ python -m pytest demo.py 
... 1 passed in 0.01 seconds ...

Broken code

Now I don't like multiple assertions in one test, so let's create a fixture and split it:

import pytest

OUT = 0
ERR = 1


@pytest.fixture
def captured_print(capsys):
    print(123, 456, 789)
    out, err = capsys.readouterr()
    return out.strip(), err.strip()


def test_print_no_stderr(captured_print):
    assert not captured_print[ERR]


def test_print_stdout_contains_5(captured_print):
    assert '5' in captured_print[OUT]

I think this should work. At least, it feels like a natural way of doing it. But it blows up:

$ python -m pytest demo.py 
... AttributeError: 'CaptureFixture' object has no attribute '_capture' ...
Full output
============================= test session starts ==============================
platform linux -- Python 3.6.2, pytest-3.2.2.dev17+g539523cf, py-1.4.34, pluggy-0.4.0
rootdir: /home/churchyard/Dokumenty/pytest, inifile: tox.ini
collected 2 items                                                               

demo.py EE

==================================== ERRORS ====================================
____________________ ERROR at setup of test_print_no_stderr ____________________

self = <_pytest.capture.CaptureFixture object at 0x7fe560f30c50>

    def readouterr(self):
        try:
>           return self._capture.readouterr()
E           AttributeError: 'CaptureFixture' object has no attribute '_capture'

../_pytest/capture.py:208: AttributeError

During handling of the above exception, another exception occurred:

capsys = <_pytest.capture.CaptureFixture object at 0x7fe560f30c50>

    @pytest.fixture
    def captured_print(capsys):
        print(123, 456, 789)
>       out, err = capsys.readouterr()

demo.py:10: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_pytest.capture.CaptureFixture object at 0x7fe560f30c50>

    def readouterr(self):
        try:
            return self._capture.readouterr()
        except AttributeError:
>           return self._outerr
E           AttributeError: 'CaptureFixture' object has no attribute '_outerr'

../_pytest/capture.py:210: AttributeError
---------------------------- Captured stdout setup -----------------------------
123 456 789
________________ ERROR at setup of test_print_stdout_contains_5 ________________

self = <_pytest.capture.CaptureFixture object at 0x7fe560f6a358>

    def readouterr(self):
        try:
>           return self._capture.readouterr()
E           AttributeError: 'CaptureFixture' object has no attribute '_capture'

../_pytest/capture.py:208: AttributeError

During handling of the above exception, another exception occurred:

capsys = <_pytest.capture.CaptureFixture object at 0x7fe560f6a358>

    @pytest.fixture
    def captured_print(capsys):
        print(123, 456, 789)
>       out, err = capsys.readouterr()

demo.py:10: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_pytest.capture.CaptureFixture object at 0x7fe560f6a358>

    def readouterr(self):
        try:
            return self._capture.readouterr()
        except AttributeError:
>           return self._outerr
E           AttributeError: 'CaptureFixture' object has no attribute '_outerr'

../_pytest/capture.py:210: AttributeError
---------------------------- Captured stdout setup -----------------------------
123 456 789
=========================== 2 error in 0.06 seconds ============================

System information

$ python --version
Python 3.6.2

$ pip freeze
py==1.4.34
-e git://github.com/pytest-dev/pytest.git@539523cfee4c49a765569abcf68134b1255eedb5#egg=pytest

# also happens on 3.2.1

$ uname
Linux

$ uname -m
x86_64

$ head -n2 /etc/os-release 
NAME=Fedora
VERSION="26 (Twenty Six)"
@nicoddemus

This comment has been minimized.

Member

nicoddemus commented Aug 22, 2017

Hi @hroncok thanks for the report!

To me it is a bug; if using capsys from fixtures cannot be supported at least it should provide a better error message.

@ApaDoctor

This comment has been minimized.

Contributor

ApaDoctor commented Sep 22, 2017

@nicoddemus
In the first code _capture method exists with in CaptureFixture all time starting from the begining(function declaration)
In the first example _capture doesn't exist.
_capture method inits in _start.
_start called in CaptureManager
Next steps is hard to discover.
So what the solution of this problem?
Just to correct error message?
What is your recomendation?

@hroncok

This comment has been minimized.

Member

hroncok commented Sep 22, 2017

I'm deeply sorry, but I don't understand what are you trying to say. Could you please be a little bit more verbose?

@ApaDoctor

This comment has been minimized.

Contributor

ApaDoctor commented Sep 22, 2017

@hroncok
Oh, this question wasn't for you)
I forgot to add direct mention)

@nicoddemus

This comment has been minimized.

Member

nicoddemus commented Sep 26, 2017

@ApaDoctor I have a working fix, I will prepare a PR later today. Thanks for the interest, your question forced me to study the code and I ended up finding a solution.

@hroncok

This comment has been minimized.

Member

hroncok commented Oct 9, 2017

Thanks for fixing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment