packages feed

hspec 1.2.0.1 → 1.3.0

raw patch · 11 files changed

+283/−184 lines, 11 filesdep +directorydep +filepathdep +hspec-expectationsdep −hspec-discoverdep −hspec-shouldbedep ~QuickChecknew-component:exe:hspec-discoverPVP ok

version bump matches the API change (PVP)

Dependencies added: directory, filepath, hspec-expectations, hspec-meta

Dependencies removed: hspec-discover, hspec-shouldbe

Dependency ranges changed: QuickCheck

API changes (from Hackage documentation)

- Test.Hspec: Summary :: Int -> Int -> Summary
- Test.Hspec: data Spec
- Test.Hspec: data Summary
- Test.Hspec: hHspec :: Handle -> Specs -> IO Summary
- Test.Hspec: hspecB :: Specs -> IO Bool
- Test.Hspec: summaryExamples :: Summary -> Int
- Test.Hspec: summaryFailures :: Summary -> Int
- Test.Hspec: type Specs = [Spec]
+ Test.Hspec: context :: String -> Spec -> Spec
- Test.Hspec: describe :: String -> [Spec] -> Spec
+ Test.Hspec: describe :: String -> Spec -> Spec
- Test.Hspec: hspec :: Specs -> IO ()
+ Test.Hspec: hspec :: Spec -> IO ()
- Test.Hspec: it :: Example a => String -> a -> Spec
+ Test.Hspec: it :: Example v => String -> v -> Spec

Files

