-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Behavior Driven Development for Haskell -- -- Behavior Driven Development for Haskell -- -- Hspec is based on the Ruby library RSpec - so much of what applies to -- RSpec also applies to Hspec. Hspec ties together descriptions -- of behavior and examples of that behavior. The examples can -- then be run as tests and the output summarises what needs to be -- implemented. @package hspec @version 0.4.3 -- | This module contains the core types, constructors, classes, instances, -- and utility functions common to hspec. module Test.Hspec.Core -- | The result of running an example. data Result Success :: Result Fail :: String -> Result Pending :: String -> Result -- | Everything needed to specify and show a specific behavior. data Spec Spec :: String -> String -> Result -> Spec -- | What is being tested, usually the name of a type. name :: Spec -> String -- | The specific behavior being tested. requirement :: Spec -> String -- | The status of this behavior. result :: Spec -> Result data Formatter Formatter :: (Handle -> Spec -> IO ()) -> (Handle -> Spec -> [String] -> IO ()) -> (Handle -> Spec -> [String] -> IO ()) -> (Handle -> Spec -> [String] -> IO ()) -> (Handle -> [String] -> IO ()) -> (Handle -> [Spec] -> Double -> IO ()) -> Formatter exampleGroupStarted :: Formatter -> Handle -> Spec -> IO () examplePassed :: Formatter -> Handle -> Spec -> [String] -> IO () exampleFailed :: Formatter -> Handle -> Spec -> [String] -> IO () examplePending :: Formatter -> Handle -> Spec -> [String] -> IO () errorsFormatter :: Formatter -> Handle -> [String] -> IO () footerFormatter :: Formatter -> Handle -> [Spec] -> Double -> IO () -- | Create a set of specifications for a specific type being described. -- Once you know what you want specs for, use this. -- --
-- describe "abs" [ -- it "returns a positive number given a negative number" -- (abs (-1) == 1) -- ] --describe :: String -> [IO (String, Result)] -> IO [IO Spec] -- | Combine a list of descriptions. descriptions :: [IO [IO Spec]] -> IO [IO Spec] -- | Evaluate a Result. Any exceptions (undefined, etc.) are treated as -- failures. safely :: Result -> IO Result -- | Anything that can be used as an example of a behavior. class SpecVerifier a it :: SpecVerifier a => String -> a -> IO (String, Result) -- | Declare an example as not successful or failing but pending some other -- work. If you want to report on a behavior but don't have an example -- yet, use this. -- --
-- describe "fancyFormatter" [ -- it "can format text in a way that everyone likes" -- (pending "waiting for clarification from the designers") -- ] --pending :: String -> Result failedCount :: [Spec] -> Int isFailure :: Result -> Bool -- | Create a more readable display of a quantity of something. quantify :: Num a => a -> String -> String instance Eq Result instance SpecVerifier Result instance SpecVerifier Bool -- | Importing this module allows you to use an HUnit test case as -- an example for a behavior. You can use an explicit TestCase -- data constructor or use an IO() action. For an IO() -- action, any exception means the example failed; otherwise, it's -- successfull. -- --
-- describe "cutTheDeck" [ -- it "puts the first half of a list after the last half" -- (TestCase $ assertEqual "cut the deck" [3,4,1,2] (cutTheDeck [1,2,3,4])), -- -- it "restores an even sized list when cut twice" -- (assertEqual "cut the deck twice" [3,4,1,2] (cutTheDeck (cutTheDeck [1,2,3,4]))), -- ] --module Test.Hspec.HUnit instance SpecVerifier Test instance SpecVerifier (IO ()) -- | This module contains formaatters that take a set of specs and write to -- a given handle. They follow a structure similar to RSpec formatters. module Test.Hspec.Formatters specdoc :: Bool -> Formatter -- | This module contains the runners that take a set of specs, evaluate -- their examples, and report to a given handle. module Test.Hspec.Runner type Specs = [IO Spec] -- | Create a document of the given specs and write it to stdout. hspec :: IO Specs -> IO [Spec] -- | 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 -> IO Specs -> IO [Spec] -- | Create a document of the given specs and write it to the given handle. -- THIS IS LIKELY TO CHANGE hHspecWithFormat :: Formatter -> Handle -> IO Specs -> IO [Spec] -- | Create a set of specifications for a specific type being described. -- Once you know what you want specs for, use this. -- --
-- describe "abs" [ -- it "returns a positive number given a negative number" -- (abs (-1) == 1) -- ] --describe :: String -> [IO (String, Result)] -> IO [IO Spec] -- | Create a description and example of a behavior, a list of these is -- used by describe. Once you know what you want to specify, use -- this. -- --
-- describe "closeEnough" [ -- it "is true if two numbers are almost the same" -- (1.001 `closeEnough` 1.002), -- -- it "is false if two numbers are not almost the same" -- (not $ 1.001 `closeEnough` 1.003) -- ] --it :: SpecVerifier a => String -> a -> IO (String, Result) -- | This module contains the runners that take a set of specs, specified -- in a monadic style, evaluate their examples, and report to a given -- handle. -- -- 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 -- import Test.Hspec.QuickCheck -- import Test.Hspec.HUnit -- import Test.QuickCheck hiding (property) -- 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 can act as a behavior's example. (must import -- Test.Hspec.HUnit) -- --
-- it "removes the \"ext\" prefix of the extension" -- (TestCase $ let expected = "5555551234135" -- actual = unformatPhoneNumber "(555) 555-1234 ext 135" -- in assertEqual "remove extension" 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" -- let actual = unformatPhoneNumber "NUMBERS" -- assertEqual "letters to numbers" expected actual) ---- -- The property function allows a QuickCheck property to act as an -- example. (must import Test.Hspec.HUnit) -- --
-- it "can add and remove formatting without changing the number" -- (property $ forAll phoneNumber $ -- \ n -> unformatPhoneNumber (formatPhoneNumber n) == n) -- -- phoneNumber :: Gen String -- phoneNumber = do -- nums <- elements [7,10,11,12,13,14,15] -- vectorOf nums (elements "0123456789") --module Test.Hspec.Monadic -- | Everything needed to specify and show a specific behavior. data Spec -- | The result of running an example. data Result type Specs = Writer [IO [IO Spec]] () describe :: String -> Writer [ItSpec] () -> Specs it :: SpecVerifier v => String -> v -> Writer [ItSpec] () -- | Create a document of the given specs and write it to stdout. hspec :: Specs -> IO [Spec] -- | Declare an example as not successful or failing but pending some other -- work. If you want to report on a behavior but don't have an example -- yet, use this. -- --
-- describe "fancyFormatter" [ -- it "can format text in a way that everyone likes" -- (pending "waiting for clarification from the designers") -- ] --pending :: String -> Result -- | Combine a list of descriptions. descriptions :: [IO [IO Spec]] -> IO [IO Spec] -- | 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 [Spec] -- | Importing this module allows you to use a QuickCheck property as an -- example for a behavior. Use the property function to indicate a -- QuickCkeck property. -- --
-- describe "cutTheDeck" [ -- it "puts the first half of a list after the last half" -- (property $ \ xs -> let top = take (length xs `div` 2) xs -- bot = drop (length xs `div` 2) xs -- in cutTheDeck xs == bot ++ top), -- -- it "restores an even sized list when cut twice" -- (property $ \ xs -> even (length xs) ==> cutTheDeck (cutTheDeck xs) == xs) -- ] --module Test.Hspec.QuickCheck property :: Testable a => a -> QuickCheckProperty a instance Testable t => SpecVerifier (QuickCheckProperty t) -- | 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. -- -- 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 -- import Test.Hspec.QuickCheck -- import Test.Hspec.HUnit -- import Test.QuickCheck hiding (property) -- 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" [ ---- -- 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 can act as a behavior's example. (must import -- Test.Hspec.HUnit) -- --
-- it "removes the \"ext\" prefix of the extension" -- (TestCase $ let expected = "5555551234135" -- actual = unformatPhoneNumber "(555) 555-1234 ext 135" -- in assertEqual "remove extension" 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" -- let actual = unformatPhoneNumber "NUMBERS" -- assertEqual "letters to numbers" expected actual), ---- -- The property function allows a QuickCheck property to act as an -- example. (must import Test.Hspec.HUnit) -- --
-- it "can add and remove formatting without changing the number" -- (property $ forAll phoneNumber $ -- \ n -> unformatPhoneNumber (formatPhoneNumber n) == n) -- ] -- -- phoneNumber :: Gen String -- phoneNumber = do -- nums <- elements [7,10,11,12,13,14,15] -- vectorOf nums (elements "0123456789") --module Test.Hspec -- | Everything needed to specify and show a specific behavior. data Spec -- | The result of running an example. data Result type Specs = [IO Spec] -- | Create a set of specifications for a specific type being described. -- Once you know what you want specs for, use this. -- --
-- describe "abs" [ -- it "returns a positive number given a negative number" -- (abs (-1) == 1) -- ] --describe :: String -> [IO (String, Result)] -> IO [IO Spec] -- | Create a description and example of a behavior, a list of these is -- used by describe. Once you know what you want to specify, use -- this. -- --
-- describe "closeEnough" [ -- it "is true if two numbers are almost the same" -- (1.001 `closeEnough` 1.002), -- -- it "is false if two numbers are not almost the same" -- (not $ 1.001 `closeEnough` 1.003) -- ] --it :: SpecVerifier a => String -> a -> IO (String, Result) -- | Create a document of the given specs and write it to stdout. hspec :: IO Specs -> IO [Spec] -- | Declare an example as not successful or failing but pending some other -- work. If you want to report on a behavior but don't have an example -- yet, use this. -- --
-- describe "fancyFormatter" [ -- it "can format text in a way that everyone likes" -- (pending "waiting for clarification from the designers") -- ] --pending :: String -> Result -- | Combine a list of descriptions. descriptions :: [IO [IO Spec]] -> IO [IO Spec] -- | 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 -> IO Specs -> IO [Spec]