2011-11-19 6 views
14

値がQuickCheckされたテストに失敗した場合、デバッグに使用したいと思います。私のデータはread、私はおそらくIOからそれを得るためにいくつかの方法をハック可能性がありますが、そうでないことができた場合はquickcheckに失敗した値を見つける

let failValue = quickCheck' myTest 
in someStuff failValue 

:私はのような何かを行うことができますどのような方法があります。

答えて

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" 
+0

非常に賢い、ありがとう – Xodarap

+0

この小さなトリックは私のHaskellのデバッグの経験をより良くしました。ありがとう –

2

1つの方法は、sample'メソッドを使用して手動でテストを実行し、失敗した値を見つけ出すことです。例えば、障害のある二重の機能をテストする:唯一の問題はsample'ある

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 

のみバグを誘発するのに十分ではないかもしれない11個の試験値を生成します。

関連する問題