@@ -37,12 +37,20 @@ import Control.Monad.Eff (Eff())
3737import Control.Monad.Eff.Console (CONSOLE (), log )
3838import Control.Monad.Eff.Exception (EXCEPTION (), throwException , error )
3939import Control.Monad.Eff.Random (RANDOM ())
40+ import Control.Monad.Except.Trans (ExceptT , runExceptT , throwError )
41+ import Control.Monad.State (State )
42+ import Control.Monad.Trans (lift )
43+ import Control.Monad.Writer.Trans (WriterT , runWriterT , tell )
44+ import Control.Monad.Rec.Class (tailRecM )
4045
46+ import Data.Either (Either (..))
4147import Data.List (List (..))
48+ import Data.Monoid.Additive (Additive (..))
49+ import Data.Tuple (Tuple (..))
4250import Data.Unfoldable (replicateA )
4351
4452import Test.QuickCheck.Arbitrary (class Arbitrary , arbitrary )
45- import Test.QuickCheck.Gen (Gen , evalGen )
53+ import Test.QuickCheck.Gen (Gen , GenState , evalGen )
4654import Test.QuickCheck.LCG (Seed , randomSeed )
4755
4856-- | A type synonym which represents the effects used by the `quickCheck` function.
@@ -52,36 +60,37 @@ type QC eff a = Eff (console :: CONSOLE, random :: RANDOM, err :: EXCEPTION | ef
5260-- |
5361-- | This function generates a new random seed, runs 100 tests and
5462-- | prints the test results to the console.
55- quickCheck :: forall eff prop . ( Testable prop ) => prop -> QC eff Unit
63+ quickCheck :: forall eff prop . Testable prop => prop -> QC eff Unit
5664quickCheck prop = quickCheck' 100 prop
5765
5866-- | A variant of the `quickCheck` function which accepts an extra parameter
5967-- | representing the number of tests which should be run.
60- quickCheck' :: forall eff prop . ( Testable prop ) => Int -> prop -> QC eff Unit
68+ quickCheck' :: forall eff prop . Testable prop => Int -> prop -> QC eff Unit
6169quickCheck' n prop = do
62- seed <- randomSeed
63- let results = quickCheckPure seed n prop
64- let successes = countSuccesses results
65- log $ show successes <> " /" <> show n <> " test(s) passed."
66- throwOnFirstFailure one results
67-
70+ seed <- randomSeed
71+ case evalGen (runExceptT (runWriterT (tailRecM loop 0 ))) { newSeed: seed, size: 10 } of
72+ Left err -> throwException $ error $ " Test " <> show (err.index + 1 ) <> " failed: \n " <> err.msg
73+ Right (Tuple _ (Additive successes)) -> do
74+ log $ show successes <> " /" <> show n <> " test(s) passed."
6875 where
69-
70- throwOnFirstFailure :: Int -> List Result -> QC eff Unit
71- throwOnFirstFailure _ Nil = pure unit
72- throwOnFirstFailure n (Cons (Failed msg) _) = throwException $ error $ " Test " <> show n <> " failed: \n " <> msg
73- throwOnFirstFailure n (Cons _ rest) = throwOnFirstFailure (n + one) rest
74-
75- countSuccesses :: List Result -> Int
76- countSuccesses Nil = zero
77- countSuccesses (Cons Success rest) = one + countSuccesses rest
78- countSuccesses (Cons _ rest) = countSuccesses rest
76+ loop :: Int
77+ -> WriterT (Additive Int )
78+ (ExceptT { index :: Int , msg :: String }
79+ (State GenState )) (Either Int Unit )
80+ loop index | index == n = pure (Right unit)
81+ loop index = do
82+ result <- lift (lift (test prop))
83+ case result of
84+ Success -> do
85+ tell (Additive 1 )
86+ pure (Left (index + 1 ))
87+ Failed msg -> throwError { index, msg }
7988
8089-- | Test a property, returning all test results as an array.
8190-- |
8291-- | The first argument is the _random seed_ to be passed to the random generator.
8392-- | The second argument is the number of tests to run.
84- quickCheckPure :: forall prop . ( Testable prop ) => Seed -> Int -> prop -> List Result
93+ quickCheckPure :: forall prop . Testable prop => Seed -> Int -> prop -> List Result
8594quickCheckPure s n prop = evalGen (replicateA n (test prop)) { newSeed: s, size: 10 }
8695
8796-- | The `Testable` class represents _testable properties_.
0 commit comments