pytest.raises上下文管理器中tokenize方法未执行的问题排查
解决生成器在pytest中未触发异常的问题
我一眼就看出问题所在了——你的tokenize方法返回的是生成器对象,而生成器函数在被调用时并不会立即执行函数体代码,它只会创建一个生成器实例,只有当你开始迭代这个生成器(比如用list()包裹、遍历它,或者调用next())的时候,才会真正执行里面的逻辑,进而触发可能存在的异常。
你的测试代码问题出在这:
with pytest.raises(SyntaxError): Tokenizer(source).tokenize()
这里你只是调用了tokenize()得到了生成器对象,但根本没去迭代它,所以tokenize方法里的代码一行都没执行,自然不会抛出异常,pytest就会提示你没捕获到预期的错误。
修复方案
只需要强制迭代生成器即可,最简单的方式是用list()把生成器转换成列表:
@pytest.mark.parametrize("source", SYNTAX_ERROR_SOURCES) def test_tokenize_fail_syntax_error(source: str) -> None: with pytest.raises(SyntaxError): # 强制迭代所有token,触发生成器内的逻辑 list(Tokenizer(source).tokenize())
或者你也可以手动遍历生成器:
@pytest.mark.parametrize("source", SYNTAX_ERROR_SOURCES) def test_tokenize_fail_syntax_error(source: str) -> None: with pytest.raises(SyntaxError): tokenizer = Tokenizer(source) for _ in tokenizer.tokenize(): pass
为什么脚本执行正常?
你在脚本里运行python tokenizer.py "a@b"时,应该是在代码里对生成器做了迭代操作(比如打印每个token、遍历处理等),这时候生成器的逻辑才会被执行,所以异常会正常抛出。
内容的提问来源于stack exchange,提问作者Lysandros Nikolaou
相关产品推荐
相关产品推荐

