Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verify the error code or message from SystemExit in pytest

Tags:

python

pytest

According to the pytest documentation, I can assert that a SystemExit() occurs, but I want to do more: I also want to verify the exit code and any messages. I tried the below code, but nothing prints and I'm not sure what I would need to assert to prove that I got the right error code.

    with pytest.raises(SystemExit):
        docopt_args = validate_args(docopt_args)
        out, err = pytest.capsys.readouterr()
        assert out == 'Foo'
        print out, err

When I run my test, it passes, but that is it. Nothing is printed and I don't get an assert error.

The code I expect to be executed is:

        print '\n' + docopt_args['-d'] + ' is not a valid date\n'
        sys.exit(-3)
like image 276
Robin Siebler Avatar asked May 15 '15 09:05

Robin Siebler


1 Answers

This works with the latest pytest:

All you need to do is run pytest with the --capture=sys option and dependent the assertion outside of the raises() context (this bit is important for some reason!)

Example:

#!/usr/bin/env python

from __future__ import print_function

import pytest


def f(code=0):
    print("Foo")
    raise SystemExit(code)


def test_f(capsys):
    with pytest.raises(SystemExit):
        f()
    out, err = capsys.readouterr()
    assert out == "Foo\n"
    print(out, err)

Demo:

$ py.test -v --capture=sys test_foo.py 
======================================= test session starts ========================================
platform linux2 -- Python 2.7.9 -- py-1.4.27 -- pytest-2.7.0 -- /home/prologic/.virtualenvs/test/bin/python
rootdir: /home/prologic/tmp, inifile: 
collected 1 items 

test_foo.py::test_f PASSED

===================================== 1 passed in 0.00 seconds =====================================

Changing the print("Foo") to print("Bar") results in:

$ py.test -v --capture=sys test_foo.py 
======================================= test session starts ========================================
platform linux2 -- Python 2.7.9 -- py-1.4.27 -- pytest-2.7.0 -- /home/prologic/.virtualenvs/test/bin/python
rootdir: /home/prologic/tmp, inifile: 
collected 1 items 

test_foo.py::test_f FAILED

============================================= FAILURES =============================================
______________________________________________ test_f ______________________________________________

capsys = <_pytest.capture.CaptureFixture instance at 0x7f2729405518>

    def test_f(capsys):
        with pytest.raises(SystemExit):
            f()
        out, err = capsys.readouterr()
>       assert out == "Foo\n"
E       assert 'Bar\n' == 'Foo\n'
E         - Bar
E         + Foo

test_foo.py:17: AssertionError
===================================== 1 failed in 0.01 seconds =====================================

Which I think is exactly what you were after!

I did this in a clean virtualenv:

mkvirtualenv test
pip install pytest

The trick here is to read and understand Setting capturing methods or disabling capturing

like image 104
James Mills Avatar answered Sep 19 '22 04:09

James Mills