如何用Pytest测试含用户输入并调用其他函数的Python函数?
用Pytest测试基于用户输入的页面式函数
当然可以用Pytest测试这类函数,而且不需要大改你的现有架构——核心是搞定用户输入的模拟问题就行。下面直接给你具体实现方案和优化建议:
核心思路:模拟用户输入
你的函数依赖input()获取用户输入,这是外部交互,没法直接在测试里手动输入。Pytest的monkeypatch fixture可以帮你替换掉系统的input函数,让它返回你预设的测试值;另外用pytest-mock(Pytest的插件,需先通过pip install pytest-mock安装)可以验证目标函数是否被正确调用。
先给你的示例函数补全基础代码:
def go_back(): pass # 实际返回上一页的逻辑 def save(): pass # 实际保存逻辑 def func(): choice = input("Enter choice (b/s): ") if choice == "b": go_back() elif choice == "s": save() else: raise ValueError("Invalid Input")
具体测试用例
1. 测试输入"b"时调用go_back()
def test_func_triggers_go_back(monkeypatch, mocker): # 把系统input替换成返回"b"的函数 monkeypatch.setattr('builtins.input', lambda _: 'b') # 模拟go_back函数,用来验证是否被调用 mock_go_back = mocker.patch('__main__.go_back') func() # 断言go_back确实被调用了一次 mock_go_back.assert_called_once()
2. 测试输入"s"时调用save()
def test_func_triggers_save(monkeypatch, mocker): monkeypatch.setattr('builtins.input', lambda _: 's') mock_save = mocker.patch('__main__.save') func() mock_save.assert_called_once()
3. 测试无效输入抛出异常
import pytest def test_func_invalid_input_raises_error(monkeypatch): monkeypatch.setattr('builtins.input', lambda _: 'x') # 断言调用func时会抛出指定的ValueError with pytest.raises(ValueError, match="Invalid Input"): func()
可选的架构优化(非必须,但测试更省心)
如果后续页面函数越来越多,你可以把输入获取逻辑和业务逻辑分开,这样测试会更简洁:
- 让页面函数接收输入参数,而不是自己调用
input() - 单独写个入口函数处理用户输入,再调用页面函数
比如调整后的代码:
def func(choice): if choice == "b": go_back() elif choice == "s": save() else: raise ValueError("Invalid Input") # 专门处理输入的入口 def run_func(): choice = input("Enter choice (b/s): ") func(choice)
这样测试func时就不用管input了,直接传参数就行:
def test_func_go_back(mocker): mock_go_back = mocker.patch('__main__.go_back') func("b") mock_go_back.assert_called_once()
这种分离的方式也让代码职责更清晰,后续维护和测试都更方便。
总结
- 完全可以用Pytest测试这类依赖用户输入的函数,核心是模拟
input并验证函数行为 - 现有架构不需要强制调整,但分离输入和业务逻辑能提升测试效率
- 测试的重点是验证函数的行为(调用对应函数、抛出异常),而不是必须要有返回值
内容的提问来源于stack exchange,提问作者Sadegh Mousawi
相关产品推荐
相关产品推荐

