@@ -19,6 +19,7 @@ module Test.QuickCheck
1919 ( QC
2020 , quickCheck
2121 , quickCheck'
22+ , quickCheckWithSeed
2223 , quickCheckPure
2324 , class Testable
2425 , test
@@ -29,6 +30,8 @@ module Test.QuickCheck
2930 , (===)
3031 , assertNotEquals
3132 , (/==)
33+ , module Test.QuickCheck.LCG
34+ , module Test.QuickCheck.Arbitrary
3235 ) where
3336
3437import Prelude
@@ -47,9 +50,9 @@ import Data.Monoid (mempty)
4750import Data.Tuple (Tuple (..))
4851import Data.Unfoldable (replicateA )
4952
50- import Test.QuickCheck.Arbitrary (class Arbitrary , arbitrary )
53+ import Test.QuickCheck.Arbitrary (class Arbitrary , arbitrary , class Coarbitrary , coarbitrary )
5154import Test.QuickCheck.Gen (Gen , evalGen , runGen )
52- import Test.QuickCheck.LCG (Seed , randomSeed )
55+ import Test.QuickCheck.LCG (Seed , runSeed , randomSeed )
5356
5457-- | A type synonym which represents the effects used by the `quickCheck` function.
5558type QC eff a = Eff (console :: CONSOLE , random :: RANDOM , err :: EXCEPTION | eff ) a
@@ -66,14 +69,24 @@ quickCheck prop = quickCheck' 100 prop
6669quickCheck' :: forall eff prop . Testable prop => Int -> prop -> QC eff Unit
6770quickCheck' n prop = do
6871 seed <- randomSeed
72+ quickCheckWithSeed seed n prop
73+
74+ -- | A variant of the `quickCheck'` function that accepts a specific seed as
75+ -- | well as the number tests that should be run.
76+ quickCheckWithSeed
77+ :: forall eff prop . Testable prop => Seed -> Int -> prop -> QC eff Unit
78+ quickCheckWithSeed seed n prop = do
6979 let result = tailRec loop { seed, index: 0 , successes: 0 , firstFailure: mempty }
7080 log $ show result.successes <> " /" <> show n <> " test(s) passed."
71- for_ result.firstFailure \{ index, message } ->
72- throwException $ error $ " Test " <> show (index + 1 ) <> " failed: \n " <> message
81+ for_ result.firstFailure \{ index, message, seed: failureSeed } ->
82+ throwException $ error
83+ $ " Test " <> show (index + 1 )
84+ <> " (seed " <> show (runSeed failureSeed) <> " ) failed: \n "
85+ <> message
7386 where
74- loop :: LoopState -> Step LoopState ( LoopResult ())
75- loop { seed, index, successes, firstFailure }
76- | index == n = Done { successes, firstFailure }
87+ loop :: LoopState -> Step LoopState LoopState
88+ loop state@ { seed, index, successes, firstFailure }
89+ | index == n = Done state
7790 | otherwise =
7891 case runGen (test prop) { newSeed: seed, size: 10 } of
7992 Tuple Success s ->
@@ -88,17 +101,17 @@ quickCheck' n prop = do
88101 { seed: s.newSeed
89102 , index: index + 1
90103 , successes
91- , firstFailure: firstFailure <> First (Just { index, message })
104+ , firstFailure:
105+ firstFailure <> First (Just { index, message, seed })
92106 }
93107
94- type LoopResult r =
108+ type LoopState =
95109 { successes :: Int
96- , firstFailure :: First { index :: Int , message :: String }
97- | r
110+ , firstFailure :: First { index :: Int , message :: String , seed :: Seed }
111+ , seed :: Seed
112+ , index :: Int
98113 }
99114
100- type LoopState = LoopResult (seed :: Seed , index :: Int )
101-
102115-- | Test a property, returning all test results as an array.
103116-- |
104117-- | The first argument is the _random seed_ to be passed to the random generator.
@@ -125,6 +138,9 @@ instance testableBoolean :: Testable Boolean where
125138instance testableFunction :: (Arbitrary t , Testable prop ) => Testable (t -> prop ) where
126139 test f = arbitrary >>= test <<< f
127140
141+ instance testableGen :: Testable prop => Testable (Gen prop ) where
142+ test = flip bind test
143+
128144-- | The result of a test: success or failure (with an error message).
129145data Result = Success | Failed String
130146
0 commit comments