Verify the error code or message from SystemExit in pytest

Question:

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 daten'
        sys.exit(-3)
Asked By: Robin Siebler

||

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 == "Foon"
    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 == "Foon"
E       assert 'Barn' == 'Foon'
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

Answered By: James Mills

James Mills’ answer doesn’t answer the question fully. capsys is the easy bit.

As mentioned in the comment by mvr, to get the exit code returned, do this:

with pytest.raises(SystemExit) as excinfo:
    run_something()

assert excinfo.value.code == 1
Answered By: mike rodent
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.