packages feed

hspec 1.1.3 → 1.2.0

raw patch · 16 files changed

+362/−345 lines, 16 filesdep +doctestdep +hspecdep +hspec-discoverdep ~HUnitdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: doctest, hspec, hspec-discover

Dependency ranges changed: HUnit, base

API changes (from Hackage documentation)

- Test.Hspec: descriptions :: Specs -> Specs
- Test.Hspec: hspecX :: Specs -> IO a
- Test.Hspec.Core: SpecExample :: String -> a -> SpecTree a
- Test.Hspec.Core: SpecGroup :: String -> [SpecTree a] -> SpecTree a
- Test.Hspec.Core: data SpecTree a
- Test.Hspec.Core: descriptions :: Specs -> Specs
- Test.Hspec.Core: failedCount :: [EvaluatedSpec] -> Int
- Test.Hspec.Core: failure :: [EvaluatedSpec] -> Bool
- Test.Hspec.Core: hspecX :: Specs -> IO a
- Test.Hspec.Core: isFailure :: Result -> Bool
- Test.Hspec.Core: safeEvaluateExample :: AnyExample -> IO Result
- Test.Hspec.Core: success :: [EvaluatedSpec] -> Bool
- Test.Hspec.Core: type AnyExample = IO Result
- Test.Hspec.Core: type EvaluatedSpec = SpecTree Result
- Test.Hspec.Core: type UnevaluatedSpec = Spec
- Test.Hspec.Monadic: descriptions :: [Spec] -> Spec
- Test.Hspec.Monadic: hspecX :: Spec -> IO a
- Test.Hspec.Monadic: type Spec = SpecM ()
- Test.Hspec.Monadic: type Specs = SpecM ()
- Test.Hspec.Runner: describe :: String -> [Spec] -> Spec
- Test.Hspec.Runner: it :: Example a => String -> a -> Spec
+ Test.Hspec: Summary :: Int -> Int -> Summary
+ Test.Hspec: data Summary
+ Test.Hspec: summaryExamples :: Summary -> Int
+ Test.Hspec: summaryFailures :: Summary -> Int
+ Test.Hspec.Core: Summary :: Int -> Int -> Summary
+ Test.Hspec.Core: data Summary
+ Test.Hspec.Core: summaryExamples :: Summary -> Int
+ Test.Hspec.Core: summaryFailures :: Summary -> Int
+ Test.Hspec.Monadic: Summary :: Int -> Int -> Summary
+ Test.Hspec.Monadic: data Summary
+ Test.Hspec.Monadic: summaryExamples :: Summary -> Int
+ Test.Hspec.Monadic: summaryFailures :: Summary -> Int
+ Test.Hspec.Runner: Summary :: Int -> Int -> Summary
+ Test.Hspec.Runner: data Summary
+ Test.Hspec.Runner: instance Eq Summary
+ Test.Hspec.Runner: instance Monoid Summary
+ Test.Hspec.Runner: instance Show Summary
+ Test.Hspec.Runner: summaryExamples :: Summary -> Int
+ Test.Hspec.Runner: summaryFailures :: Summary -> Int
- Test.Hspec: hHspec :: Handle -> Specs -> IO [EvaluatedSpec]
+ Test.Hspec: hHspec :: Handle -> Specs -> IO Summary
- Test.Hspec: hspec :: Specs -> IO [EvaluatedSpec]
+ Test.Hspec: hspec :: Specs -> IO ()
- Test.Hspec.Core: hHspec :: Handle -> Specs -> IO [EvaluatedSpec]
+ Test.Hspec.Core: hHspec :: Handle -> Specs -> IO Summary
- Test.Hspec.Core: hspec :: Specs -> IO [EvaluatedSpec]
+ Test.Hspec.Core: hspec :: Specs -> IO ()
- Test.Hspec.Core: quantify :: (Show a, Num a, Eq a) => a -> String -> String
+ Test.Hspec.Core: quantify :: Int -> String -> String
- Test.Hspec.Monadic: hHspec :: Handle -> Spec -> IO [EvaluatedSpec]
+ Test.Hspec.Monadic: hHspec :: Handle -> Spec -> IO Summary
- Test.Hspec.Monadic: hspec :: Spec -> IO [EvaluatedSpec]
+ Test.Hspec.Monadic: hspec :: Spec -> IO ()
- Test.Hspec.Runner: hHspec :: Handle -> Specs -> IO [EvaluatedSpec]
+ Test.Hspec.Runner: hHspec :: Handle -> Specs -> IO Summary
- Test.Hspec.Runner: hHspecWithFormat :: Formatter -> Bool -> Handle -> Specs -> IO [EvaluatedSpec]
+ Test.Hspec.Runner: hHspecWithFormat :: Formatter -> Bool -> Handle -> Specs -> IO Summary
- Test.Hspec.Runner: hspec :: Specs -> IO [EvaluatedSpec]
+ Test.Hspec.Runner: hspec :: Specs -> IO ()

