使用pytest测试持续循环场景下输入触发预期方法调用的方案
实现方案
你可以根据测试目标选择以下两种方案,均可以规避无限循环/输入阻塞问题:
方案1:仅验证method_a是否触发method_b调用(单元测试推荐)
单元测试需要保证被测逻辑的隔离性,你可以直接mock掉method_b,完全不执行它的真实内部逻辑,自然不会触发input请求和循环问题。
实现逻辑:
- 模拟
input返回jump触发method_a的对应分支 - 给
method_b绑定中断异常作为副作用,只要method_b被调用就终止后续执行,避免method_a递归死循环 - 最终断言
method_b被调用1次即可
示例测试代码(基于pytest):
import pytest from unittest.mock import MagicMock from your_module import TwoInputs # 替换为实际的模块导入路径 # 自定义测试用中断异常 class TestInterrupt(Exception): pass def test_method_a_triggers_method_b(monkeypatch): # 模拟input固定返回jump monkeypatch.setattr("builtins.input", lambda _: "jump") test_obj = TwoInputs() # 只要调用method_b就抛出中断异常,终止流程 test_obj.method_b = MagicMock(side_effect=TestInterrupt) # 捕获中断异常 with pytest.raises(TestInterrupt): test_obj.method_a() # 验证method_b确实被调用了1次 test_obj.method_b.assert_called_once()
方案2:验证执行到method_b的输入提示
如果你需要确认程序确实运行到了method_b的输入环节,可以给input设置序列返回值,覆盖完整执行流程的所有输入需求:
- 第一个返回值
jump:触发method_a调用method_b - 第二个返回值
1:命中method_b的正确分支,退出内部循环 - 第三个返回值
exit:让递归调用的method_a触发退出,避免无限递归
同时可以断言input的调用参数,确认第二个输入提示符合预期。
示例测试代码:
import pytest from unittest.mock import call from your_module import TwoInputs def test_reach_method_b_input(monkeypatch): # 按调用顺序设置input的返回值 input_mock = MagicMock(side_effect=["jump", "1", "exit"]) monkeypatch.setattr("builtins.input", input_mock) # mock quit避免测试进程被终止 monkeypatch.setattr("builtins.quit", lambda: None) test_obj = TwoInputs() test_obj.method_a() # 验证input的调用顺序和提示文本符合预期 input_mock.assert_has_calls([ call("Enter something: "), call("Enter some other thing: "), call("Enter something: ") ])
内容的提问来源于stack exchange,提问作者longvandyke
相关产品推荐
相关产品推荐

