Python中如何为简易ATM程序的其余函数编写unittest单元测试
简易ATM程序unittest单元测试编写指南
首先先修正你现有代码和初版测试里的基础问题,否则测试无法正常运行:
- 测试类存在语法错误:
classTestATM要改为class TestATM(unittest.TestCase),注意父类TestCase为驼峰大写开头,类名和继承的父类之间要加空格 - 业务代码里的
user_pin、user_balance是全局变量,测试前需要预设固定值,避免测试结果受外部环境影响 - 所有调用
input()的交互函数不能直接运行测试,需要用unittest.mock模块的patch方法模拟用户输入,否则测试会卡住等待手动输入 - 你写的初版PIN测试有逻辑错误:
input()返回的输入值永远是字符串类型,传整数9876和字符串类型的存储PIN比对会永远返回False
1. 补全PIN校验函数测试
你目前只写了正确PIN的校验场景,需要补充错误PIN的反向用例:
import unittest from unittest.mock import patch # 先预设测试用的固定全局值 user_pin = "9876" user_balance = 1000 # 这里放入你之前写的pin_validation、log_in、withdraw_cash业务函数 class TestATM(unittest.TestCase): def test_pin_validation_correct(self): # 正确PIN场景 result = pin_validation("9876") self.assertTrue(result) def test_pin_validation_wrong(self): # 错误PIN场景 result = pin_validation("1234") self.assertFalse(result)
2. 登录函数测试用例
登录逻辑需要覆盖3个核心场景,所有输入交互用patch模拟:
- 首次输入正确PIN,直接登录成功
- 前两次输错PIN,第三次输入正确,登录成功
- 连续3次输错PIN,触发账户锁定异常
@patch('builtins.input', return_value="9876") def test_log_in_success_first_try(self, mock_input): result = log_in() self.assertTrue(result) @patch('builtins.input', side_effect=["1234", "5678", "9876"]) def test_log_in_success_third_try(self, mock_input): result = log_in() self.assertTrue(result) @patch('builtins.input', side_effect=["1111", "2222", "3333"]) def test_log_in_locked_after_3_wrong(self, mock_input): # 断言连续输错3次时抛出对应类型的异常,且错误信息匹配 with self.assertRaises(TypeError) as e: log_in() self.assertEqual(str(e.exception), "Account locked")
3. 取款函数测试用例
取款逻辑需要覆盖2个核心场景,用setUp方法在每个用例执行前重置余额,避免不同测试之间的数据干扰:
- 取款金额小于账户余额,取款成功,余额正确扣减
- 取款金额大于账户余额,抛出余额不足异常
def setUp(self): # 每个测试用例执行前重置全局余额为初始值 global user_balance user_balance = 1000 @patch('builtins.input', return_value="200") def test_withdraw_success(self, mock_input): result = withdraw_cash() # 原函数取款成功返回False,断言返回值符合预期 self.assertFalse(result) # 断言余额扣减正确 global user_balance self.assertEqual(user_balance, 800) @patch('builtins.input', return_value="1200") def test_withdraw_insufficient_balance(self, mock_input): # 断言余额不足时抛出对应异常 with self.assertRaises(ValueError) as e: withdraw_cash() self.assertEqual(str(e.exception), "Not enough funds in account")
*额外提示:你的业务代码里有两段永远不会执行的死代码,可以直接删掉:
log_in函数里raise TypeError("Account locked")之后的return Falsewithdraw_cash函数里return False之后的assert new_balance > 0,如果要保留这个余额为正的校验,需要把断言挪到return语句之前*
内容的提问来源于stack exchange,提问作者frenchtoast
相关产品推荐
相关产品推荐

