@@ -33,19 +33,20 @@ module Test.QuickCheck
33
33
34
34
import Prelude
35
35
36
- import Control.Monad.Eff (Eff () )
37
- import Control.Monad.Eff.Console (CONSOLE () , log )
36
+ import Control.Monad.Eff (Eff )
37
+ import Control.Monad.Eff.Console (CONSOLE , log )
38
38
import Control.Monad.Eff.Exception (EXCEPTION , throwException , error )
39
- import Control.Monad.Eff.Random (RANDOM () )
40
- import Control.Monad.Rec.Class (tailRecM )
41
- import Data.Either ( Either (..))
39
+ import Control.Monad.Eff.Random (RANDOM )
40
+ import Control.Monad.Rec.Class (Step (..), tailRec )
41
+
42
42
import Data.Foldable (for_ )
43
43
import Data.List (List )
44
44
import Data.Maybe (Maybe (..))
45
45
import Data.Maybe.First (First (..))
46
46
import Data.Monoid (mempty )
47
47
import Data.Tuple (Tuple (..))
48
48
import Data.Unfoldable (replicateA )
49
+
49
50
import Test.QuickCheck.Arbitrary (class Arbitrary , arbitrary )
50
51
import Test.QuickCheck.Gen (Gen , evalGen , runGen )
51
52
import Test.QuickCheck.LCG (Seed , randomSeed )
@@ -64,31 +65,39 @@ quickCheck prop = quickCheck' 100 prop
64
65
-- | representing the number of tests which should be run.
65
66
quickCheck' :: forall eff prop . Testable prop => Int -> prop -> QC eff Unit
66
67
quickCheck' n prop = do
67
- seed <- randomSeed
68
- { successes, firstFailure } <- tailRecM loop { seed, index: 0 , successes: 0 , firstFailure: mempty }
69
- log $ show successes <> " /" <> show n <> " test(s) passed."
70
- for_ firstFailure \{ index, message } ->
71
- throwException $ error $ " Test " <> show (index + 1 ) <> " failed: \n " <> message
68
+ seed <- randomSeed
69
+ let result = tailRec loop { seed, index: 0 , successes: 0 , firstFailure: mempty }
70
+ 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
72
73
where
73
- loop :: { seed :: Seed , index :: Int , successes :: Int , firstFailure :: First { index :: Int , message :: String } }
74
- -> QC eff (Either { seed :: Seed , index :: Int , successes :: Int , firstFailure :: First { index :: Int , message :: String } }
75
- { successes :: Int , firstFailure :: First { index :: Int , message :: String } } )
76
- loop { seed, index, successes, firstFailure }
77
- | index == n = pure (Right { successes, firstFailure })
78
- | otherwise = do
74
+ loop :: LoopState -> Step LoopState (LoopResult ())
75
+ loop { seed, index, successes, firstFailure }
76
+ | index == n = Done { successes, firstFailure }
77
+ | otherwise =
79
78
case runGen (test prop) { newSeed: seed, size: 10 } of
80
79
Tuple Success s ->
81
- pure (Left { seed: s.newSeed
82
- , index: index + 1
83
- , successes: successes + 1
84
- , firstFailure
85
- })
80
+ Loop
81
+ { seed: s.newSeed
82
+ , index: index + 1
83
+ , successes: successes + 1
84
+ , firstFailure
85
+ }
86
86
Tuple (Failed message) s ->
87
- pure (Left { seed: s.newSeed
88
- , index: index + 1
89
- , successes
90
- , firstFailure: firstFailure <> First (Just { index, message })
91
- })
87
+ Loop
88
+ { seed: s.newSeed
89
+ , index: index + 1
90
+ , successes
91
+ , firstFailure: firstFailure <> First (Just { index, message })
92
+ }
93
+
94
+ type LoopResult r =
95
+ { successes :: Int
96
+ , firstFailure :: First { index :: Int , message :: String }
97
+ | r
98
+ }
99
+
100
+ type LoopState = LoopResult (seed :: Seed , index :: Int )
92
101
93
102
-- | Test a property, returning all test results as an array.
94
103
-- |
0 commit comments