hspec2 0.3.3 → 0.3.4
raw patch · 4 files changed
+30/−87 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- hspec2.cabal +1/−2
- src/Test/Hspec.hs +12/−4
- src/Test/Hspec/Memoize.hs +0/−79
- test/Test/HspecSpec.hs +17/−2
hspec2.cabal view
@@ -1,5 +1,5 @@ name: hspec2-version: 0.3.3+version: 0.3.4 license: MIT license-file: LICENSE copyright: (c) 2011-2014 Simon Hengel,@@ -59,7 +59,6 @@ Test.Hspec.QuickCheck other-modules: Test.Hspec.Util- Test.Hspec.Memoize Test.Hspec.Compat Test.Hspec.Core.Type Test.Hspec.Core.QuickCheckUtil
src/Test/Hspec.hs view
@@ -39,15 +39,14 @@ , hspec ) where -import Control.Applicative 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-import Test.Hspec.Memoize -- | Combine a list of specs into a larger spec. describe :: String -> SpecWith a -> SpecWith a@@ -103,15 +102,24 @@ beforeAll action = fromSpecList . return . BuildSpecs . go where go spec = do- action_ <- ioMemo action+ mvar <- newMVar Nothing+ let action_ = memoize mvar action return . runSpecM $ 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)+ -- | Run a custom action before all spec items. beforeAllWith :: (b -> IO a) -> SpecWith a -> SpecWith b beforeAllWith action = fromSpecList . return . BuildSpecs . go where go spec = do- action_ <- (. action) <$> newIOMemoizer+ mvar <- newMVar Nothing+ let action_ = memoize mvar . action return . runSpecM $ aroundWith (\e x -> action_ x >>= e) spec -- | Run a custom action after every spec item.
− src/Test/Hspec/Memoize.hs
@@ -1,79 +0,0 @@--- Copyright (c) 2012, Dan Burton------ All rights reserved.------ Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:------ * Redistributions of source code must retain the above copyright--- notice, this list of conditions and the following disclaimer.------ * Redistributions in binary form must reproduce the above--- copyright notice, this list of conditions and the following--- disclaimer in the documentation and/or other materials provided--- with the distribution.------ * Neither the name of Dan Burton nor the names of other--- contributors may be used to endorse or promote products derived--- from this software without specific prior written permission.------ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS--- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT--- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR--- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT--- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,--- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT--- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,--- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY--- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT--- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE--- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.-module Test.Hspec.Memoize (ioMemo, newIOMemoizer) where--import Control.Concurrent.MVar-import Data.IORef---- | Memoize an IO action.--- The action will be performed--- the first time that it its value is demanded;--- all subsequent invocations--- will simply recall the value acquired--- from the first call.--- If the value is never demanded,--- then the action will never be performed.------ This is basically a safe version of--- 'System.IO.Unsafe.unsafeInterleaveIO'.--- This function is also thread-safe:--- it is guaranteed that the action passed in--- will be performed exactly 0 or 1 times--- by this code. Exceptions will be propagated--- to the caller.------ Example usage:------ >>> getLine' <- ioMemo getLine------ >>> replicateM 3 getLine'--- Hello--- ["Hello", "Hello", "Hello"]-ioMemo :: IO a -> IO (IO a)-ioMemo action = do- memo <- newIOMemoizer- return (memo action)--newIOMemoizer :: IO (IO a -> IO a)-newIOMemoizer = do- b <- newMVar True- r <- newIORef undefined- return (ioMemoizer b r)--ioMemoizer :: MVar Bool -> IORef a -> IO a -> IO a-ioMemoizer b r action = do- modifyMVar_ b $ \isEmpty ->- if isEmpty- then do v <- action- writeIORef r v- return False- else return False- readIORef r
test/Test/HspecSpec.hs view
@@ -141,13 +141,13 @@ it "runs an action before the first spec item" $ do ref <- newIORef ([] :: [String]) let append n = modifyIORef ref (++ return n)- silence $ H.hspec $ H.beforeAll (append "before") $ do+ silence $ H.hspec $ H.beforeAll (append "beforeAll") $ do H.it "foo" $ do append "foo" H.it "bar" $ do append "bar" readIORef ref `shouldReturn` [- "before"+ "beforeAll" , "foo" , "bar" ]@@ -158,6 +158,21 @@ silence $ H.hspec $ H.beforeAll (return n) $ do H.it "foo" $ \m -> do m `shouldBe` (n :: Int)++ describe "beforeAllWith" $ do+ it "runs an action before the first spec item" $ do+ ref <- newIORef ([] :: [String])+ let append n = modifyIORef ref (++ return n)+ silence $ H.hspec $ H.before (return 23) $ H.beforeAllWith (\n -> append "beforeAllWith" >> return (succ n :: Int)) $ do+ H.it "foo" $ \n -> do+ append ("foo " ++ show n)+ H.it "bar" $ \n -> do+ append ("bar " ++ show n)+ readIORef ref `shouldReturn` [+ "beforeAllWith"+ , "foo 24"+ , "bar 24"+ ] describe "after" $ do it "must be used with a before action" $ do