Files

− Specs.hs
@@ -1,158 +0,0 @@-{-# OPTIONS_GHC -fno-warn-deprecations #-}-module Main (main) where--import           Test.Hspec.ShouldBe (Specs, describe, it, hspecX)--import qualified Test.Hspec as H-import           Test.Hspec hiding (Specs, describe, it, hspecX)-import           Test.Hspec.Runner (hHspecWithFormat)-import           Test.Hspec.Internal (SpecTree(..), Spec(..), Result(..), quantify)-import           Test.Hspec.Formatters-import           Test.Hspec.QuickCheck-import           Test.Hspec.HUnit ()-import           Test.HUnit-import           System.IO-import           System.IO.Silently-import           Data.List (isPrefixOf)-import qualified Test.HUnit as HUnit--main :: IO ()-main = specs >>= hspecX--specs :: IO Specs-specs = do-  let testSpecs = [H.describe "Example" [-          H.it "success" (Success),-          H.it "fail 1" (Fail "fail message"),-          H.it "pending" (pending "pending message"),-          H.it "fail 2" (HUnit.assertEqual "assertEqual test" 1 (2::Int)),-          H.it "exceptions" (undefined :: Bool),-          H.it "quickcheck" (property $ \ i -> i == (i+1::Integer))]-          ]--  (reportContents, exampleSpecs)     <- capture $ hHspecWithFormat specdoc         False stdout testSpecs-  (silentReportContents, _)          <- capture $ hHspecWithFormat silent          False stdout testSpecs-  (progressReportContents, _)        <- capture $ hHspecWithFormat progress        False stdout testSpecs-  (failed_examplesReportContents, _) <- capture $ hHspecWithFormat failed_examples False stdout testSpecs--  let report = lines reportContents--  return $ do-    describe "the \"describe\" function" $ do-        it "takes a description of what the behavior is for" $-            case exampleSpecs of-              [SpecGroup "Example" _] -> True-              _ -> False--        it "groups behaviors for what's being described" $-            case exampleSpecs of-              [SpecGroup _ xs] -> length xs == 6-              _ -> False--        describe "a nested description" $ do-            it "has it's own specs"-                (True)--    describe "the \"it\" function" $ do-        it "takes a description of a desired behavior" $-            case unSpec $ H.it "whatever" Success of-              SpecExample requirement _ -> requirement == "whatever"-              _ -> False--        it "takes an example of that behavior" $ do-            case unSpec $ H.it "whatever" Success of-              SpecExample _ example -> do-                r <- example-                r @?= Success-              SpecGroup _ _ -> assertFailure "unexpected SpecGroup"--        it "can use a Bool, HUnit Test, QuickCheck property, or \"pending\" as an example"-            (True)--        it "will treat exceptions as failures"-            (any (==" - exceptions FAILED [3]") report)--    describe "the \"hspec\" function" $ do-        it "displays a header for each thing being described"-            (any (=="Example") report)--        it "displays one row for each behavior"-            (HUnit.assertEqual "" 29 (length report))--        it "displays a row for each successfull, failed, or pending example"-            (any (==" - success") report && any (==" - fail 1 FAILED [1]") report)--        it "displays a detailed list of failed examples"-            (any (=="1) Example fail 1 FAILED") report)--        it "displays a '#' with an additional message for pending examples"-            (any (=="     # PENDING: pending message") report )--        it "summarizes the time it takes to finish"-            (any ("Finished in " `isPrefixOf`) report)--        it "summarizes the number of examples and failures"-            (any (=="6 examples, 4 failures") report)--        it "outputs failed examples in red, pending in yellow, and successful in green"-            (True)--    describe "Bool as an example" $ do-        it "is just an expression that evaluates to a Bool"-            (True)--    describe "HUnit TestCase as an example" $ do-        it "is specified with the HUnit \"TestCase\" data constructor"-            (HUnit.TestCase $ HUnit.assertBool "example" True)--        it "is the assumed example for IO() actions"-            (HUnit.assertBool "example" True)--        it "will show the failed assertion text if available (e.g. assertBool)" $ do-          (innerReport, _) <- capture $ hspec $ [H.describe "" [ H.it "" (HUnit.assertBool "trivial" False)]]-          HUnit.assertBool "should find assertion text" $ any (=="trivial") (lines innerReport)--        it "will show the failed assertion expected and actual values if available (e.g. assertEqual)" $ do-          (innerReportContents, _) <- capture $ hspec $ [H.describe "" [ H.it "" (HUnit.assertEqual "trivial" (1::Int) 2)]]-          let innerReport = lines innerReportContents-          HUnit.assertBool "should find assertion text" $ any (=="trivial") innerReport-          HUnit.assertBool "should find 'expected: 1'" $ any (=="expected: 1") innerReport-          HUnit.assertBool "should find ' but got: 2'" $ any (==" but got: 2") innerReport--    describe "QuickCheck property as an example" $ do-        it "is specified with the \"property\" function"-            (property $ \ b -> b || True)--        it "will show what falsified it"-            (any (=="0") report)--    describe "pending as an example" $ do-        it "is specified with the \"pending\" function and an explanation" True--        it "accepts a message to display in the report" True--    describe "the \"hHspecWithFormat\" function" $ do-        it "can use the \"silent\" formatter to show no output"-            (null silentReportContents)--        it "can use the \"progress\" formatter to show '..F...FF.F' style output"-            (HUnit.assertEqual "" ".F.FFF" (head $ lines progressReportContents))--        it "can use the \"specdoc\" formatter to show all examples (default)"-            (HUnit.assertEqual "" "Example" (lines reportContents !! 1))--        it "can use the \"failed_examples\" formatter to show only failed examples"-            (HUnit.assertEqual "" "1) Example fail 1 FAILED" (lines failed_examplesReportContents !! 1))--    describe "quantify (an internal function)" $ do-        it "returns an amount and a word given an amount and word"-            (quantify (1::Int) "thing" == "1 thing")--        it "returns a singular word given the number 1"-            (quantify (1::Int) "thing" == "1 thing")--        it "returns a plural word given a number greater than 1"-            (quantify (2::Int) "thing" == "2 things")--        it "returns a plural word given the number 0"-            (quantify (0::Int) "thing" == "0 things")
Test/Hspec.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_HADDOCK prune #-} -- | -- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is -- an approach to software development that combines Test-Driven Development,@@ -34,14 +35,25 @@ -- * Running a spec , hspec , hspecB-, hspecX , hHspec+, Summary (..) --- * Deprecated functions+++++-- deprecated functions , descriptions+, hspecX+++ ) where  import           Test.Hspec.Core+++  -- $intro --
Test/Hspec/Core.hs view
@@ -1,8 +1,27 @@-{-# OPTIONS_GHC -fno-warn-deprecations #-}+{-# OPTIONS_HADDOCK prune #-} -- |--- This module contains the core types, constructors, classes, instances, and--- utility functions common to hspec.+-- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is+-- an approach to software development that combines Test-Driven Development,+-- Domain Driven Design, and Acceptance Test-Driven Planning. Hspec helps you+-- do the TDD part of that equation, focusing on the documentation and design+-- aspects of TDD.+--+-- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of+-- what applies to RSpec also applies to Hspec. Hspec ties together+-- /descriptions/ of behavior and /examples/ of that behavior. The examples can+-- also be run as tests and the output summarises what needs to be implemented.+--+-- NOTE: There is a monadic and a non-monadic API.  This is the documentation+-- for the non-monadic API.  The monadic API is more stable, so you may prefer+-- it over this one.  For documentation on the monadic API look at+-- "Test.Hspec.Monadic".+ module Test.Hspec.Core (+++-- * Introduction+-- $intro+ -- * Types   Spec , Specs@@ -17,29 +36,19 @@ -- * Running a spec , hspec , hspecB-, hspecX , hHspec+, Summary (..)  -- * Internals-, SpecTree (..)-, EvaluatedSpec-, Result (..) , quantify+, Result (..) --- * Deprecated types and functions--- | The following types and functions are deprecated and will be removed with--- the next release.------ If you still need any of those, please open an issue and describe your use--- case: <https://github.com/hspec/hspec/issues>+-- deprecated stuff , descriptions+, hspecX , AnyExample , safeEvaluateExample , UnevaluatedSpec-, success-, failure-, isFailure-, failedCount ) where  import           Test.Hspec.Internal hiding (safeEvaluateExample)@@ -47,36 +56,85 @@ import           Test.Hspec.Pending import           Test.Hspec.Runner +-- $intro+--+-- The three functions you'll use the most are 'hspecX', 'describe', and 'it'.+-- Here is an example of functions that format and unformat phone numbers and+-- the specs for them.+--+-- > import Test.Hspec+-- > import Test.Hspec.QuickCheck+-- > import Test.Hspec.HUnit ()+-- > import Test.QuickCheck+-- > import Test.HUnit+-- >+-- > main = hspecX mySpecs+--+-- Since the specs are often used to tell you what to implement, it's best to+-- start with undefined functions. Once we have some specs, then you can+-- implement each behavior one at a time, ensuring that each behavior is met+-- and there is no undocumented behavior.+--+-- > unformatPhoneNumber :: String -> String+-- > unformatPhoneNumber number = undefined+-- >+-- > formatPhoneNumber :: String -> String+-- > formatPhoneNumber number = undefined+--+-- The 'describe' function takes a list of behaviors and examples bound+-- together with the 'it' function+--+-- > mySpecs = [describe "unformatPhoneNumber" [+--+-- A boolean expression can act as a behavior's example.+--+-- >   it "removes dashes, spaces, and parenthesies" $+-- >     unformatPhoneNumber "(555) 555-1234" == "5555551234"+-- >   ,+--+-- The 'pending' function marks a behavior as pending an example. The example+-- doesn't count as failing.+--+-- >   it "handles non-US phone numbers" $+-- >     pending "need to look up how other cultures format phone numbers"+-- >   ,+--+-- An HUnit 'Test.HUnit.Test' can act as a behavior's example. (must import+-- "Test.Hspec.HUnit")+--+-- >   it "removes the \"ext\" prefix of the extension" $ TestCase $ do+-- >     let expected = "5555551234135"+-- >         actual   = unformatPhoneNumber "(555) 555-1234 ext 135"+-- >     expected @?= actual+-- >   ,+--+-- An @IO()@ action is treated like an HUnit 'TestCase'. (must import+-- "Test.Hspec.HUnit")+--+-- >   it "converts letters to numbers" $ do+-- >     let expected = "6862377"+-- >         actual   = unformatPhoneNumber "NUMBERS"+-- >     actual @?= expected+-- >   ,+--+-- The 'property' function allows a QuickCheck property to act as an example.+-- (must import "Test.Hspec.QuickCheck")+--+-- >   it "can add and remove formatting without changing the number" $ property $+-- >     forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n+-- >   ]]+-- >+-- > phoneNumber :: Gen String+-- > phoneNumber = do+-- >   n <- elements [7,10,11,12,13,14,15]+-- >   vectorOf n (elements "0123456789")+ {-# DEPRECATED UnevaluatedSpec "use Spec instead" #-} type UnevaluatedSpec = Spec --- | DEPRECATED: This is no longer needed (it's just an alias for `id` now).+{-# DEPRECATED descriptions "this is no longer needed, and will be removed in a future release" #-} descriptions :: Specs -> Specs descriptions = id-{-# DEPRECATED descriptions "this is no longer needed, and will be removed in a future release" #-}--{-# DEPRECATED success "This will be removed with the next major release.  If you still need this, raise your voice!" #-}-success :: [EvaluatedSpec] -> Bool-success = not . failure--{-# DEPRECATED failure "This will be removed with the next major release.  If you still need this, raise your voice!" #-}-failure :: [EvaluatedSpec] -> Bool-failure = any p-  where-    p (SpecGroup _ xs) = any p xs-    p (SpecExample _ x) = isFailure x--{-# DEPRECATED isFailure "This will be removed with the next major release.  If you still need this, raise your voice!" #-}-isFailure :: Result -> Bool-isFailure (Fail _) = True-isFailure _        = False--{-# DEPRECATED failedCount "This will be removed with the next major release.  If you still need this, raise your voice!" #-}-failedCount :: [EvaluatedSpec] -> Int-failedCount = sum . map count-  where-    count (SpecGroup _ xs) = sum (map count xs)-    count (SpecExample _ x) = if isFailure x then 1 else 0  {-# DEPRECATED AnyExample "This will be removed with the next major release.  If you still need this, raise your voice!" #-} type AnyExample  = IO Result
Test/Hspec/Formatters.hs view
@@ -43,6 +43,7 @@ import           Data.List (intersperse) import           Text.Printf import           Control.Monad (unless)+import           Control.Applicative  -- We use an explicit import list for "Test.Hspec.Formatters.Internal", to make -- sure, that we only use the public API to implement formatters.@@ -134,12 +135,12 @@  defaultFooter :: FormatM () defaultFooter = do-  cpuTime <- getCPUTime-  time <- getRealTime++  writeLine =<< printf "Finished in %1.4f seconds, used %1.4f seconds of CPU time" <$> getRealTime <*> getCPUTime+   fails <- getFailCount   total <- getTotalCount   (if fails == 0 then withSuccessColor else withFailColor) $ do-    writeLine $ printf "Finished in %1.4f seconds, used %1.4f seconds of CPU time" time cpuTime     writeLine ""     write $ quantify total "example" ++ ", "     writeLine $ quantify fails "failure"
Test/Hspec/Formatters/Internal.hs view
@@ -32,6 +32,7 @@ import qualified System.IO as IO import           System.IO (Handle) import           Control.Monad (when)+import           Control.Applicative import           Control.Exception (bracket_) import           System.Console.ANSI import           Control.Monad.Trans.State hiding (gets, modify)@@ -72,7 +73,7 @@ totalCount s = successCount s + pendingCount s + failCount s  newtype FormatM a = FormatM (StateT FormatterState IO a)-  deriving (Functor, Monad)+  deriving (Functor, Applicative, Monad)  runFormatM :: Bool -> Handle -> FormatM a -> IO a runFormatM useColor handle (FormatM action) = do
Test/Hspec/HUnit.hs view
@@ -23,8 +23,7 @@ -- >     it "gives the original list, if applied twice" $ TestCase $ -- >       (reverse . reverse) [1, 2, 3] @?= [1, 2, 3] ---module Test.Hspec.HUnit (-) where+module Test.Hspec.HUnit () where  import           System.IO.Silently import           Test.Hspec.Core@@ -41,6 +40,6 @@              then Success              else Fail (details $ fails "")     return r--details :: String -> String-details = concat . intersperse "\n" . tail . init . lines+    where+      details :: String -> String+      details = concat . intersperse "\n" . tail . init . lines
Test/Hspec/Internal.hs view
@@ -1,9 +1,6 @@-{-# LANGUAGE FlexibleInstances #-} module Test.Hspec.Internal (-  SpecTree (..)-, Spec (..)+  Spec (..) , Specs-, EvaluatedSpec , Example (..) , safeEvaluateExample , Result (..)@@ -16,37 +13,21 @@ where  import           Control.Exception-import qualified Test.Hspec.Pending as Pending +-- | A list of specs. type Specs = [Spec]-type EvaluatedSpec = SpecTree Result  -- | The result of running an example. data Result = Success | Pending (Maybe String) | Fail String   deriving (Eq, Show) -newtype Spec = Spec {unSpec :: SpecTree (IO Result)}---- IMPORTANT: Remove this warnings and remove -fno-warn-deprecations from the--- following modules/files when making SpecGroup abstract.------  * Spec.hs---  * Test.Hspec.Runner---  * Test.Hspec.Core----{-# WARNING SpecExample "This will be removed from the public interface with the next major release.  If you need this, raise your voice!" #-}-{-# WARNING SpecGroup "This will be removed from the public interface with the next major release.  If you need this, raise your voice!" #-}- -- | Internal representation of a spec.------ This will be made abstract with the next release.  If you still need access--- to any constructors, open an issue and describe your use case:--- <https://github.com/hspec/hspec/issues>-data SpecTree a = SpecGroup String [SpecTree a]-            | SpecExample String a+data Spec = SpecGroup String [Spec]+          | SpecExample String (IO Result) +-- | The @describe@ function combines a list of specs into a larger spec. describe :: String -> [Spec] -> Spec-describe str specs = Spec . SpecGroup str $ map unSpec specs+describe = SpecGroup  safeEvaluateExample :: IO Result -> IO Result safeEvaluateExample action = do@@ -70,7 +51,7 @@ -- >   ] -- it :: Example a => String -> a -> Spec-it requirement' = Spec . SpecExample requirement' . evaluateExample+it requirement = SpecExample requirement . evaluateExample  -- | A type class for examples. --@@ -88,13 +69,18 @@ instance Example Result where   evaluateExample r = r `seq` return r -instance Example Pending.Pending where-  evaluateExample (Pending.Pending reason) = evaluateExample (Pending reason)--instance Example (String -> Pending.Pending) where-  evaluateExample _ = evaluateExample (Pending.Pending Nothing)- -- | Create a more readable display of a quantity of something.-quantify :: (Show a, Num a, Eq a) => a -> String -> String+--+-- Examples:+--+-- >>> quantify 0 "example"+-- "0 examples"+--+-- >>> quantify 1 "example"+-- "1 example"+--+-- >>> quantify 2 "example"+-- "2 examples"+quantify :: Int -> String -> String quantify 1 s = "1 " ++ s quantify n s = show n ++ " " ++ s ++ "s"
Test/Hspec/Monadic.hs view
@@ -1,11 +1,17 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# OPTIONS_HADDOCK prune #-}+{-# OPTIONS_GHC -fno-warn-deprecations #-} -- |--- There is a monadic and a non-monadic API.  This is the documentation for the--- monadic API.  The monadic API is suitable for most use cases, and it is more--- stable than the non-monadic API.------ For documentation on the non-monadic API look at "Test.Hspec".+-- Hspec is a Behaviour-Driven Development tool for Haskell programmers. BDD is+-- an approach to software development that combines Test-Driven Development,+-- Domain Driven Design, and Acceptance Test-Driven Planning. Hspec helps you+-- do the TDD part of that equation, focusing on the documentation and design+-- aspects of TDD. --+-- Hspec (and the preceding intro) are based on the Ruby library RSpec. Much of+-- what applies to RSpec also applies to Hspec. Hspec ties together+-- /descriptions/ of behavior and /examples/ of that behavior. The examples can+-- also be run as tests and the output summarises what needs to be implemented. module Test.Hspec.Monadic ( -- * Introduction -- $intro@@ -23,22 +29,24 @@ -- * Running a spec , hspec , hspecB-, hspecX , hHspec+, Summary (..)  -- * Interface to the non-monadic API , runSpecM , fromSpecList --- * Deprecated types and functions-, descriptions+-- deprecated stuff , Specs+, descriptions+, hspecX ) where  import           System.IO-import           Test.Hspec.Core (EvaluatedSpec, Example)+import           Test.Hspec.Core (Example) import qualified Test.Hspec.Core as Core import qualified Test.Hspec.Runner as Runner+import           Test.Hspec.Runner (Summary (..)) import           Test.Hspec.Pending (Pending) import qualified Test.Hspec.Pending as Pending @@ -122,15 +130,16 @@ newtype SpecM a = SpecM (Writer [Core.Spec] a)   deriving Monad --- | Create a document of the given specs and write it to stdout.-hspec :: Spec -> IO [EvaluatedSpec]+-- | Create a document of the given spec and write it to stdout.+--+-- Exit the program with `exitSuccess` if all examples passed, with+-- `exitFailure` otherwise.+hspec :: Spec -> IO () hspec = Runner.hspec . runSpecM --- | Use in place of `hspec` to also exit the program with an @ExitCode@-hspecX :: Spec -> IO a-hspecX = Runner.hspecX . runSpecM---- | Use in place of hspec to also give a @Bool@ success indication+-- | Create a document of the given spec and write it to stdout.+--+-- Return `True` if all examples passed, `False` otherwise. hspecB :: Spec -> IO Bool hspecB = Runner.hspecB . runSpecM @@ -138,7 +147,7 @@ -- -- > writeReport filename specs = withFile filename WriteMode (\h -> hHspec h specs) ---hHspec :: Handle -> Spec -> IO [EvaluatedSpec]+hHspec :: Handle -> Spec -> IO Summary hHspec h = Runner.hHspec h . runSpecM  -- | Convert a monadic spec into a non-monadic spec.@@ -149,12 +158,21 @@ fromSpecList :: [Core.Spec] -> Spec fromSpecList = SpecM . tell +-- | The @describe@ function combines a list of specs into a larger spec. describe :: String -> Spec -> Spec describe label action = SpecM . tell $ [Core.describe label (runSpecM action)] +-- | An alias for `describe`. context :: String -> Spec -> Spec context = describe +-- |+-- Create a set of specifications for a specific type being described.  Once+-- you know what you want specs for, use this.+--+-- > describe "abs" $ do+-- >   it "returns a positive number given a negative number" $+-- >     abs (-1) == 1 it :: Example v => String -> v -> Spec it label action = (SpecM . tell) [Core.it label action] @@ -174,10 +192,13 @@ pending :: String  -> Pending pending = Pending.pending --- | DEPRECATED: Use `sequence_` instead.+{-# DEPRECATED Specs "use Spec instead" #-}+type Specs = SpecM ()++{-# DEPRECATED descriptions "use sequence_ instead" #-} descriptions :: [Spec] -> Spec descriptions = sequence_-{-# DEPRECATED descriptions "use sequence_ instead" #-} --- | DEPRECATED: Use `Spec` instead-type Specs = SpecM ()+{-# DEPRECATED hspecX "use hspec instead" #-}+hspecX :: Spec -> IO a+hspecX = Runner.hspecX . runSpecM
Test/Hspec/Pending.hs view
@@ -1,6 +1,20 @@+{-# LANGUAGE FlexibleInstances #-} module Test.Hspec.Pending where +import qualified Test.Hspec.Internal as Internal+import           Test.Hspec.Internal (Example(..))++-- NOTE: This is defined in a separate packages, because it clashes with+-- Result.Pending.++-- | A pending example. newtype Pending = Pending (Maybe String)++instance Example Pending where+  evaluateExample (Pending reason) = evaluateExample (Internal.Pending reason)++instance Example (String -> Pending) where+  evaluateExample _ = evaluateExample (Pending Nothing)  -- | A pending example. --
Test/Hspec/QuickCheck.hs view
@@ -36,9 +36,9 @@ instance Example QC.Property where   evaluateExample p = do     r <- silence $ QC.quickCheckResult p-    let r' = case r of-              QC.Success {}           -> Success-              f@(QC.Failure {})       -> Fail (QC.output f)-              g@(QC.GaveUp {})        -> Fail ("Gave up after " ++ quantify (QC.numTests g) "test" )-              QC.NoExpectedFailure {} -> Fail ("No expected failure")-    return r'+    return $+      case r of+        QC.Success {}               -> Success+        f@(QC.Failure {})           -> Fail (QC.output f)+        QC.GaveUp {QC.numTests = n} -> Fail ("Gave up after " ++ quantify n "test" )+        QC.NoExpectedFailure {}     -> Fail ("No expected failure")
Test/Hspec/Runner.hs view
@@ -1,11 +1,24 @@-{-# OPTIONS_GHC -fno-warn-deprecations #-} -- | This module contains the runners that take a set of specs, evaluate their examples, and -- report to a given handle. -- module Test.Hspec.Runner (-  Specs, hspec, hspecX, hspecB, hHspec, hHspecWithFormat, describe, it, toExitCode+  Specs+, hspec+, hspecB+, hHspec+, hHspecWithFormat+, toExitCode++, Summary (..)++-- * Deprecated functions+, hspecX ) where +import           Control.Monad (unless, (>=>))+import           Control.Applicative+import           Data.Monoid+ import           Test.Hspec.Internal import           Test.Hspec.Formatters import           Test.Hspec.Formatters.Internal@@ -13,13 +26,13 @@ import           System.Exit  -- | Evaluate and print the result of checking the spec examples.-runFormatter :: Formatter -> Spec -> FormatM EvaluatedSpec-runFormatter formatter = go 0 [] . unSpec+runFormatter :: Formatter -> Spec -> FormatM ()+runFormatter formatter = go 0 []   where+    go :: Int -> [String] -> Spec -> FormatM ()     go nesting groups (SpecGroup group xs) = do       exampleGroupStarted formatter nesting group-      ys <- mapM (go (succ nesting) (group : groups)) xs-      return (SpecGroup group ys)+      mapM_ (go (succ nesting) (group : groups)) xs     go nesting groups (SpecExample requirement e) = do       result <- liftIO $ safeEvaluateExample e       case result of@@ -34,7 +47,6 @@         Pending reason -> do           increasePendingCount           examplePending formatter nesting requirement reason-      return (SpecExample requirement result)  failureDetails :: [String] -> String -> String -> Int -> String failureDetails groups requirement err i =@@ -48,49 +60,54 @@       _   -> concatMap (++ " - ") (reverse groups)  --- | Use in place of `hspec` to also exit the program with an @ExitCode@+-- | Create a document of the given specs and write it to stdout.+--+-- Exit the program with `exitSuccess` if all examples passed, with+-- `exitFailure` otherwise.+hspec :: Specs -> IO ()+hspec = hspecB >=> (`unless` exitFailure)++{-# DEPRECATED hspecX "use hspec instead" #-} hspecX :: Specs -> IO a-hspecX ss = hspecB ss >>= exitWith . toExitCode+hspecX = hspecB >=> exitWith . toExitCode --- | Use in place of hspec to also give a @Bool@ success indication+-- | Create a document of the given specs and write it to stdout.+--+-- Return `True` if all examples passed, `False` otherwise. hspecB :: Specs -> IO Bool-hspecB ss = success `fmap` hspec ss+hspecB = fmap success . hHspec stdout   where-    success :: [EvaluatedSpec] -> Bool-    success = not . failure--    failure :: [EvaluatedSpec] -> Bool-    failure = any p-      where-        p (SpecGroup _ xs) = any p xs-        p (SpecExample _ x) = isFailure x--    isFailure :: Result -> Bool-    isFailure (Fail _) = True-    isFailure _        = False---- | Create a document of the given specs and write it to stdout.-hspec :: Specs -> IO [EvaluatedSpec]-hspec = hHspec stdout+    success :: Summary -> Bool+    success s = summaryFailures s == 0  -- | Create a document of the given specs and write it to the given handle. -- -- > writeReport filename specs = withFile filename WriteMode (\h -> hHspec h specs) ---hHspec :: Handle -> Specs -> IO [EvaluatedSpec]+hHspec :: Handle -> Specs -> IO Summary hHspec h specs = do   useColor <- hIsTerminalDevice h   hHspecWithFormat specdoc useColor h specs  -- | Create a document of the given specs and write it to the given handle. -- THIS IS LIKELY TO CHANGE-hHspecWithFormat :: Formatter -> Bool -> Handle -> Specs -> IO [EvaluatedSpec]+hHspecWithFormat :: Formatter -> Bool -> Handle -> Specs -> IO Summary hHspecWithFormat formatter useColor h ss = runFormatM useColor h $ do-  specList <- mapM (runFormatter formatter) ss+  mapM_ (runFormatter formatter) ss   failedFormatter formatter   footerFormatter formatter-  return specList+  Summary <$> getTotalCount <*> getFailCount  toExitCode :: Bool -> ExitCode toExitCode True  = ExitSuccess toExitCode False = ExitFailure 1++-- | Summary of a test run.+data Summary = Summary {+  summaryExamples :: Int+, summaryFailures :: Int+} deriving (Eq, Show)++instance Monoid Summary where+  mempty = Summary 0 0+  (Summary x1 x2) `mappend` (Summary y1 y2) = Summary (x1 + y1) (x2 + y2)
+ example/NonMonadic.hs view
@@ -0,0 +1,23 @@+module Main (main, spec) where++import Test.Hspec.Core+import Test.Hspec.HUnit ()+import Test.Hspec.QuickCheck+import Test.HUnit++shouldBe :: (Show a, Eq a) => a -> a -> Assertion+actual `shouldBe` expected = actual @?= expected++main :: IO ()+main = hspec spec++spec :: Specs+spec = [+    describe "reverse" [+      it "reverses a list" $ do+        reverse [1 :: Int, 2, 3] `shouldBe` [3, 2, 1]++    , it "gives the original list, if applied twice" $ property $+        \(xs) -> reverse (reverse xs) == (xs :: [Int])+    ]+  ]
+ example/Spec.hs view
@@ -0,0 +1,21 @@+module Main (main, spec) where++import Test.Hspec.Monadic+import Test.Hspec.HUnit ()+import Test.Hspec.QuickCheck+import Test.HUnit++shouldBe :: (Show a, Eq a) => a -> a -> Assertion+actual `shouldBe` expected = actual @?= expected++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "reverse" $ do+    it "reverses a list" $ do+      reverse [1 :: Int, 2, 3] `shouldBe` [3, 2, 1]++    it "gives the original list, if applied twice" $ property $+      \xs -> reverse (reverse xs) == (xs :: [Int])
hspec.cabal view
@@ -1,26 +1,26 @@-name:           hspec-version:        1.1.3-cabal-version:  >= 1.8-build-type:     Simple-license:        BSD3-license-file:   LICENSE-copyright:      (c) 2011 Trystan Spangler-category:       Testing-author:         Trystan Spangler-maintainer:     trystan.s@comcast.net-stability:      experimental-bug-reports:    https://github.com/hspec/hspec/issues-homepage:       http://hspec.github.com/-synopsis:       Behavior Driven Development for Haskell-description:    Behavior Driven Development for Haskell-                .-                Hspec is roughly based on the Ruby library RSpec. However,-                Hspec is just a framework for running HUnit and QuickCheck-                tests. Compared to other options, it provides a much nicer-                syntax that makes tests very easy to read.-                .-                New to Hspec?  Start with the introductory documentation:-                <http://hspec.github.com/>+name:             hspec+version:          1.2.0+license:          BSD3+license-file:     LICENSE+copyright:        (c) 2011 Trystan Spangler+author:           Trystan Spangler+maintainer:       trystan.s@comcast.net+build-type:       Simple+cabal-version:    >= 1.8+category:         Testing+stability:        experimental+bug-reports:      https://github.com/hspec/hspec/issues+homepage:         http://hspec.github.com/+synopsis:         Behavior Driven Development for Haskell+description:      Behavior Driven Development for Haskell+                  .+                  Hspec is roughly based on the Ruby library RSpec. However,+                  Hspec is just a framework for running HUnit and QuickCheck+                  tests. Compared to other options, it provides a much nicer+                  syntax that makes tests very easy to read.+                  .+                  Start with the introductory documentation:+                  <http://hspec.github.com/>  source-repository head   type: git@@ -71,21 +71,45 @@     , HUnit >= 1 && <= 2     , QuickCheck >= 2.4.0.1 && <= 2.5     , hspec-shouldbe+    , hspec-discover --- this should be merged with spec-test-suite old-spec+test-suite doctests+  main-is:+      doctests.hs   type:       exitcode-stdio-1.0+  ghc-options:+      -Wall -Werror -threaded+  hs-source-dirs:+      test+  build-depends:+      base+    , doctest >= 0.7++test-suite example+  type:+      exitcode-stdio-1.0   main-is:-      Specs.hs+      Spec.hs+  hs-source-dirs:+      example   ghc-options:       -Wall -Werror   build-depends:-      base >= 4 && <= 5-    , silently >= 1.1.1 && < 2-    , ansi-terminal == 0.5.5-    , time < 1.5-    , transformers >= 0.2.0 && < 0.4.0-    , HUnit >= 1 && <= 2-    , QuickCheck >= 2.4.0.1 && <= 2.5-    , hspec-shouldbe+      base+    , hspec+    , HUnit++test-suite example-non-monadic+  type:+      exitcode-stdio-1.0+  main-is:+      NonMonadic.hs+  hs-source-dirs:+      example+  ghc-options:+      -Wall -Werror+  build-depends:+      base+    , hspec+    , HUnit
test/Spec.hs view
@@ -1,9 +1,1 @@-module Main (main) where--import           Test.Hspec.ShouldBe--import qualified Test.Hspec.MonadicSpec--main :: IO ()-main = hspecX $ do-  describe "Test.Hspec.Monadic" Test.Hspec.MonadicSpec.spec+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ test/doctests.hs view
@@ -0,0 +1,6 @@+module Main where++import           Test.DocTest++main :: IO ()+main = doctest ["Test/Hspec/Internal.hs"]