Search code examples
haskellquickcheck

Find the value that failed for quickcheck


When a value fails a QuickCheck'd test, I'd like to use it for debugging. Is there any way I can do something like:

let failValue = quickCheck' myTest
in someStuff failValue

If my data was readable then I could probably hack some way to get it in from IO, but it's not.


Solution

  • I couldn't find anything in the QuickCheck API to do this in a nice way, but here's something I hacked together using the monadic QuickCheck API. It intercepts and logs the inputs to your property in an IORef, and assumes that if it failed, the last one was the culprit and returns it in a Just. If the test passed, the result is Nothing. This can probably be refined a bit but for simple one-argument properties it should do the job.

    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"