module Test.Hspec (
Spec
, Example
, module Test.Hspec.Expectations
, describe
, context
, it
, specify
, example
, pending
, pendingWith
, before
, beforeAll
, after
, afterAll
, around
, parallel
, runIO
, hspec
) where
import Control.Exception (finally)
import Control.Concurrent.MVar
import Test.Hspec.Core.Type hiding (describe, it)
import Test.Hspec.Runner
import Test.Hspec.HUnit ()
import Test.Hspec.Expectations
import qualified Test.Hspec.Core as Core
describe :: String -> Spec -> Spec
describe label spec = runIO (runSpecM spec) >>= fromSpecList . return . Core.describe label
context :: String -> Spec -> Spec
context = describe
it :: Example a => String -> a -> Spec
it label action = fromSpecList [Core.it label action]
specify :: Example a => String -> a -> Spec
specify = it
example :: Expectation -> Expectation
example = id
parallel :: Spec -> Spec
parallel = mapSpecItem $ \item -> item {itemIsParallelizable = True}
before :: IO () -> Spec -> Spec
before action = around (action >>)
beforeAll :: IO () -> Spec -> Spec
beforeAll action spec = do
mvar <- runIO (newMVar Nothing)
let action_ = memoize mvar action
before action_ spec
memoize :: MVar (Maybe a) -> IO a -> IO a
memoize mvar action = modifyMVar mvar $ \ma -> case ma of
Just a -> return (ma, a)
Nothing -> do
a <- action
return (Just a, a)
after :: IO () -> Spec -> Spec
after action = around (`finally` action)
afterAll :: IO () -> Spec -> Spec
afterAll action spec = runIO (runSpecM spec) >>= fromSpecList . return . SpecWithCleanup action
around :: (IO () -> IO ()) -> Spec -> Spec
around a2 = mapSpecItem $ \item -> item {itemExample = \params a1 -> itemExample item params (a1 . a2)}