Catch SystemExit message with Pytest

1.8k Views Asked by At

I am writing test using pytest. I have a case where some function throws SystemExit with some error message on terminal in case of wrong input.

I want to write test for the case when SystemExit is thrown and verify that there is specific string in the output error message.

Here's the code:


def test_validate_input():
  ...
  with pytest.raises(SystemExit) as error:
    _validate_function(test_wrong_input)
  assert error.value.code == 1

I am not able to get the output error message in error that I get on command line if I run the actual function the validate some input. Please let me know what I am missing here.

Edit:

I was calling a subprocess.call_output to run a command which was throwing the error. I have to add stderr=subprocess.STDOUT in the call_output call as an argument to get the error message. Then I used @p3j4p5's answer in my test.

2

There are 2 best solutions below

5
On BEST ANSWER

Pytest's raises() takes a match argument. The docs tell us:

If specified, a string containing a regular expression, or a regular expression object, that is tested against the string representation of the exception

and

This is only used when pytest.raises is used as a context manager

So it should be suitable for your case:

def test_validate_input():
  ...
  with pytest.raises(SystemExit, match='exception message content'):
      _validate_function(test_wrong_input)

This test will pass if the raised SystemExit exception has been raised with a message matching the provided regular expression, and will fail otherwise.

Alternatively, if you want to manually check the message:

The context manager produces an ExceptionInfo object which can be used to inspect the details of the captured exception

In your case, assuming that SystemExit is called with and integer (code) and a string (message) that would be:

def test_validate_input():
  ...
  with pytest.raises(SystemExit) as exc_info:
      _validate_function(test_wrong_input)

  assert exc_info.value.args[0] == 1
  assert exc_info.value.args[1] == 'exception message content'
2
On

If I understand correctly, your message is printed on stderr before SystemExit is raised, in this case you'll need capsys

def test_validate_input(capsys):
  ...
  with pytest.raises(SystemExit) as error:
      _validate_function(test_wrong_input)
  assert error.value.code == 1
  captured = capsys.readouterr()
  assert captured.err == "Expected error message\n"