You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python unittest无法捕获try/except包裹的异常问题求助

问题

我写了一个检测CSV空白单元格的方法blank_cell,发现空白单元格时会抛出BlankCellError,但这个异常被方法内部的try/except捕获并打印了信息。用pytest写测试用例时,想用pytest.raises断言异常抛出,但测试一直失败,提示DID NOT RAISE <class 'src.csv_methods.BlankCellError'>,明明方法确实触发了异常,也输出了日志和打印内容,修改测试代码后还是不行。

pytest输出

====================================================================================================== FAILURES ======================================================================================================
___________________________________________________________________________________ TestCSVFileMethods.test_verify_cell_not_blank ____________________________________________________________________________________

    self = <tests.test_csv_methods.TestCSVFileMethods testMethod=test_blank_cell>
    
        def test_blank_cell(self):
            # Add another entry to the name column with a blank value
            with open(self.temp_file, "a", newline="") as f:
                writer = csv.DictWriter(f, fieldnames=["id","name"])
                writer.writerow({"id": "2", "name": ""})
    
>       with pytest.raises(BlankCellError):
E       Failed: DID NOT RAISE <class 'src.csv_methods.BlankCellError'>

tests/test_csv_methods.py:161: Failed
------------------------------------------------------------------------------------------------ Captured stdout call ------------------------------------------------------------------------------------------------
BlankCell: Missing cell value for ID: '2' - 'Column: name'
------------------------------------------------------------------------------------------------- Captured log call --------------------------------------------------------------------------------------------------
WARNING  root:csv_methods.py:294 Missing cell value for ID: '2' - 'Column: name'
Missing cell value for ID: '2' - 'Column: name'
============================================================================================== short test summary info ===============================================================================================
FAILED tests/test_csv_methods.py::TestCSVFileMethods::test_blank_cell - Failed: DID NOT RAISE <class 'src.csv_methods.BlankCellError'>
============================================================================================ 1 failed, 6 passed in 0.10s ============================================================================================

异常类及方法代码

class BlankCellError(Exception):
        pass

csv_file = "csv_data/assets.csv"
def blank_cell(csv_file):
    try:
        with open(csv_file, newline="") as file:
            reader = csv.DictReader(file)

            for row_idx, row_v in enumerate(reader, start=1):  # Start at 1 to skip the csv column headers
                for k, v in row_v.items():
                    if v.strip() == "":
                        raise BlankCellError(f"Missing cell value for ID: '{row_v['id']}' - 'Column: {k}'")
                    else:
                        continue

    except BlankCellError as e:
        print(f"BlankCell: {e}")

测试代码(更新后)

import csv
import unittest
import pytest
    
def create_test_file(file_name, content):
    with open(file_name, "a") as f:
        writer = csv.DictWriter(f, fieldnames=["id","name"])
        writer.writeheader()
        writer.writerows(content)
        
class TestCSVFileMethods(unittest.TestCase):
    def setUp(self):
        self.data = [
            {
                "id": "1",
                "name": "name1"
            },
        ]
        self.temp_file = os.path.join("tests", "tmp_csv.csv")
        create_test_file(self.temp_file, self.data)
    
    def test_blank_cell(self):
        # Add another entry to the name column with a blank value
        with open(self.temp_file, "a", newline="") as f:
            writer = csv.DictWriter(f, fieldnames=["id","name"])
            writer.writerow({"id": "2", "name": ""})

        with pytest.raises(BlankCellError) as excinfo:  
            blank_cell(self.temp_file)  
        assert str(excinfo.value) == "Missing cell value for ID"  

更新后错误输出:

E       Failed: DID NOT RAISE <class 'src.csv_methods.BlankCellError'>
原因

核心问题出在blank_cell方法内部:你在方法里用try/except捕获了自己抛出的BlankCellError,并且只做了打印操作,没有把异常重新抛出到方法外部。这样当测试代码调用blank_cell时,方法执行完后不会向外传递任何异常,pytest.raises自然捕获不到。

解决办法

有两种可选方案,根据你的需求选择:

方案1:修改方法,让异常向外抛出

如果你的设计意图是让blank_cell发现空白单元格时抛出异常,由调用方处理,那需要在捕获异常后重新抛出:

def blank_cell(csv_file):
    try:
        with open(csv_file, newline="") as file:
            reader = csv.DictReader(file)

            for row_idx, row_v in enumerate(reader, start=1):
                for k, v in row_v.items():
                    if v.strip() == "":
                        raise BlankCellError(f"Missing cell value for ID: '{row_v['id']}' - 'Column: {k}'")
    except BlankCellError as e:
        print(f"BlankCell: {e}")
        raise  # 重新抛出异常,让外部能捕获到

这样修改后,测试代码里的pytest.raises就能正常捕获到异常,测试会通过。

方案2:保留方法内部处理,修改测试逻辑

如果你的设计就是让blank_cell自己处理异常(只打印不抛出),那测试就不需要断言异常,而是断言打印的内容或者日志输出:

def test_blank_cell(self):
    with open(self.temp_file, "a", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=["id","name"])
        writer.writerow({"id": "2", "name": ""})
    
    # 捕获标准输出,检查打印内容
    captured = capsys.readouterr()
    blank_cell(self.temp_file)
    assert "BlankCell: Missing cell value for ID: '2' - 'Column: name'" in captured.out
    
    # 或者检查日志输出
    import logging
    logger = logging.getLogger("root")
    with self.assertLogs(logger, level="WARNING") as log_context:
        blank_cell(self.temp_file)
        self.assertIn("Missing cell value for ID: '2' - 'Column: name'", log_context.output[0])

内容的提问来源于stack exchange,提问作者Luca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 07:15:14