我是巨 Python 和巨 Python 的初学者.我有一个函数,我正在try 用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)

我想测试是否引发了异常,以及错误消息是否与我在上面的代码中输入的消息匹配.

My attempts

@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

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

My questions:

我测试过的消息‘INVALID INPUT FILE’似乎正在与空字符串‘’匹配?为什么?如何正确捕获和断言sys.exit("一些错误消息")?

推荐答案

您看到的是一个空字符串,因为您在不带参数的情况下引发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')让您的代码显式退出.

您的代码already does that,但您通过让对open的调用提升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.

下面是一个完整的示例(我在这里包含了一些存根函数,这样我就可以使用您的read_data方法,基本上不加修改):

import csv
import sys
import types
import pytest

from unittest import mock

def fill_poly_with_data(x):
    return x

def input_parsing_1(args):
    return types.SimpleNamespace(f="testing")

def read_data(args) -> tuple:
    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:
        sys.exit('Invalid input file \n')
    else:
        return (polyline, parsed_args.f)

@mock.patch('builtins.open')
def test_function_that_exits(mock_open):
    mock_open.side_effect = FileNotFoundError
    with pytest.raises(SystemExit, match="Invalid input file"):
        read_data(['-f', 'cos'])

Python-3.x相关问答推荐

网站抓取:当我使用Chrome DevTools中的网络选项卡时,找不到正确的URL来提供我想要的数据

如何在当前测试中使用fixture 转换后的数据进行参数化?

我无法直接在 VSCode 中运行该程序,但可以使用 VScode 中的终端运行它

aiogram机器人中处理文本输入异常而不是按钮点击的回调函数.

一起使用数据类和枚举

根据按不同列中的值分组的平均值划分 DataFrame

仅当从 USB 摄像头接收到新图像时才处理图像

Seaborn:注释线性回归方程

你如何表达一个没有参数的 Python Callable?

Pytorch 的随机 Select ?

无法在 macOS 上的 Anaconda3 python3.6 上安装 OpenCV3

Python 错误:IndexError:字符串索引超出范围

pandas 中 df.reindex() 和 df.set_index() 方法的区别

if 语句中冒号的语法错误

如何找出从哪个模块导入名称?

是否在未完成初始化的对象上调用了 del?

无论如何我可以在 Google colaboratory 中下载文件吗?

在 Alembic 迁移期间更新列内容

TypeError:只有整数标量数组可以转换为标量索引

将 Python 字节转换为无符号 8 位整数