Search code examples
pythonpython-3.xpytestsystemexit

Catch SystemExit message with Pytest


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.


Solution

  • 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'