【问题标题】:In pytest, how to test for sys.exit('some error message')?在 pytest 中,如何测试 sys.exit(\'some error message\')?
【发布时间】:2022-12-15 21:33:27
【问题描述】:

我是 python 和 pytest 的初学者。我有一个函数,我正在尝试使用 Pytest 测试异常部分:

def read_data(args) -> tuple[Polyline, str]:
    parsed_args = input_parsing_1(args)
    try:
        with open(parsed_args.f) as f_input:
            reader = csv.reader(f_input)
            polyline = fill_poly_with_data(reader)
    except FileNotFoundError as e:
        sys.exit('Invalid input file \n')
    else:
        return (polyline, parsed_args.f)

我想测试是否出现异常以及错误消息是否与我在上面的代码中输入的消息匹配。

我的尝试

@patch('project.open')
def test_read_data_error_SE(mock_open):
    mock_open.side_effect = SystemExit
    with pytest.raises(SystemExit):
        assert read_data(['-f', ''])

@patch('project.open')
def test_read_data_error_FNFE2(mock_open):
    mock_open.side_effect = FileNotFoundError
    with pytest.raises(SystemExit):
        with pytest.raises(FileNotFoundError):
            assert read_data(['-f', 'cos'])

上述测试工作正常。

我还想断言 sys.exit 消息是否与 'Invalid input file \n' 匹配。我试过了:


@patch('project.open')
def test_read_data_error_SE1(mock_open):
    mock_open.side_effect = SystemExit
    with pytest.raises(SystemExit, match='Invalid input file'):
        assert read_data(['-f', ''])

@patch('project.open')
def test_read_data_error_SE2(mock_open):
    mock_open.side_effect = SystemExit
    with pytest.raises(SystemExit) as e:
        assert read_data(['-f', ''])
    assert 'Invalid input file' in str(e.value)

但这些测试失败了:

===================================================== short test summary info ======================================================
FAILED test_project.py::test_read_data_error_SE1 - AssertionError: Regex pattern did not match.
FAILED test_project.py::test_read_data_error_SE2 - AssertionError: assert 'Invalid input file' in ''

我在 stackoverflow 上看到了一些帖子,例如: Verify the error code or message from SystemExit in pytest

How to properly assert that an exception gets raised in pytest?

Catch SystemExit message with Pytest

但他们似乎都没有回答我的问题。

我的问题:

似乎我测试过的消息“无效输入文件”正在与空字符串“”匹配?为什么?如何正确捕获并断言 sys.exit('some error message')?

【问题讨论】:

    标签: python-3.x pytest systemexit


    【解决方案1】:

    您看到一个空字符串,因为您在没有参数的情况下引发 SystemExit:

    @patch('project.open')
    def test_read_data_error_SE1(mock_open):
        mock_open.side_effect = SystemExit
        with pytest.raises(SystemExit, match='Invalid input file'):
            assert read_data(['-f', ''])
    

    你已经设置了mock_open.side_effect = SystemExit,所以当你代码调用open()时,它会在没有参数的情况下引发SystemExit。如果你想看到类似 Invalid input file 的消息,请通过调用 sys.exit('Invalid input file') 显式退出你的代码。

    你的代码已经这样做了,但是您通过调用 open raise SystemExit 来先发制人。你可能希望 open 改为提高 FileNotFound

    @patch('project.open')
    def test_read_data_error_SE1(mock_open):
        mock_open.side_effect = FileNotFound
        with pytest.raises(SystemExit, match='Invalid input file'):
            assert read_data(['-f', ''])
    

    这将被read_data中的except捕获,然后调用sys.exit

    【讨论】:

      【解决方案2】:

      你想要猴子补丁 sys.exit

      import sys
      def foo(txt):
          return txt
      sys.exit = foo
      
      @patch('project.open')
      def test_read_data_error_SE2(mock_open):
          assert read_data(['-f', '']) == 'Invalid input file 
      '
          
      

      https://www.geeksforgeeks.org/monkey-patching-in-python-dynamic-behavior/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-11
        • 2013-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-30
        相关资源
        最近更新 更多