从种子为 QuickCheck 重新创建失败的输入值
Recreating failing input value for QuickCheck from a seed
当QuickCheck测试失败时,有时我需要遍历ghci(或stack repl)中的代码来分析问题。所以我做的第一件事就是重新创建失败的输入。现在 QuickCheck 打印出失败的输入(使用 Show
),但有时很难或不可能从中重新创建输入。例如,所讨论的类型可能不会实现 Read
。或者它可能是一个非常复杂的类型,需要很多类型才能重新创建它,跟踪导出这些类型的模块,然后手动将它们导入 repl 是一件麻烦事。
所以我希望能够从种子 中重新创建失败的输入,这也由 QuickCheck 报告。看起来 Test.QuickCheck.Gen 中的 unGen
就是为此设计的。
unGen :: QCGen -> Int -> a
Run the generator on a particular seed. If you just want to get a
random value out, consider using generate.
但是unGen
需要两个输入参数。我猜第二个是种子。如何重新创建 QCGen
参数?这是我尝试的示例,其中种子为 -4346962096583255693。 unGen
好像不太喜欢负种子,所以我一定是做错了。
λ> (unGen arbitrary) (mkQCGen 0) (-4346962096583255693) :: ImprintEmptyBrainTestData
ImprintEmptyBrainTestData (*** Exception: Negative exponent
您应该使用 quickCheckResult
(或 quickCheckWithResult
)来 运行 您的测试。如果 returns 和 Failure
,usedSeed
和 usedSize
字段具有 QCGen
和 Int
值,您需要在 Args
到 quickCheckWith
.
还有一个包 quickcheck-with-counterexamples,如果测试失败,属性可以捕获生成的值以供进一步检查。
当QuickCheck测试失败时,有时我需要遍历ghci(或stack repl)中的代码来分析问题。所以我做的第一件事就是重新创建失败的输入。现在 QuickCheck 打印出失败的输入(使用 Show
),但有时很难或不可能从中重新创建输入。例如,所讨论的类型可能不会实现 Read
。或者它可能是一个非常复杂的类型,需要很多类型才能重新创建它,跟踪导出这些类型的模块,然后手动将它们导入 repl 是一件麻烦事。
所以我希望能够从种子 中重新创建失败的输入,这也由 QuickCheck 报告。看起来 Test.QuickCheck.Gen 中的 unGen
就是为此设计的。
unGen :: QCGen -> Int -> a
Run the generator on a particular seed. If you just want to get a random value out, consider using generate.
但是unGen
需要两个输入参数。我猜第二个是种子。如何重新创建 QCGen
参数?这是我尝试的示例,其中种子为 -4346962096583255693。 unGen
好像不太喜欢负种子,所以我一定是做错了。
λ> (unGen arbitrary) (mkQCGen 0) (-4346962096583255693) :: ImprintEmptyBrainTestData
ImprintEmptyBrainTestData (*** Exception: Negative exponent
您应该使用 quickCheckResult
(或 quickCheckWithResult
)来 运行 您的测试。如果 returns 和 Failure
,usedSeed
和 usedSize
字段具有 QCGen
和 Int
值,您需要在 Args
到 quickCheckWith
.
还有一个包 quickcheck-with-counterexamples,如果测试失败,属性可以捕获生成的值以供进一步检查。