题解单元测试生成:随机用例要有暴力解兜底
一、测试生成不能只靠直觉
给算法题写单元测试时,很多人会随手写几个看起来正常的输入。这样能检查格式,却很难覆盖隐藏边界。AI 生成测试用例也会有同样问题,它可能生成一批相似样例,看起来数量很多,实际覆盖很窄。
更可靠的做法,是对小规模输入使用暴力解兜底。随机生成输入,同时用暴力算法计算期望输出,再和待测解法对比。这样可以自动发现很多边界错误。
二、随机测试要有约束
flowchart TD A[输入生成器] --> B[暴力解] A --> C[待测解] B --> D[结果对比] C --> D D --> E[失败用例归档]输入生成器要理解题目约束。数组长度、值域、是否允许重复、图是否连通、字符串字符集,这些都要显式配置。没有约束的随机测试,容易生成非法输入,反而干扰判断。
随机测试还要覆盖特殊分布。全相等、严格递增、严格递减、稀疏图、完全图、单元素、空结构,都比普通均匀随机更容易发现问题。随机不是乱扔数据,而是有策略地探索状态空间。
三、暴力解要简单可信
def brute_force(nums): best = 0 for i in range(len(nums)): total = 0 for j in range(i, len(nums)): total += nums[j] best = max(best, total) return best暴力解不追求性能,追求清晰可信。小规模输入下,它可以用穷举覆盖所有可能。待测解法可以是 O(n),暴力解可以是 O(n²) 或 O(n³),只要输入规模控制好即可。
如果暴力解本身复杂,就要谨慎。测试系统不能建立在另一个容易错的黑盒上。必要时可以准备人工校验样例,或者用两个不同思路的暴力解互相验证。
fuzz_config: max_n: 8 value_range: [-5, 5] rounds: 1000四、失败用例要最小化
随机测试发现失败后,原始输入可能很长。系统应该尝试缩小失败用例,比如删除无关元素、缩小数值范围、减少图节点。最小反例更适合学习,也更适合调试。
失败用例要进入回归库。修复代码后,原失败用例必须继续保留,防止以后同类错误复发。题解测试不是一次性动作,而是持续积累反例。
测试生成还要考虑超时。随机轮数太多,反馈会变慢;轮数太少,又容易漏错误。可以把测试分成快速集和深度集。快速集在每次保存时运行,深度集在提交或发布前运行。这样既能保持反馈速度,也能保留更强验证。
对浮点题和多解题,结果比较要特殊处理。浮点题需要误差范围,多解题需要验证答案是否合法,而不是和唯一期望值完全相等。测试框架如果只支持精确比较,会误判很多正确解。
测试报告要能指导修改。失败时输出输入、期望、实际、随机种子和生成器版本。随机种子尤其关键,它能让失败用例复现。没有种子,随机测试发现的问题很容易变成“刚才好像错过一次”。
最后,AI 生成测试也要被审查。模型可能生成不满足约束的用例,或者给出错误期望值。用暴力解、schema 校验和人工抽样结合,才能让测试集本身可靠。
测试覆盖还要记录题型标签。比如滑动窗口、图遍历、区间动态规划、字符串匹配,不同标签对应不同边界模板。长期积累后,系统可以自动提醒某类题缺少哪些典型反例。
五、总结
题解单元测试生成要结合约束随机、特殊分布、暴力解兜底和失败用例最小化。
随机用例不是为了凑数量。它的价值在于自动探索边界,并把隐藏错误沉淀成可复现的反例。