+ hspec-discover/example/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ hspec-discover/integration-test/empty/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+ hspec-discover/src/Main.hs view
@@ -0,0 +1,8 @@+module Main (main) where++import           System.Environment++import           Run (run)++main :: IO ()+main = getArgs >>= run
+ hspec-discover/src/Run.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- | A preprocessor that finds and combines specs.+module Run where+import           Control.Monad+import           Control.Applicative+import           Data.List+import           Data.String+import           Data.Function+import           System.Environment+import           System.Exit+import           System.IO+import           System.Directory+import           System.FilePath hiding (combine)++instance IsString ShowS where+  fromString = showString++run :: [String] -> IO ()+run args_ = case args_ of+  src : _ : dst : args -> do+    nested <- case args of+      []           -> return False+      ["--nested"] -> return True+      _            -> exit+    specs <- findSpecs src+    writeFile dst (mkSpecModule src nested specs)+  _ -> exit+  where+    exit = do+      name <- getProgName+      hPutStrLn stderr ("usage: " ++ name ++ " SRC CUR DST [--nested]")+      exitFailure++mkSpecModule :: FilePath -> Bool -> [SpecNode] -> String+mkSpecModule src nested nodes =+  ( "{-# LINE 1 " . shows src . " #-}"+  . showString "module Main where\n"+  . showString "import Test.Hspec\n"+  . importList nodes+  . showString "main :: IO ()\n"+  . showString "main = hspec $ "+  . format nodes+  ) "\n"+  where+    format+      | nested    = formatSpecsNested+      | otherwise = formatSpecs++-- | Generate imports for a list of specs.+importList :: [SpecNode] -> ShowS+importList = go ""+  where+    go :: ShowS -> [SpecNode] -> ShowS+    go current = foldr (.) "" . map (f current)+    f current (SpecNode name inhabited children) = this . go (current . showString name . ".") children+      where+        this+          | inhabited = "import qualified " . current . showString name . "Spec\n"+          | otherwise = id++-- | Combine a list of strings with (>>).+sequenceS :: [ShowS] -> ShowS+sequenceS = foldr (.) "" . intersperse " >> "++-- | Convert a list of specs to code.+formatSpecs :: [SpecNode] -> ShowS+formatSpecs xs+  | null xs   = "return ()"+  | otherwise = sequenceS (map formatSpec xs)++-- | Convert a spec to code.+formatSpec :: SpecNode -> ShowS+formatSpec = sequenceS . go ""+  where+    go :: String -> SpecNode -> [ShowS]+    go current (SpecNode name inhabited children) = addThis $ concatMap (go (current ++ name ++ ".")) children+      where+        addThis :: [ShowS] -> [ShowS]+        addThis+          | inhabited = ("describe " . shows (current ++ name) . " " . showString (current ++ name ++ "Spec.spec") :)+          | otherwise = id++-- | Convert a list of specs to code.+--+-- Hierarchical modules are mapped to nested specs.+formatSpecsNested :: [SpecNode] -> ShowS+formatSpecsNested xs+  | null xs   = "return ()"+  | otherwise = sequenceS (map formatSpecNested xs)++-- | Convert a spec to code.+--+-- Hierarchical modules are mapped to nested specs.+formatSpecNested :: SpecNode -> ShowS+formatSpecNested = go ""+  where+    go current (SpecNode name inhabited children) = "describe " . shows name . " (" . specs . ")"+      where+        specs :: ShowS+        specs = (sequenceS . addThis . map (go (current . showString name . "."))) children+        addThis+          | inhabited = ((current . showString name . "Spec.spec") :)+          | otherwise = id++data SpecNode = SpecNode String Bool [SpecNode]+  deriving (Eq, Show)++specNodeName :: SpecNode -> String+specNodeName (SpecNode name _ _) = name++specNodeInhabited :: SpecNode -> Bool+specNodeInhabited (SpecNode _ inhabited _) = inhabited++specNodeChildren :: SpecNode -> [SpecNode]+specNodeChildren (SpecNode _ _ children) = children++getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])+getFilesAndDirectories dir = do+  c <- filter (`notElem` ["..", "."]) <$> getDirectoryContents dir+  dirs <- filterM (doesDirectoryExist . (dir </>)) c+  files <- filterM (doesFileExist . (dir </>)) c+  return (dirs, files)++-- | Find specs relative to given source file.+--+-- The source file itself is not considered.+findSpecs :: FilePath -> IO [SpecNode]+findSpecs src = do+  let (dir, file) = splitFileName src+  (dirs, files) <- getFilesAndDirectories dir+  go dir (dirs, filter (/= file) files)+  where+    go :: FilePath -> ([FilePath], [FilePath]) -> IO [SpecNode]+    go base (dirs, files) = do+      nestedSpecs <- forM dirs $ \d -> do+        let dir = base </> d+        SpecNode d False <$> (getFilesAndDirectories dir >>= go dir)+      (return . filterSpecs . combineSpecs) (specsFromFiles files ++ nestedSpecs)+      where+        specsFromFiles = map (\x -> SpecNode (stripSuffix x) True []) . filter (isSuffixOf suffix)+          where+            suffix = "Spec.hs"+            stripSuffix = reverse . drop (length suffix) . reverse++        -- remove empty leafs+        filterSpecs :: [SpecNode] -> [SpecNode]+        filterSpecs = filter (\x -> specNodeInhabited x || (not . null . specNodeChildren) x)++        -- sort specs, and merge nodes with the same name+        combineSpecs :: [SpecNode] -> [SpecNode]+        combineSpecs = foldr f [] . sortBy (compare `on` specNodeName)+          where+            f x@(SpecNode n1 _ _) (y@(SpecNode n2 _ _):acc) | n1 == n2 = x `combine` y : acc+            f x acc = x : acc++            x `combine` y = SpecNode name inhabited children+              where+                name      = specNodeName x+                inhabited = specNodeInhabited x || specNodeInhabited y+                children  = specNodeChildren x ++ specNodeChildren y
+ hspec-discover/test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-meta-discover #-}
hspec.cabal view
@@ -1,10 +1,9 @@ name:             hspec-version:          1.2.0.1+version:          1.3.0 license:          BSD3 license-file:     LICENSE-copyright:        (c) 2011 Trystan Spangler-author:           Trystan Spangler-maintainer:       trystan.s@comcast.net+copyright:        (c) 2011-2012 Trystan Spangler, (c) 2011-2012 Simon Hengel, (c) 2011 Greg Weber+maintainer:       Simon Hengel <sol@typeful.net> build-type:       Simple cabal-version:    >= 1.8 category:         Testing@@ -39,14 +38,15 @@     , transformers >= 0.2.0 && < 0.4.0     , HUnit >= 1 && <= 2     , QuickCheck >= 2.4.0.1 && <= 2.5+    , hspec-expectations   exposed-modules:       Test.Hspec-    , Test.Hspec.Core-    , Test.Hspec.Monadic-    , Test.Hspec.Runner-    , Test.Hspec.Formatters-    , Test.Hspec.HUnit-    , Test.Hspec.QuickCheck+      Test.Hspec.Core+      Test.Hspec.Monadic+      Test.Hspec.Runner+      Test.Hspec.Formatters+      Test.Hspec.HUnit+      Test.Hspec.QuickCheck   other-modules:       Test.Hspec.Pending       Test.Hspec.Internal@@ -69,8 +69,8 @@     , transformers >= 0.2.0 && < 0.4.0     , HUnit >= 1 && <= 2     , QuickCheck >= 2.4.0.1 && <= 2.5-    , hspec-shouldbe-    , hspec-discover+    , hspec-expectations+    , hspec-meta  test-suite doctests   main-is:@@ -112,3 +112,61 @@       base     , hspec     , HUnit++-- hspec-discover+executable hspec-discover+  ghc-options:+      -Wall+  hs-source-dirs:+      hspec-discover/src+  main-is:+      Main.hs+  other-modules:+      Run+  build-depends:+      base >= 4 && <= 5+    , filepath+    , directory++test-suite hspec-discover-spec+  type:+      exitcode-stdio-1.0+  ghc-options:+      -Wall -Werror+  hs-source-dirs:+      hspec-discover/src+    , hspec-discover/test+  main-is:+      Spec.hs+  build-depends:+      base >= 4 && <= 5+    , filepath+    , directory+    , hspec-meta++test-suite hspec-discover-example+  type:+      exitcode-stdio-1.0+  ghc-options:+      -Wall -Werror+  hs-source-dirs:+      hspec-discover/example+  main-is:+      Spec.hs+  build-depends:+      base >= 4 && <= 5+    , hspec+    , QuickCheck++test-suite hspec-discover-integration-test-empty+  type:+      exitcode-stdio-1.0+  ghc-options:+      -Wall -Werror+  hs-source-dirs:+      hspec-discover/integration-test/empty+  main-is:+      Spec.hs+  build-depends:+      base >= 4 && <= 5+    , hspec
src/Test/Hspec.hs view
@@ -1,59 +1,42 @@ {-# 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,--- 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 is a framework for /Behavior-Driven Development (BDD)/ in Haskell. 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 {-# WARNING "This module will re-export Test.Hspec.Monadic in the future.  Either use Test.Hspec.Core as a drop-in replacement, or migrate your code to the monadic API!" #-} (+-- also be run as tests and the output summarizes what needs to be implemented.+module Test.Hspec (  -- * Introduction -- $intro  -- * Types   Spec-, Specs , Example , Pending +-- * Setting expectations+, module Test.Hspec.Expectations+ -- * Defining a spec , describe+, context , it , pending  -- * Running a spec , hspec-, hspecB-, hHspec-, Summary (..)-------- deprecated functions-, descriptions-, hspecX--- ) where -import           Test.Hspec.Core---+import           Test.Hspec.Monadic+import           Test.Hspec.HUnit ()+import           Test.Hspec.QuickCheck ()+import           Test.Hspec.Expectations  -- $intro --@@ -62,12 +45,11 @@ -- the specs for them. -- -- > import Test.Hspec--- > import Test.Hspec.QuickCheck--- > import Test.Hspec.HUnit () -- > import Test.QuickCheck -- > import Test.HUnit -- >--- > main = hspec mySpecs+-- > main :: IO ()+-- > main = hspec spec -- -- 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@@ -75,53 +57,42 @@ -- and there is no undocumented behavior. -- -- > unformatPhoneNumber :: String -> String--- > unformatPhoneNumber number = undefined+-- > unformatPhoneNumber = undefined -- > -- > formatPhoneNumber :: String -> String--- > formatPhoneNumber number = undefined+-- > formatPhoneNumber = undefined -- -- The 'describe' function takes a list of behaviors and examples bound -- together with the 'it' function ----- > mySpecs = [describe "unformatPhoneNumber" [+-- > spec :: Spec+-- > spec = do+-- >   describe "unformatPhoneNumber" $ do ----- A boolean expression can act as a behavior's example.+-- A `Bool` can be used as an example. ----- >   it "removes dashes, spaces, and parenthesies" $--- >     unformatPhoneNumber "(555) 555-1234" == "5555551234"--- >   ,+-- >     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"--- >   ,+-- >     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")+-- An HUnit 'Test.HUnit.Lang.Assertion' can be used as an example. ----- >   it "removes the \"ext\" prefix of the extension" $ TestCase $ do--- >     let expected = "5555551234135"--- >         actual   = unformatPhoneNumber "(555) 555-1234 ext 135"--- >     expected @?= actual--- >   ,+-- >     it "converts letters to numbers" $ do+-- >       let expected = "6862377"+-- >           actual   = unformatPhoneNumber "NUMBERS"+-- >       actual @?= expected ----- 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")+-- A QuickCheck 'Test.QuickCheck.Property' can be used as an example. ----- >   it "can add and remove formatting without changing the number" $ property $--- >     forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n--- >   ]]+-- >     it "can add and remove formatting without changing the number" $ property $+-- >       forAll phoneNumber $ \n -> unformatPhoneNumber (formatPhoneNumber n) == n -- > -- > phoneNumber :: Gen String -- > phoneNumber = do
src/Test/Hspec/Core.hs view
@@ -1,21 +1,9 @@ {-# 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,--- 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".-+-- "Test.Hspec". module Test.Hspec.Core (  @@ -68,7 +56,8 @@ -- > import Test.QuickCheck -- > import Test.HUnit -- >--- > main = hspec mySpecs+-- > main :: IO ()+-- > main = hspec spec -- -- 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@@ -84,7 +73,7 @@ -- The 'describe' function takes a list of behaviors and examples bound -- together with the 'it' function ----- > mySpecs = [describe "unformatPhoneNumber" [+-- > spec = [describe "unformatPhoneNumber" [ -- -- A boolean expression can act as a behavior's example. --
src/Test/Hspec/Internal.hs view
@@ -54,12 +54,6 @@ it requirement = SpecExample requirement . evaluateExample  -- | A type class for examples.------ To use an HUnit `Test.HUnit.Test` or an `Test.HUnit.Assertion` as an example--- you need to import "Test.Hspec.HUnit".------ To use a QuickCheck `Test.QuickCheck.Property` as an example you need to--- import "Test.Hspec.QuickCheck". class Example a where   evaluateExample :: a -> IO Result 
src/Test/Hspec/Monadic.hs view
@@ -1,20 +1,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# OPTIONS_HADDOCK prune #-} {-# OPTIONS_GHC -fno-warn-deprecations #-}--- |--- 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 -- * Types   Spec , Example@@ -52,78 +39,6 @@  import           Control.Monad.Trans.Writer (Writer, execWriter, tell) --- $intro------ The three functions you'll use the most are 'hspec', 'describe', and 'it'.--- Here is an example of functions that format and unformat phone numbers and--- the specs for them.------ > import Test.Hspec.Monadic--- > import Test.Hspec.QuickCheck--- > import Test.Hspec.HUnit ()--- > import Test.QuickCheck--- > import Test.HUnit--- >--- > main = hspec 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" $ do------ 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")---  type Spec = SpecM () 
test/Spec.hs view
@@ -1,1 +1,1 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+{-# OPTIONS_GHC -F -pgmF hspec-meta-discover #-}