如何使用Replay功能运行FsCheck的特定失败测试用例
FsCheck 直接运行失败用例的最优方案
FsCheck本身提供了官方的方式跳过前置生成步骤,直接定位到触发失败的用例,比你当前用的两种临时方案更高效,常用的两种实现方式如下:
方案1:复用原有测试直接固定参数
FsCheck在输出失败信息时,除了seed、尝试次数外,也会打印触发失败的完整输入参数。你不需要额外新增独立测试,直接临时修改原有属性测试的参数定义即可:
比如原有测试代码:
[<Property>] let 排序算法测试 (输入列表: int list) = 自定义排序 输入列表 = List.sort 输入列表
如果失败输出显示触发错误的参数是输入列表 = [3;1;4;1;5;9;2;6],直接临时把测试改成无参数形式,硬编码这个失败输入:
[<Property>] let 排序算法测试 () = let 输入列表 = [3;1;4;1;5;9;2;6] 自定义排序 输入列表 = List.sort 输入列表
修改后运行测试只会执行这1次用例,可以直接打断点调试,修复完成后把代码改回原有参数形式即可,不需要额外删除测试用例。
方案2:搭配Replay属性直接跳过前置用例
如果你的测试参数结构复杂,硬编码成本高,可以用FsCheck的Replay属性配合失败信息里的尝试次数直接定位:
你看到的失败日志Falsifiable, after 74 tests,可以直接在Replay属性后加MaxTest = 74参数,如果日志里还输出了Size: xx的信息,再加StartSize = xx参数即可,示例写法:
[<Property(Replay = "12345,67890", MaxTest = 74, StartSize = 10)>] let 排序算法测试 (输入列表: int list) = 自定义排序 输入列表 = List.sort 输入列表
这样FsCheck会直接运行到第74个触发失败的用例就停止,不需要跑完全部前置用例,也不需要额外加条件断点。
额外调试技巧
如果你的测试逻辑已经封装为独立的纯函数,可以直接把失败参数复制到F#交互(FSI)中运行,不需要启动测试框架,调试响应速度更快。
内容的提问来源于stack exchange,提问作者thur
相关产品推荐
相关产品推荐

