如何测试两段Python代码对任意输入的输出是否完全一致
自写代码与参考解法的输出对比及bug定位方法
核心原理
不需要掌握复杂的测试框架知识,核心逻辑是用完全相同的输入分别运行自写代码和参考代码,自动比对输出差异,找到输出不一致的输入,就是触发你代码逻辑错误的测试用例,顺着这个用例排查执行流程就能定位问题。
操作步骤
- 整理代码结构
把自写的待调试代码、官方参考解法放在同一个Python文件中,保证两者的调用入口统一:比如都是同名类下的同名方法,入参、返回值格式完全一致,避免调用逻辑出错。 - 构造覆盖全场景的测试用例集
测试用例分三类准备,保证覆盖所有可能的逻辑分支:- 题目公开给出的示例用例
- 手动枚举的边界用例:比如单字符输入、特殊组合输入、题目规定的最大/最小合法值输入
- 批量随机生成的合法输入:按照题目给定的规则写简单的生成逻辑,批量产出上百上千个合法输入,覆盖人工枚举遗漏的场景
- 编写自动对比脚本
遍历所有测试用例,将同一个输入分别传入两个解法的入口函数拿到返回值,一旦出现返回值不一致的情况,立刻打印当前输入、自写代码输出、参考代码输出,终止运行方便排查;如果所有用例遍历完都没有不一致,说明两份代码的逻辑输出完全等价。
罗马数字转整数题的可直接运行示例
把下面的代码保存为.py文件直接运行即可,你可以替换MySolution类的内容为自己写的递归版、迭代版代码做测试:
import random # -------------------------- 待调试的自写代码区 -------------------------- prefix = ['I', 'X', 'C'] value = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} def rec(s, v): n = s[0:1] if len(s) > 1 and n in prefix and value[s[0:1]] < value[s[1:2]]: n = s[0:2] if len(n) > 1: v += value[n[1]] - value[n[0]] else: v += value[n] s = s.removeprefix(n) return v if not s else rec(s, v) class MySolution: def romanToInt(self, s: str) -> int: return rec(s, 0) # -------------------------- 官方参考解法区 -------------------------- class RefSolution: def romanToInt(self, s: str) -> int: val_map = {'I':1, 'IV':3, 'V':5, 'IX':8, 'X':10, 'XL':30, 'L':50, 'XC':80, 'C':100, 'CD':300, 'D':500, 'CM':800, 'M':1000} total = val_map[s[0]] for i in range(1, len(s)): if val_map[s[i]] > val_map[s[i-1]]: total -= 2 * val_map[s[i-1]] total += val_map[s[i]] return total # -------------------------- 自动对比测试逻辑区 -------------------------- # 1. 初始化测试用例集 test_cases = [ # 题目示例用例 "III", "IV", "IX", "LVIII", "MCMXCIV", # 手动枚举边界用例 "I", "V", "M", "MMMCMXCIX", "XL", "CD", "CM", "XIV", "XCIX" ] # 2. 追加1000个随机生成的合法罗马数字用例 roman_rule = [['M',1000], ['CM',900], ['D',500], ['CD',400], ['C',100], ['XC',90], ['L',50], ['XL',40], ['X',10], ['IX',9], ['V',5], ['IV',4], ['I',1]] for _ in range(1000): rand_num = random.randint(1, 3999) rand_str = "" remain = rand_num for char, val in roman_rule: while remain >= val: rand_str += char remain -= val test_cases.append(rand_str) # 3. 逐用例对比输出 my_solver = MySolution() ref_solver = RefSolution() for case in test_cases: my_output = my_solver.romanToInt(case) ref_output = ref_solver.romanToInt(case) if my_output != ref_output: print("找到触发bug的测试用例:") print(f"输入:{case}") print(f"自写代码输出:{my_output}") print(f"参考解法输出:{ref_output}") exit(0) print("全部测试用例通过,两份代码输出完全一致")
定位具体逻辑错误的技巧
- 拿到触发bug的输入后,在自写代码的关键执行节点加打印,输出每一步的中间变量:比如循环/递归每一层的剩余输入、当前处理的字符、临时计算值、累加结果,和参考解法在同一个输入下的中间变量逐行比对,第一个出现数值差异的位置就是逻辑错误的根源。
- 比如你写的迭代版代码里已经加了每轮的变量打印,只要拿到出错的输入,顺着打印的执行流走一遍,很快就能定位是判断条件写错、字符串截取逻辑有误,还是计算规则不符合题目要求。
- 如果上千个随机生成的用例都能通过,基本可以确认自写代码的逻辑和参考解法等价,不存在隐藏的逻辑漏洞。
内容的提问来源于stack exchange,提问作者Cesar Lopes
相关产品推荐
相关产品推荐

