@@ -19,6 +19,7 @@ module Test.QuickCheck
19
19
( QC
20
20
, quickCheck
21
21
, quickCheck'
22
+ , quickCheckWithSeed
22
23
, quickCheckPure
23
24
, class Testable
24
25
, test
@@ -29,6 +30,8 @@ module Test.QuickCheck
29
30
, (===)
30
31
, assertNotEquals
31
32
, (/==)
33
+ , module Test.QuickCheck.LCG
34
+ , module Test.QuickCheck.Arbitrary
32
35
) where
33
36
34
37
import Prelude
@@ -47,9 +50,9 @@ import Data.Monoid (mempty)
47
50
import Data.Tuple (Tuple (..))
48
51
import Data.Unfoldable (replicateA )
49
52
50
- import Test.QuickCheck.Arbitrary (class Arbitrary , arbitrary )
53
+ import Test.QuickCheck.Arbitrary (class Arbitrary , arbitrary , class Coarbitrary , coarbitrary )
51
54
import Test.QuickCheck.Gen (Gen , evalGen , runGen )
52
- import Test.QuickCheck.LCG (Seed , randomSeed )
55
+ import Test.QuickCheck.LCG (Seed , runSeed , randomSeed )
53
56
54
57
-- | A type synonym which represents the effects used by the `quickCheck` function.
55
58
type QC eff a = Eff (console :: CONSOLE , random :: RANDOM , err :: EXCEPTION | eff ) a
@@ -66,14 +69,24 @@ quickCheck prop = quickCheck' 100 prop
66
69
quickCheck' :: forall eff prop . Testable prop => Int -> prop -> QC eff Unit
67
70
quickCheck' n prop = do
68
71
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
69
79
let result = tailRec loop { seed, index: 0 , successes: 0 , firstFailure: mempty }
70
80
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
73
86
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
77
90
| otherwise =
78
91
case runGen (test prop) { newSeed: seed, size: 10 } of
79
92
Tuple Success s ->
@@ -88,17 +101,17 @@ quickCheck' n prop = do
88
101
{ seed: s.newSeed
89
102
, index: index + 1
90
103
, successes
91
- , firstFailure: firstFailure <> First (Just { index, message })
104
+ , firstFailure:
105
+ firstFailure <> First (Just { index, message, seed })
92
106
}
93
107
94
- type LoopResult r =
108
+ type LoopState =
95
109
{ 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
98
113
}
99
114
100
- type LoopState = LoopResult (seed :: Seed , index :: Int )
101
-
102
115
-- | Test a property, returning all test results as an array.
103
116
-- |
104
117
-- | The first argument is the _random seed_ to be passed to the random generator.
@@ -125,6 +138,9 @@ instance testableBoolean :: Testable Boolean where
125
138
instance testableFunction :: (Arbitrary t , Testable prop ) => Testable (t -> prop ) where
126
139
test f = arbitrary >>= test <<< f
127
140
141
+ instance testableGen :: Testable prop => Testable (Gen prop ) where
142
+ test = flip bind test
143
+
128
144
-- | The result of a test: success or failure (with an error message).
129
145
data Result = Success | Failed String
130
146
0 commit comments