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
相关产品推荐
相关产品推荐

