hspec 1.8.3 → 1.9.0
raw patch · 13 files changed
+209/−203 lines, 13 filesdep +tf-randomdep ~QuickCheckdep ~hspec-metadep ~random
Dependencies added: tf-random
Dependency ranges changed: QuickCheck, hspec-meta, random
Files
- hspec.cabal +7/−5
- src/Test/Hspec.hs +0/−1
- src/Test/Hspec/Config.hs +28/−21
- src/Test/Hspec/Core.hs +0/−8
- src/Test/Hspec/Core/QuickCheckUtil.hs +15/−13
- src/Test/Hspec/Core/Type.hs +11/−2
- src/Test/Hspec/Runner.hs +21/−16
- src/Test/Hspec/Runner/Eval.hs +113/−85
- src/Test/Hspec/Util.hs +0/−18
- test/Helper.hs +2/−1
- test/Test/Hspec/Core/TypeSpec.hs +4/−4
- test/Test/Hspec/RunnerSpec.hs +8/−10
- test/Test/Hspec/UtilSpec.hs +0/−19
hspec.cabal view
@@ -1,5 +1,5 @@ name: hspec-version: 1.8.3+version: 1.9.0 license: MIT license-file: LICENSE copyright: (c) 2011-2014 Simon Hengel,@@ -40,14 +40,15 @@ src build-depends: base == 4.*- , random == 1.0.*+ , random+ , tf-random , setenv , ansi-terminal >= 0.5 , time , transformers >= 0.2.2.0 && < 0.4.0 , deepseq , HUnit >= 1.2.5- , QuickCheck >= 2.5.1+ , QuickCheck >= 2.7 , quickcheck-io , hspec-expectations == 0.5.0.* exposed-modules:@@ -95,7 +96,8 @@ -Wall -Werror build-depends: base == 4.*- , random == 1.0.*+ , random+ , tf-random , setenv , silently >= 1.2.4 , ansi-terminal@@ -107,7 +109,7 @@ , quickcheck-io , hspec-expectations - , hspec-meta >= 1.8.0+ , hspec-meta >= 1.9.0 , process , ghc-paths
src/Test/Hspec.hs view
@@ -36,7 +36,6 @@ import Test.Hspec.Runner import Test.Hspec.HUnit () import Test.Hspec.Expectations-import Test.Hspec.Core (mapSpecItem) import qualified Test.Hspec.Core as Core -- | Combine a list of specs into a larger spec.
src/Test/Hspec/Config.hs view
@@ -3,7 +3,7 @@ , defaultConfig , getConfig , configAddFilter-, configSetSeed+, configQuickCheckArgs ) where import Control.Applicative@@ -12,12 +12,12 @@ import System.IO import System.Exit import qualified Test.QuickCheck as QC+import Test.QuickCheck.Random (mkQCGen) import Test.Hspec.Formatters import Test.Hspec.Util --- for Monad (Either e) when base < 4.3-import Control.Monad.Trans.Error ()+import Control.Monad.Trans.Error () -- for Monad (Either e) when base < 4.3 import Test.Hspec.Options import Test.Hspec.FailureReport@@ -31,7 +31,10 @@ -- A predicate that is used to filter the spec before it is run. Only examples -- that satisfy the predicate are run. , configFilterPredicate :: Maybe (Path -> Bool)-, configQuickCheckArgs :: QC.Args+, configQuickCheckSeed :: Maybe Integer+, configQuickCheckMaxSuccess :: Maybe Int+, configQuickCheckMaxDiscardRatio :: Maybe Int+, configQuickCheckMaxSize :: Maybe Int , configSmallCheckDepth :: Int , configColorMode :: ColorMode , configFormatter :: Formatter@@ -40,7 +43,7 @@ } defaultConfig :: Config-defaultConfig = Config False False False Nothing QC.stdArgs 5 ColorAuto specdoc False (Left stdout)+defaultConfig = Config False False False Nothing Nothing Nothing Nothing Nothing 5 ColorAuto specdoc False (Left stdout) -- | Add a filter predicate to config. If there is already a filter predicate, -- then combine them with `||`.@@ -54,16 +57,16 @@ (Just p1, Just p2) -> Just $ \path -> p1 path || p2 path _ -> p1_ <|> p2_ -configSetSeed :: Integer -> Config -> Config-configSetSeed n c = c {configQuickCheckArgs = (configQuickCheckArgs c) {QC.replay = Just (stdGenFromInteger n, 0)}}- mkConfig :: Maybe FailureReport -> Options -> Config mkConfig mFailureReport opts = Config { configDryRun = optionsDryRun opts , configPrintCpuTime = optionsPrintCpuTime opts , configFastFail = optionsFastFail opts , configFilterPredicate = matchFilter `filterOr` rerunFilter- , configQuickCheckArgs = qcArgs+ , configQuickCheckSeed = mSeed+ , configQuickCheckMaxSuccess = mMaxSuccess+ , configQuickCheckMaxDiscardRatio = mMaxDiscardRatio+ , configQuickCheckMaxSize = mMaxSize , configSmallCheckDepth = fromMaybe (configSmallCheckDepth defaultConfig) (optionsDepth opts) , configColorMode = optionsColorMode opts , configFormatter = optionsFormatter opts@@ -71,17 +74,27 @@ , configHandle = maybe (configHandle defaultConfig) Right (optionsOutputFile opts) } where- qcArgs = (- maybe id setSeed mSeed- . maybe id setMaxDiscardRatio mMaxDiscardRatio- . maybe id setMaxSize mMaxSize- . maybe id setMaxSuccess mMaxSuccess) QC.stdArgs mSeed = optionsSeed opts <|> (failureReportSeed <$> mFailureReport) mMaxSuccess = optionsMaxSuccess opts <|> (failureReportMaxSuccess <$> mFailureReport) mMaxSize = optionsMaxSize opts <|> (failureReportMaxSize <$> mFailureReport) mMaxDiscardRatio = optionsMaxDiscardRatio opts <|> (failureReportMaxDiscardRatio <$> mFailureReport) + matchFilter = case optionsMatch opts of+ [] -> Nothing+ xs -> Just $ foldl1' (\p0 p1 path -> p0 path || p1 path) (map filterPredicate xs)++ rerunFilter = flip elem . failureReportPaths <$> mFailureReport++configQuickCheckArgs :: Config -> QC.Args+configQuickCheckArgs c = qcArgs+ where+ qcArgs = (+ maybe id setSeed (configQuickCheckSeed c)+ . maybe id setMaxDiscardRatio (configQuickCheckMaxDiscardRatio c)+ . maybe id setMaxSize (configQuickCheckMaxSize c)+ . maybe id setMaxSuccess (configQuickCheckMaxSuccess c)) QC.stdArgs+ setMaxSuccess :: Int -> QC.Args -> QC.Args setMaxSuccess n args = args {QC.maxSuccess = n} @@ -92,13 +105,7 @@ setMaxDiscardRatio n args = args {QC.maxDiscardRatio = n} setSeed :: Integer -> QC.Args -> QC.Args- setSeed n args = args {QC.replay = Just (stdGenFromInteger n, 0)}-- matchFilter = case optionsMatch opts of- [] -> Nothing- xs -> Just $ foldl1' (\p0 p1 path -> p0 path || p1 path) (map filterPredicate xs)-- rerunFilter = flip elem . failureReportPaths <$> mFailureReport+ setSeed n args = args {QC.replay = Just (mkQCGen (fromIntegral n), 0)} getConfig :: Options -> String -> [String] -> IO Config getConfig opts_ prog args = do
src/Test/Hspec/Core.hs view
@@ -42,14 +42,6 @@ hspecWith :: Config -> [SpecTree] -> IO Summary hspecWith c = Runner.hspecWith c . fromSpecList -mapSpecItem :: (Item -> Item) -> Spec -> Spec-mapSpecItem f = fromSpecList . map go . runSpecM- where- go :: SpecTree -> SpecTree- go spec = case spec of- SpecItem item -> SpecItem (f item)- SpecGroup d es -> SpecGroup d (map go es)- modifyParams :: (Params -> Params) -> Spec -> Spec modifyParams f = mapSpecItem $ \item -> item {itemExample = \p -> (itemExample item) (f p)}
src/Test/Hspec/Core/QuickCheckUtil.hs view
@@ -1,16 +1,19 @@-{-# LANGUAGE CPP #-} module Test.Hspec.Core.QuickCheckUtil where -import Data.IORef-import Test.QuickCheck hiding (Result(..))-import Test.QuickCheck as QC-import Test.QuickCheck.Property hiding (Result(..))+import Control.Applicative+import Control.Exception+import Data.Int+import Data.IORef+import Test.QuickCheck hiding (Result(..))+import Test.QuickCheck as QC+import Test.QuickCheck.Property hiding (Result(..)) import qualified Test.QuickCheck.Property as QCP-import Test.QuickCheck.IO ()-import Control.Applicative+import Test.QuickCheck.IO ()+import Test.QuickCheck.Random+import System.Random aroundProperty :: (IO () -> IO ()) -> Property -> Property-aroundProperty action p = MkProp . aroundRose action . unProp <$> p+aroundProperty action (MkProperty p) = MkProperty $ MkProp . aroundRose action . unProp <$> p aroundRose :: (IO () -> IO ()) -> Rose QCP.Result -> Rose QCP.Result aroundRose action r = ioRose $ do@@ -20,9 +23,8 @@ isUserInterrupt :: QC.Result -> Bool isUserInterrupt r = case r of-#if MIN_VERSION_QuickCheck(2,6,0)- QC.Failure {QC.interrupted = x} -> x-#else- QC.Failure {QC.reason = "Exception: 'user interrupt'"} -> True-#endif+ QC.Failure {theException = me} -> (me >>= fromException) == Just UserInterrupt _ -> False++newSeed :: IO Int+newSeed = fromIntegral <$> (fst . randomR (0, maxBound) <$> newQCGen :: IO Int32)
src/Test/Hspec/Core/Type.hs view
@@ -6,6 +6,7 @@ , fromSpecList , SpecTree (..) , Item (..)+, mapSpecItem , Example (..) , Result (..) , Params (..)@@ -60,8 +61,8 @@ forceResult :: Result -> Result forceResult r = case r of Success -> r- Pending m -> r `seq` m `deepseq` r- Fail m -> r `seq` m `deepseq` r+ Pending m -> m `deepseq` r+ Fail m -> m `deepseq` r instance E.Exception Result @@ -83,6 +84,14 @@ , itemRequirement :: String , itemExample :: Params -> (IO () -> IO ()) -> IO Result }++mapSpecItem :: (Item -> Item) -> Spec -> Spec+mapSpecItem f = fromSpecList . map go . runSpecM+ where+ go :: SpecTree -> SpecTree+ go spec = case spec of+ SpecItem item -> SpecItem (f item)+ SpecGroup d es -> SpecGroup d (map go es) -- | The @describe@ function combines a list of specs into a larger spec. describe :: String -> [SpecTree] -> SpecTree
src/Test/Hspec/Runner.hs view
@@ -29,16 +29,16 @@ import System.Console.ANSI (hHideCursor, hShowCursor) import qualified Test.QuickCheck as QC-import System.Random (newStdGen) import Control.Monad.IO.Class (liftIO) import Test.Hspec.Compat (lookupEnv)-import Test.Hspec.Util (Path, stdGenToInteger)+import Test.Hspec.Util (Path) import Test.Hspec.Core.Type import Test.Hspec.Config import Test.Hspec.Formatters import Test.Hspec.Formatters.Internal import Test.Hspec.FailureReport+import Test.Hspec.Core.QuickCheckUtil import Test.Hspec.Options (Options(..), ColorMode(..), defaultOptions) import Test.Hspec.Runner.Eval@@ -71,16 +71,14 @@ f <- toFormatter formatter hspecWithOptions defaultOptions {optionsFormatter = f} spec --- Add a StdGen to configQuickCheckArgs if there is none. That way the same--- seed is used for all properties. This helps with --seed and --rerun.-ensureStdGen :: Config -> IO Config-ensureStdGen c = case QC.replay qcArgs of+-- Add a seed to given config if there is none. That way the same seed is used+-- for all properties. This helps with --seed and --rerun.+ensureSeed :: Config -> IO Config+ensureSeed c = case configQuickCheckSeed c of Nothing -> do- stdGen <- newStdGen- return c {configQuickCheckArgs = qcArgs {QC.replay = Just (stdGen, 0)}}+ seed <- newSeed+ return c {configQuickCheckSeed = Just (fromIntegral seed)} _ -> return c- where- qcArgs = configQuickCheckArgs c -- | Run given spec with custom options. -- This is similar to `hspec`, but more flexible.@@ -107,10 +105,14 @@ -- items. If you need this, you have to check the `Summary` yourself and act -- accordingly. hspecWith :: Config -> Spec -> IO Summary-hspecWith c_ spec = withHandle c_ $ \h -> do- c <- ensureStdGen c_+hspecWith c_ spec_ = withHandle c_ $ \h -> do+ c <- ensureSeed c_ let formatter = configFormatter c- seed = (stdGenToInteger . fst . fromJust . QC.replay . configQuickCheckArgs) c+ seed = (fromJust . configQuickCheckSeed) c+ qcArgs = configQuickCheckArgs c+ spec+ | configDryRun c = mapSpecItem markSuccess spec_+ | otherwise = spec_ useColor <- doesUseColor h c @@ -125,9 +127,9 @@ xs <- map failureRecordPath <$> getFailMessages liftIO $ writeFailureReport FailureReport { failureReportSeed = seed- , failureReportMaxSuccess = QC.maxSuccess (configQuickCheckArgs c)- , failureReportMaxSize = QC.maxSize (configQuickCheckArgs c)- , failureReportMaxDiscardRatio = QC.maxDiscardRatio (configQuickCheckArgs c)+ , failureReportMaxSuccess = QC.maxSuccess qcArgs+ , failureReportMaxSize = QC.maxSize qcArgs+ , failureReportMaxDiscardRatio = QC.maxDiscardRatio qcArgs , failureReportPaths = xs } @@ -151,6 +153,9 @@ isDumb :: IO Bool isDumb = maybe False (== "dumb") <$> lookupEnv "TERM"++markSuccess :: Item -> Item+markSuccess item = item {itemExample = evaluateExample Success} -- | Summary of a test run. data Summary = Summary {
src/Test/Hspec/Runner/Eval.hs view
@@ -1,5 +1,7 @@+{-# LANGUAGE DeriveFunctor #-} module Test.Hspec.Runner.Eval (runFormatter) where +import Control.Applicative import Control.Monad import qualified Control.Exception as E import Control.Concurrent@@ -15,111 +17,137 @@ import Test.Hspec.Timer import Data.Time.Clock.POSIX +data Tree a+ = Node String [Tree a]+ | Leaf String a+ deriving (Eq, Show, Functor)++toTree :: SpecTree -> Tree Item+toTree spec = case spec of+ SpecGroup label specs -> Node label (map toTree specs)+ SpecItem item -> Leaf (itemRequirement item) item++type EvalTree = Tree (ProgressCallback -> FormatResult -> IO (FormatM ()))+ -- | Evaluate all examples of a given spec and produce a report. runFormatter :: Bool -> Handle -> Config -> Formatter -> [SpecTree] -> FormatM ()-runFormatter useColor h c formatter specs = do+runFormatter useColor h c formatter specs_ = do headerFormatter formatter chan <- liftIO newChan- run chan useColor h c formatter specs+ reportProgress <- liftIO mkReportProgress+ run chan reportProgress c formatter specs+ where+ mkReportProgress :: IO (Path -> Progress -> IO ())+ mkReportProgress+ | useColor = every 0.05 $ exampleProgress formatter h+ | otherwise = return $ \_ _ -> return () -data Message = Done | Run (FormatM ())+ specs = map (fmap (parallelize . fmap (applyNoOpAround . applyQuickCheckArgs) . unwrapItem) . toTree) specs_ + unwrapItem :: Item -> (Bool, Params -> (IO () -> IO ()) -> IO Result)+ unwrapItem (Item isParallelizable _ e) = (isParallelizable, e)++ applyQuickCheckArgs :: (Params -> a) -> ProgressCallback -> a+ applyQuickCheckArgs e progressCallback = e $ Params (configQuickCheckArgs c) (configSmallCheckDepth c) progressCallback++ applyNoOpAround :: (a -> (IO () -> IO ()) -> b) -> a -> b+ applyNoOpAround = fmap ($ id)++-- | Execute given action at most every specified number of seconds.+every :: POSIXTime -> (a -> b -> IO ()) -> IO (a -> b -> IO ())+every seconds action = do+ timer <- newTimer seconds+ return $ \a b -> do+ r <- timer+ when r (action a b)++type ProgressCallback = Progress -> IO ()+type FormatResult = Either E.SomeException Result -> FormatM ()++parallelize :: (Bool, ProgressCallback -> IO Result) -> ProgressCallback -> FormatResult -> IO (FormatM ())+parallelize (isParallelizable, e)+ | isParallelizable = runParallel e+ | otherwise = runSequentially e++runSequentially :: (ProgressCallback -> IO Result) -> ProgressCallback -> FormatResult -> IO (FormatM ())+runSequentially e reportProgress formatResult = return $ do+ result <- liftIO $ evalExample (e reportProgress)+ formatResult result+ data Report = ReportProgress Progress | ReportResult (Either E.SomeException Result) -run :: Chan Message -> Bool -> Handle -> Config -> Formatter -> [SpecTree] -> FormatM ()-run chan useColor h c formatter specs = do+runParallel :: (ProgressCallback -> IO Result) -> ProgressCallback -> FormatResult -> IO (FormatM ())+runParallel e reportProgress formatResult = do+ mvar <- newEmptyMVar+ _ <- forkIO $ do+ let progressCallback = replaceMVar mvar . ReportProgress+ result <- evalExample (e progressCallback)+ replaceMVar mvar (ReportResult result)+ return $ evalReport mvar+ where+ evalReport :: MVar Report -> FormatM ()+ evalReport mvar = do+ r <- liftIO (takeMVar mvar)+ case r of+ ReportProgress p -> do+ liftIO $ reportProgress p+ evalReport mvar+ ReportResult result -> formatResult result++replaceMVar :: MVar a -> a -> IO ()+replaceMVar mvar p = tryTakeMVar mvar >> putMVar mvar p++evalExample :: IO Result -> IO (Either E.SomeException Result)+evalExample e = safeTry $ forceResult <$> e++data Message = Done | Run (FormatM ())++run :: Chan Message -> (Path -> ProgressCallback) -> Config -> Formatter -> [EvalTree] -> FormatM ()+run chan reportProgress_ c formatter specs = do liftIO $ do forM_ (zip [0..] specs) (queueSpec []) writeChan chan Done- processChan chan (configFastFail c)+ processMessages (readChan chan) (configFastFail c) where+ defer :: FormatM () -> IO () defer = writeChan chan . Run - queueSpec :: [String] -> (Int, SpecTree) -> IO ()- queueSpec rGroups (n, SpecGroup group xs) = do+ queueSpec :: [String] -> (Int, EvalTree) -> IO ()+ queueSpec rGroups (n, Node group xs) = do defer (exampleGroupStarted formatter n (reverse rGroups) group) forM_ (zip [0..] xs) (queueSpec (group : rGroups)) defer (exampleGroupDone formatter)- queueSpec rGroups (_, SpecItem (Item isParallelizable requirement e)) =- queueExample isParallelizable (reverse rGroups, requirement) (`e` id)+ queueSpec rGroups (_, Leaf requirement e) =+ queueExample (reverse rGroups, requirement) e - queueExample :: Bool -> Path -> (Params -> IO Result) -> IO ()- queueExample isParallelizable path e- | isParallelizable = runParallel- | otherwise = defer runSequentially+ queueExample :: Path -> (ProgressCallback -> FormatResult -> IO (FormatM ())) -> IO ()+ queueExample path e = e reportProgress formatResult >>= defer where- runSequentially :: FormatM ()- runSequentially = do- progressHandler <- liftIO (mkProgressHandler reportProgress)- result <- liftIO (evalExample e progressHandler)- formatResult formatter path result+ reportProgress = reportProgress_ path - runParallel = do- mvar <- newEmptyMVar- _ <- forkIO $ do- progressHandler <- mkProgressHandler (replaceMVar mvar . ReportProgress)- result <- evalExample e progressHandler- replaceMVar mvar (ReportResult result)- defer (evalReport mvar)+ formatResult :: Either E.SomeException Result -> FormatM ()+ formatResult result = do+ case result of+ Right Success -> do+ increaseSuccessCount+ exampleSucceeded formatter path+ Right (Pending reason) -> do+ increasePendingCount+ examplePending formatter path reason+ Right (Fail err) -> failed (Right err)+ Left err -> failed (Left err) where- evalReport :: MVar Report -> FormatM ()- evalReport mvar = do- r <- liftIO (takeMVar mvar)- case r of- ReportProgress p -> do- liftIO $ reportProgress p- evalReport mvar- ReportResult result -> formatResult formatter path result-- reportProgress :: (Int, Int) -> IO ()- reportProgress = exampleProgress formatter h path-- mkProgressHandler :: (a -> IO ()) -> IO (a -> IO ())- mkProgressHandler report- | useColor = every 0.05 report- | otherwise = return . const $ return ()-- evalExample :: (Params -> IO Result) -> (Progress -> IO ()) -> IO (Either E.SomeException Result)- evalExample e progressHandler- | configDryRun c = return (Right Success)- | otherwise = (safeTry . fmap forceResult) (e $ Params (configQuickCheckArgs c) (configSmallCheckDepth c) progressHandler)--replaceMVar :: MVar a -> a -> IO ()-replaceMVar mvar p = tryTakeMVar mvar >> putMVar mvar p--processChan :: Chan Message -> Bool -> FormatM ()-processChan chan fastFail = go- where- go = do- m <- liftIO (readChan chan)- case m of- Run action -> do- action- fails <- getFailCount- unless (fastFail && fails /= 0) go- Done -> return ()+ failed err = do+ increaseFailCount+ addFailMessage path err+ exampleFailed formatter path err -formatResult :: Formatter -> ([String], String) -> Either E.SomeException Result -> FormatM ()-formatResult formatter path result = do- case result of- Right Success -> do- increaseSuccessCount- exampleSucceeded formatter path- Right (Pending reason) -> do- increasePendingCount- examplePending formatter path reason- Right (Fail err) -> failed (Right err)- Left e -> failed (Left e)+processMessages :: IO Message -> Bool -> FormatM ()+processMessages getMessage fastFail = go where- failed err = do- increaseFailCount- addFailMessage path err- exampleFailed formatter path err---- | Execute given action at most every specified number of seconds.-every :: POSIXTime -> (a -> IO ()) -> IO (a -> IO ())-every seconds action = do- timer <- newTimer seconds- return $ \a -> do- r <- timer- when r (action a)+ go = liftIO getMessage >>= \m -> case m of+ Run action -> do+ action+ fails <- getFailCount+ unless (fastFail && fails /= 0) go+ Done -> return ()
src/Test/Hspec/Util.hs view
@@ -6,16 +6,12 @@ , filterPredicate , formatRequirement , strip-, stdGenToInteger-, stdGenFromInteger ) where -import Data.Int (Int32) import Data.List import Data.Char (isSpace) import Control.Applicative import qualified Control.Exception as E-import System.Random (StdGen) -- | Create a more readable display of a quantity of something. --@@ -90,17 +86,3 @@ strip :: String -> String strip = dropWhile isSpace . reverse . dropWhile isSpace . reverse---- | Converts a 'StdGen' into an 'Integer'. Assumes--- StdGens to be encoded as two positive 'Int32's and--- $show (StdGen a b) = show a ++ " " ++ show b$.-stdGenToInteger :: StdGen -> Integer-stdGenToInteger stdGen =- let [a, b] = map read . words $ show stdGen- in b * fromIntegral (maxBound :: Int32) + a---- | Inverse of 'stdGenToInteger'.-stdGenFromInteger :: Integer -> StdGen-stdGenFromInteger n =- let (a, b) = quotRem n (fromIntegral (maxBound :: Int32))- in read (show b ++ " " ++ show a)
test/Helper.hs view
@@ -33,6 +33,7 @@ import Test.Hspec.Meta import Test.QuickCheck hiding (Result(..))+import Test.QuickCheck.Random import qualified Test.Hspec as H import qualified Test.Hspec.Core as H (Params(..), Item(..), mapSpecItem)@@ -63,7 +64,7 @@ | otherwise = x defaultParams :: H.Params-defaultParams = H.Params (H.configQuickCheckArgs H.defaultConfig) (H.configSmallCheckDepth H.defaultConfig) (const $ return ())+defaultParams = H.Params stdArgs {replay = Just (mkQCGen 23, 0)} (H.configSmallCheckDepth H.defaultConfig) (const $ return ()) sleep :: POSIXTime -> IO () sleep = threadDelay . floor . (* 1000000)
test/Test/Hspec/Core/TypeSpec.hs view
@@ -14,10 +14,10 @@ main = hspec spec evaluateExample :: H.Example e => e -> IO H.Result-evaluateExample e = H.evaluateExample e (defaultParams {H.paramsQuickCheckArgs = (H.paramsQuickCheckArgs defaultParams) {replay = Just (read "", 0)}}) id+evaluateExample e = H.evaluateExample e defaultParams id evaluateExampleWith :: H.Example e => (IO () -> IO ()) -> e -> IO H.Result-evaluateExampleWith action e = H.evaluateExample e (defaultParams {H.paramsQuickCheckArgs = (H.paramsQuickCheckArgs defaultParams) {replay = Just (read "", 0)}}) action+evaluateExampleWith action e = H.evaluateExample e defaultParams action spec :: Spec spec = do@@ -72,7 +72,7 @@ it "shows what falsified it" $ do H.Fail r <- evaluateExample $ property $ \x y -> x + y == (x * y :: Int) r `shouldBe` intercalate "\n" [- "Falsifiable (after 1 test and 2 shrinks): "+ "Falsifiable (after 2 tests and 2 shrinks): " , "0" , "1" ]@@ -92,7 +92,7 @@ it "shows what falsified it" $ do H.Fail r <- evaluateExample $ property $ \x y -> x + y `shouldBe` (x * y :: Int) r `shouldBe` intercalate "\n" [- "Falsifiable (after 1 test and 2 shrinks): "+ "Falsifiable (after 2 tests and 2 shrinks): " , "expected: 0" , " but got: 1" , "0"
test/Test/Hspec/RunnerSpec.hs view
@@ -88,16 +88,14 @@ it "reuses the same seed" $ do let runSpec_ = (captureLines . ignoreExitCode . H.hspec) $ do H.it "foo" $ property $ (/= (26 :: Integer))-- r0 <- withArgs ["--seed", "2413421499272008081"] runSpec_+ r0 <- withArgs ["--seed", "42"] runSpec_ r0 `shouldContain` [- "Falsifiable (after 66 tests): "+ "Falsifiable (after 31 tests): " , "26" ]- r1 <- withArgs ["-r"] runSpec_ r1 `shouldContain` [- "Falsifiable (after 66 tests): "+ "Falsifiable (after 31 tests): " , "26" ] @@ -294,11 +292,11 @@ context "with --seed" $ do it "uses specified seed" $ do- r <- captureLines . ignoreExitCode . withArgs ["--seed", "2413421499272008081"] . H.hspec $ do+ r <- captureLines . ignoreExitCode . withArgs ["--seed", "42"] . H.hspec $ do H.it "foo" $ property (/= (26 :: Integer)) r `shouldContain` [- "Falsifiable (after 66 tests): "+ "Falsifiable (after 31 tests): " , "26" ] @@ -308,13 +306,13 @@ H.it "foo" $ property $ \n -> ((17 + 31 * n) `mod` 50) /= (23 :: Integer) r0 <- runSpec ["--seed", "23"]- r0 `shouldContain` "(after 88 tests)"+ r0 `shouldContain` "(after 27 tests)" r1 <- runSpec ["--seed", "42"]- r1 `shouldContain` "(after 48 tests)"+ r1 `shouldContain` "(after 31 tests)" r2 <- runSpec ["--rerun", "--seed", "23"]- r2 `shouldContain` "(after 88 tests)"+ r2 `shouldContain` "(after 27 tests)" context "when given an invalid argument" $ do let run = withArgs ["--seed", "foo"] . H.hspec $ do
test/Test/Hspec/UtilSpec.hs view
@@ -1,9 +1,6 @@-{-# OPTIONS_GHC -fno-warn-orphans #-} module Test.Hspec.UtilSpec (main, spec) where import Helper-import Data.Int (Int32)-import System.Random (StdGen) import qualified Control.Exception as E import Test.Hspec.Util@@ -90,19 +87,3 @@ it "properly handles context after a subject that consists of several components" $ do formatRequirement (["Data", "List", "reverse", "when applied twice"], "reverses a list") `shouldBe` "Data.List.reverse, when applied twice, reverses a list"-- describe "stdGenToInteger" $ do- it "is inverse to stdGenFromInteger" $ property $- \(NonNegative i) -> (stdGenToInteger . stdGenFromInteger) i `shouldBe` i-- describe "stdGenFromInteger" $ do- it "is inverse to stdGenToInteger" $ property $- \stdGen -> (stdGenFromInteger . stdGenToInteger) stdGen `shouldBe` stdGen--instance Eq StdGen where- a == b = show a == show b--instance Arbitrary StdGen where- arbitrary = do- (Positive a, Positive b) <- arbitrary- return $ read (show (a :: Int32) ++ " " ++ show (b :: Int32))