每次我运行“quickCheck prop_xyz”时,都会使用一个新的随机种子。如何强制 QuickCheck 始终使用相同的随机种子?
谢谢!
每次我运行“quickCheck prop_xyz”时,都会使用一个新的随机种子。如何强制 QuickCheck 始终使用相同的随机种子?
谢谢!
您需要的功能在Test.QuickCheck
; 用于quickCheckWith
指定自定义Args
。特别是,有一个replay :: Maybe (StdGen, Int)
字段,它允许您重播测试。所以你可以使用stdArgs
默认值并调整它们;例如,
ghci> :load Main.hs
ghci> import Test.QuickCheck
ghci> import System.Random -- for mkStdGen
ghci> quickCheckWith stdArgs{replay = Just (mkStdGen 42, 0)} prop_xyz
元组的第二个组成部分与测试用例的大小有关,但我忘记了具体是什么。
使用quickCheckWith
功能
quickCheckWith (stdArgs{replay = Just (myNewGen, testSize)}) property
如果你有一个失败的测试并且你想重用它,
result <- quickCheckResult failing_prop
let gen = usedSeed result
let size = usedSize result
获得在失败测试中使用的大小和种子。
由于您还需要可重现的错误,因此一个好的收缩算法可能会有所帮助。默认情况下,它会返回[]
但提供了一个足够好的结果,那么即使在不同的随机运行中,您也可能会遇到相同(最小)的失败。
QuickCheck >= 2.7 和 tf-random 的示例。
如果失败的测试运行的输出看起来像这样:
Failure {
usedSeed = TFGenR 1CE4E8B15F9197B60EE70803C62388671B62D6F88720288F5339F7EC521FEBC4 0 70368744177663 46 0,
USEDSIZE = 75,
...
}
然后您可以重现失败,如下所示:
import Test.QuickCheck.Random (QCGen(..))
import System.Random.TF (TFGen)
qcheck :: Testable a => a -> IO ()
qcheck prop = quickCheckWith args prop
where
usedSeed = QCGen (read "TFGenR 1CE4E8B15F9197B60EE70803C62388671B62D6F88720288F5339F7EC521FEBC4 0 70368744177663 46 0"::TFGen)
usedSize = 75
args = stdArgs{
replay=Just(usedSeed, usedSize)
}
如果要确定Generator
导致失败的原因,可以执行以下操作:
import Test.QuickCheck
import System.Random
reproducableTest :: Testable a => a -> Maybe (StdGen, Int) -> IO ()
reproducableTest prop repl = do result <- quickCheckWithResult stdArgs{replay = repl} prop
case result of
Failure{interrupted = False} -> do putStrLn $ "Use " ++ show (usedSeed result) ++ " as the initial seed"
putStrLn $ "Use " ++ show (usedSize result) ++ " as the initial size"
_ -> return ()
只有两个种子编号中的第一个应该用作函数的参数。所以如果你有你的财产prop
,你的初始电话将是reproducableTest prop Nothing
。你会得到类似的东西
Use x y as the initial seed
Use z as the initial size
然后你会再次打电话给reproducableTest prop $ Just (mkStdGen x , z)