hspec-core-2.11.16: src/Test/Hspec/Core/QuickCheck.hs
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
-- | Stability: provisional
module Test.Hspec.Core.QuickCheck (
modifyMaxSuccess
, modifyMaxDiscardRatio
, modifyMaxSize
, modifyMaxShrinks
, modifyArgs
) where
import Prelude ()
import Test.Hspec.Core.Compat
import Test.QuickCheck (Args(..))
import qualified Test.QuickCheck as QC
import qualified Test.QuickCheck.State as QC (numSuccessTests, maxSuccessTests)
import qualified Test.QuickCheck.Property as QCP
import Test.Hspec.Core.Util
import Test.Hspec.Core.QuickCheck.Util
import Test.Hspec.Core.Example (Example(..), Params(..), Result(..), ResultStatus(..), FailureReason(..), hunitFailureToResult)
import Test.Hspec.Core.Spec.Monad (SpecWith, modifyParams)
-- | Use a modified `maxSuccess` for given spec.
modifyMaxSuccess :: (Int -> Int) -> SpecWith a -> SpecWith a
modifyMaxSuccess = modifyArgs . modify
where
modify :: (Int -> Int) -> Args -> Args
modify f args = args {maxSuccess = f (maxSuccess args)}
-- | Use a modified `maxDiscardRatio` for given spec.
modifyMaxDiscardRatio :: (Int -> Int) -> SpecWith a -> SpecWith a
modifyMaxDiscardRatio = modifyArgs . modify
where
modify :: (Int -> Int) -> Args -> Args
modify f args = args {maxDiscardRatio = f (maxDiscardRatio args)}
-- | Use a modified `maxSize` for given spec.
modifyMaxSize :: (Int -> Int) -> SpecWith a -> SpecWith a
modifyMaxSize = modifyArgs . modify
where
modify :: (Int -> Int) -> Args -> Args
modify f args = args {maxSize = f (maxSize args)}
-- | Use a modified `maxShrinks` for given spec.
modifyMaxShrinks :: (Int -> Int) -> SpecWith a -> SpecWith a
modifyMaxShrinks = modifyArgs . modify
where
modify :: (Int -> Int) -> Args -> Args
modify f args = args {maxShrinks = f (maxShrinks args)}
-- | Use modified `Args` for given spec.
modifyArgs :: (Args -> Args) -> SpecWith a -> SpecWith a
modifyArgs = modifyParams . modify
where
modify :: (Args -> Args) -> Params -> Params
modify f p = p {paramsQuickCheckArgs = f (paramsQuickCheckArgs p)}
instance Example QC.Property where
#ifdef ENABLE_SPEC_HOOK_ARGS
type Arg QC.Property = ()
#endif
evaluateExample e = evaluateExample (\() -> e)
#ifdef ENABLE_SPEC_HOOK_ARGS
instance Example (a -> QC.Property) where
type Arg (a -> QC.Property) = a
#else
instance Example (() -> QC.Property) where
#endif
evaluateExample p params hook progressCallback = do
let args = paramsQuickCheckArgs params
r <- QC.quickCheckWithResult args {QC.chatty = False} (QCP.callback qcProgressCallback $ aroundProperty hook p)
return $ fromQuickCheckResult args r
where
qcProgressCallback = QCP.PostTest QCP.NotCounterexample $
\st _ -> progressCallback (QC.numSuccessTests st, QC.maxSuccessTests st)
fromQuickCheckResult :: QC.Args -> QC.Result -> Result
fromQuickCheckResult args r = case parseQuickCheckResult r of
QuickCheckResult _ info (QuickCheckOtherFailure err) -> Result info $ Failure Nothing (Reason err)
QuickCheckResult _ info QuickCheckSuccess -> Result (if QC.chatty args then info else "") Success
QuickCheckResult n info (QuickCheckFailure QCFailure{..}) -> case quickCheckFailureException of
Just e | Just result <- fromException e -> Result info result
Just e | Just hunit <- fromException e -> Result info $ hunitFailureToResult (Just hunitAssertion) hunit
Just e -> failure (uncaughtException e)
Nothing -> failure falsifiable
where
failure = Result info . Failure Nothing . Reason
numbers = formatNumbers n quickCheckFailureNumShrinks
hunitAssertion :: String
hunitAssertion = intercalate "\n" [
"Falsifiable " ++ numbers ++ ":"
, indent (unlines quickCheckFailureCounterexample)
]
uncaughtException e = intercalate "\n" [
"uncaught exception: " ++ formatException e
, numbers
, indent (unlines quickCheckFailureCounterexample)
]
falsifiable = intercalate "\n" [
quickCheckFailureReason ++ " " ++ numbers ++ ":"
, indent (unlines quickCheckFailureCounterexample)
]
indent :: String -> String
indent = intercalate "\n" . map (" " ++) . lines