Pytest: Capsys doesn't correctly handle whitespace characters

Created on 1 Jun 2018  路  4Comments  路  Source: pytest-dev/pytest

I wrote this very simple function:

def reverse_array(array):
    print(' '.join(array[::-1]))

and relative unit-test:

import pytest

from mymodule.arrays import reverse_array


@pytest.mark.parametrize('array,expected', [
    ('0 1 2 3', '3 2 1 0\n'),
    ('1 4 3 2', '2 3 4 1\n')
])
def test_reverse_array(array, expected, capsys):
    reverse_array(array=array)
    assert capsys.readouterr().out == expected

I would expect the tests to pass but for some reason capsys is not correctly handling the whitespaces in the result. Here is the stdout:

=============================================================================== FAILURES ===============================================================================
________________________________________________________________ test_reverse_array[0 1 2 3-3 2 1 0\n] _________________________________________________________________

array = '0 1 2 3', expected = '3 2 1 0\n', capsys = <_pytest.capture.CaptureFixture object at 0x7fae49211588>

    @pytest.mark.parametrize('array,expected', [
        ('0 1 2 3', '3 2 1 0\n'),
        ('1 4 3 2', '2 3 4 1\n')
    ])
    def test_reverse_array(array, expected, capsys):
        reverse_array(array=array)
>       assert capsys.readouterr().out == expected
E       AssertionError: assert '3   2   1   0\n' == '3 2 1 0\n'
E         - 3   2   1   0
E         + 3 2 1 0

tests/test_reverse_array.py:12: AssertionError
________________________________________________________________ test_reverse_array[1 4 3 2-2 3 4 1\n] _________________________________________________________________

array = '1 4 3 2', expected = '2 3 4 1\n', capsys = <_pytest.capture.CaptureFixture object at 0x7fae492115c0>

    @pytest.mark.parametrize('array,expected', [
        ('0 1 2 3', '3 2 1 0\n'),
        ('1 4 3 2', '2 3 4 1\n')
    ])
    def test_reverse_array(array, expected, capsys):
        reverse_array(array=array)
>       assert capsys.readouterr().out == expected
E       AssertionError: assert '2   3   4   1\n' == '2 3 4 1\n'
E         - 2   3   4   1
E         + 2 3 4 1

tests/test_reverse_array.py:12: AssertionError
================================================================= 2 failed, 13 passed in 0.10 seconds ==================================================================

These are the package installed in my virtualenv:

$ pip freeze
atomicwrites==1.1.5
attrs==18.1.0
backcall==0.1.0
coverage==4.5.1
decorator==4.3.0
greenlet==0.4.13
-e [email protected]:IamGianluca/hackerrank.git@88637d616dd221ad120665f486fa11c80b59a38f#egg=hrank
ipdb==0.11
ipython==6.4.0
ipython-genutils==0.2.0
jedi==0.12.0
more-itertools==4.2.0
msgpack==0.5.6
neovim==0.2.6
parso==0.2.1
pexpect==4.5.0
pickleshare==0.7.4
pluggy==0.6.0
prompt-toolkit==1.0.15
ptyprocess==0.5.2
py==1.5.3
Pygments==2.2.0
pytest==3.6.0
pytest-cov==2.5.1
simplegeneric==0.8.1
six==1.11.0
traitlets==4.3.2
wcwidth==0.1.7
question

Most helpful comment

You're right! I'm closing the issue. Thanks for your help @asottile

All 4 comments

GitMate.io thinks possibly related issues are https://github.com/pytest-dev/pytest/issues/1553 (Assert diff does not handle newline), https://github.com/pytest-dev/pytest/issues/1996 (Warnings handling), https://github.com/pytest-dev/pytest/issues/3207 (capsys does not follow the OS newline rules for print), https://github.com/pytest-dev/pytest/issues/439 (capsys fixture does not collect the same test output as reported by pytest), and https://github.com/pytest-dev/pytest/issues/353 (py.test doesn't expose that an exception occurred while handling another).

The output looks to be what I expect at least -- do you mean to have your "array" be a string or are you forgetting a .split() or ?

>>> def reverse_array(array):
...     return ' '.join(array[::-1])
... 
>>> reverse_array('1 2 3')
'3   2   1'
>>> reverse_array('123')
'3 2 1'
>>> # how I think you mean to implement this
... def reverse_array(array):
...     return ' '.join(array.split()[::-1])
... 
>>> reverse_array('1 2 3')
'3 2 1'
>>> reverse_array('123')
'123'
>>> reverse_array('hello world')
'world hello'

Note that I've changed print to return so it's more clear what's going on :)

You're right! I'm closing the issue. Thanks for your help @asottile

you may also find reversed helpful for your endeavors as well ;)

Was this page helpful?
0 / 5 - 0 ratings