14

ある値が QuickCheck のテストに失敗した場合、それをデバッグに使用したいと考えています。次のようなことができる方法はありますか?

let failValue = quickCheck' myTest
in someStuff failValue

私のデータが可能であれば、read何らかの方法でハッキングして IO からデータを取得できたかもしれませんが、そうではありません。

4

2 に答える 2

9

QuickCheck API には、これを適切に行う方法は何も見つかりませんでしたが、モナディックな QuickCheck API を使用して一緒にハッキングしたものを次に示します。プロパティへの入力を傍受して でログに記録し、IORef失敗した場合は最後の入力が原因であると想定し、 で返しますJust。テストに合格した場合、結果はNothingです。これはおそらく少し洗練される可能性がありますが、引数が 1 つの単純なプロパティの場合は、これで十分です。

import Control.Monad
import Data.IORef
import Test.QuickCheck
import Test.QuickCheck.Monadic

prop_failIfZero :: Int -> Bool
prop_failIfZero n = n /= 0

quickCheck' :: (Arbitrary a, Show a) => (a -> Bool) -> IO (Maybe a)
quickCheck' prop = do input <- newIORef Nothing
                      result <- quickCheckWithResult args (logInput input prop)
                      case result of
                         Failure {} -> readIORef input
                         _ -> return Nothing
  where
    logInput input prop x = monadicIO $ do run $ writeIORef input (Just x)
                                           assert (prop x)
    args = stdArgs { chatty = False }

main = do failed <- quickCheck' prop_failIfZero
          case failed of
              Just x -> putStrLn $ "The input that failed was: " ++ show x
              Nothing -> putStrLn "The test passed"
于 2011-11-19T02:34:47.357 に答える
2

1 つの方法は、サンプルの方法を使用して手動でテストを実行し、失敗した値を見つけることです。たとえば、問題のある double 関数をテストします。

import Test.QuickCheck

double :: Int -> Int
double x | x < 10 = 2 * x
         | otherwise = 13

doubleTest :: Int -> Bool
doubleTest x = x + x == double x

tester :: IO ()
tester = do
  values <- sample' arbitrary
  let failedValues = filter (not . doubleTest) values
  print failedValues

唯一の問題はsample'、11 個のテスト値しか生成しないことです。これでは、バグを引き起こすには十分ではない可能性があります。

于 2011-11-19T02:31:44.543 に答える