You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试调用含输入交互函数的Python业务功能?

解决delete_booking测试时模拟输入失效的问题

一、最快解决:直接模拟confirm_choice的返回值

既然你已经完成了confirm_choice的单元测试,测试delete_booking时完全不需要关心它内部怎么获取用户输入——只需要验证当confirm_choice返回True/False时,delete_booking的行为是否符合预期即可。

假设你的代码结构如下:

# 模块:booking_ops.py
def confirm_choice():
    while True:
        resp = input("确认删除?(Y/N): ").strip().upper()
        if resp == 'Y':
            return True
        elif resp == 'N':
            return False

def delete_booking(booking_id):
    if confirm_choice():
        # 执行CSV删除逻辑
        print(f"删除预订{booking_id}")
        return True
    else:
        print("取消删除")
        return False

测试时用unittest.mock.patch直接替换delete_booking调用的confirm_choice:

import unittest
from unittest.mock import patch
from booking_ops import delete_booking

class TestDeleteBooking(unittest.TestCase):
    @patch('booking_ops.confirm_choice')
    def test_delete_confirmed(self, mock_confirm):
        # 模拟用户确认操作
        mock_confirm.return_value = True
        result = delete_booking("BK-001")
        self.assertTrue(result)
        # 可选:断言确认函数被调用过一次
        mock_confirm.assert_called_once()

    @patch('booking_ops.confirm_choice')
    def test_delete_canceled(self, mock_confirm):
        # 模拟用户取消操作
        mock_confirm.return_value = False
        result = delete_booking("BK-001")
        self.assertFalse(result)
        mock_confirm.assert_called_once()

if __name__ == '__main__':
    unittest.main()

注意:patch的路径必须是delete_booking实际引用confirm_choice的路径——如果两者在同一个模块,路径就是模块名+函数名;如果delete_booking是从其他模块导入的confirm_choice,要patchdelete_booking所在模块里的confirm_choice引用,而非原定义模块的函数。

二、为什么直接mock input会失效?

如果之前你尝试patchbuiltins.input但没生效,核心原因是confirm_choice内部的input引用没被正确覆盖:比如confirm_choice在另一个模块,你却patch了测试模块里的input,此时confirm_choice调用的还是原模块的input,自然需要手动输入。这种情况下要么patchconfirm_choice所在模块的input,要么直接patchconfirm_choice本身(后者更简洁)。

三、是否需要解耦函数?

解耦是更优的长期实践,推荐采用。比如把confirm_choice作为可选参数传入delete_booking,测试时直接传入模拟逻辑,无需依赖mock工具:

修改业务函数:

def delete_booking(booking_id, confirm_func=confirm_choice):
    if confirm_func():
        # 执行删除逻辑
        return True
    else:
        return False

测试代码可以简化为:

def test_delete_confirmed():
    result = delete_booking("BK-001", lambda: True)
    assert result is True

def test_delete_canceled():
    result = delete_booking("BK-001", lambda: False)
    assert result is False

这种方式让依赖关系更明确,测试代码更直观,也避免了mock路径错误的问题。

内容的提问来源于stack exchange,提问作者bjornelvar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:35:23