Pytest的pytest.raises(ValueError)无法检测抛出异常问题解决
Pytest未检测到预期抛出的ValueError?试试重载模块
如果你碰到这种情况:直接调用函数时会正常抛出ValueError,但用Pytest测试时却提示DID NOT RAISE <class 'Exception'>,那大概率是模块没有重载,测试用的还是旧版本的代码。
问题还原
我要测试的read_file函数会在解析无效JSON时抛出ValueError:
# foo.py import json def read_file(input_file): try: with open(input_file, "r", encoding='utf-8') as reader: pre_input_data = json.load(reader) except ValueError: raise ValueError
测试函数逻辑很简单,就是验证传入无效JSON文件时会抛出ValueError:
# test_foo.py import pytest from foo import read_file def test_read_file(): with pytest.raises(ValueError): read_file("invalidJsonFile.json")
直接调用read_file("invalidJsonFile.json")会正常报错:
Invalid json file: Expecting value: line 1 column 1 (char 0)
但运行测试时却失败了,报错信息显示明明函数抛出了错误,Pytest却没捕获到:
test_read_file() Invalid json file: Expecting value: line 1 column 1 (char 0) --------------------------------------------------------------------------- Failed Traceback (most recent call last) <ipython-input-47-c42b81670a67> in <module>() ----> 1 test_read_file() 2 frames <ipython-input-46-178e6c645f01> in test_read_file() 1 def test_read_file(): 2 with pytest.raises(Exception): ----> 3 read_file("invalidJsonFile.json") /usr/local/lib/python3.6/dist-packages/_pytest/python_api.py in __exit__(self, *tp) 727 __tracebackhide__ = True 728 if tp[0] is None: --> 729 fail(self.message) 730 self.excinfo.__init__(tp) 731 suppress_exception = issubclass(self.excinfo.type, self.expected_exception) /usr/local/lib/python3.6/dist-packages/_pytest/outcomes.py in fail(msg, pytrace) 115 """ 116 __tracebackhide__ = True --> 117 raise Failed(msg=msg, pytrace=pytrace) 118 119 Failed: DID NOT RAISE <class 'Exception'>
问题原因
这是因为Python会缓存导入的模块,如果你修改了read_file函数的代码(比如之前没有正确抛出ValueError,后来修改了),但没有重新重载模块,测试代码依然在使用缓存里的旧版本函数,自然就会出现"函数明明报错,但测试没检测到"的矛盾情况。
解决方案
解决方法很简单,就是在测试前手动重载包含目标函数的模块,确保测试使用的是最新代码。
你可以在运行测试前执行这段代码重载模块:
import sys import importlib importlib.reload(sys.modules['foo']) # 替换成你的模块名 from foo import read_file
或者直接把重载逻辑加到测试文件的开头:
import pytest import sys import importlib # 重载模块,确保用的是最新的函数代码 importlib.reload(sys.modules['foo']) from foo import read_file def test_read_file(): with pytest.raises(ValueError): read_file("invalidJsonFile.json")
这样再运行测试,Pytest就能正确捕获到函数抛出的ValueError了。
内容的提问来源于stack exchange,提问作者SantoshGupta7
相关产品推荐
相关产品推荐

