diff --git a/hspec-discover/src/Config.hs b/hspec-discover/src/Config.hs
--- a/hspec-discover/src/Config.hs
+++ b/hspec-discover/src/Config.hs
@@ -22,7 +22,7 @@
   ]
 
 usage :: String -> String
-usage prog = "\nUsage: " ++ prog ++ " SRC CUR DST [--nested] [--formatter=FORMATTER]\n"
+usage prog = "\nUsage: " ++ prog ++ " SRC CUR DST [--formatter=FORMATTER]\n"
 
 parseConfig :: String -> [String] -> Either String Config
 parseConfig prog args = case getOpt Permute options args of
diff --git a/hspec-discover/src/Run.hs b/hspec-discover/src/Run.hs
--- a/hspec-discover/src/Run.hs
+++ b/hspec-discover/src/Run.hs
@@ -1,17 +1,26 @@
 {-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverloadedStrings #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 -- | A preprocessor that finds and combines specs.
-module Run where
+module Run (
+  run
+
+-- exported for testing
+, importList
+, fileToSpec
+, findSpecs
+, getFilesRecursive
+, driverWithFormatter
+, moduleName
+) where
 import           Control.Monad
 import           Control.Applicative
 import           Data.List
 import           Data.Maybe
 import           Data.String
-import           Data.Function
 import           System.Environment
 import           System.Exit
 import           System.IO
-import           System.Directory
+import           System.Directory (doesDirectoryExist, getDirectoryContents, doesFileExist)
 import           System.FilePath hiding (combine)
 
 import           Config
@@ -19,6 +28,8 @@
 instance IsString ShowS where
   fromString = showString
 
+type Spec = String
+
 run :: [String] -> IO ()
 run args_ = do
   name <- getProgName
@@ -28,25 +39,22 @@
         hPutStrLn stderr err
         exitFailure
       Right c -> do
+        when (configNested c) (hPutStrLn stderr "hspec-discover: WARNING - The `--nested' flag is deprecated and will be removed in a future release!")
         specs <- findSpecs src
         writeFile dst (mkSpecModule src c specs)
     _ -> do
       hPutStrLn stderr (usage name)
       exitFailure
 
-mkSpecModule :: FilePath -> Config -> [SpecNode] -> String
+mkSpecModule :: FilePath -> Config -> [Spec] -> String
 mkSpecModule src c nodes =
   ( "{-# LINE 1 " . shows src . " #-}"
   . showString "module Main where\n"
   . importList nodes
   . maybe driver (driverWithFormatter (null nodes)) (configFormatter c)
-  . format nodes
+  . formatSpecs nodes
   ) "\n"
   where
-    format
-      | configNested c = formatSpecsNested
-      | otherwise = formatSpecs
-
     driver =
         showString "import Test.Hspec\n"
       . showString "main :: IO ()\n"
@@ -64,125 +72,48 @@
 moduleName = reverse . dropWhile (== '.') . dropWhile (/= '.') . reverse
 
 -- | Generate imports for a list of specs.
-importList :: [SpecNode] -> ShowS
-importList = go ""
+importList :: [Spec] -> ShowS
+importList = foldr (.) "" . map f
   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
+    f :: Spec -> ShowS
+    f name = "import qualified " . showString name . "Spec\n"
 
 -- | Combine a list of strings with (>>).
 sequenceS :: [ShowS] -> ShowS
 sequenceS = foldr (.) "" . intersperse " >> "
 
 -- | Convert a list of specs to code.
-formatSpecs :: [SpecNode] -> ShowS
+formatSpecs :: [Spec] -> 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)
+formatSpec :: Spec -> ShowS
+formatSpec name = "describe " . shows name . " " . showString name . "Spec.spec"
 
--- | Find specs relative to given source file.
---
--- The source file itself is not considered.
-findSpecs :: FilePath -> IO [SpecNode]
+findSpecs :: FilePath -> IO [Spec]
 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 = catMaybes . map specFromFile
-          where
-            suffixes :: [String]
-            suffixes = ["Spec.hs","Spec.lhs"]
-
-            specFromFile :: FilePath -> Maybe SpecNode
-            specFromFile file = msum $ map (specFromFile_ file) suffixes
-
-            specFromFile_ :: FilePath -> String -> Maybe SpecNode
-            specFromFile_ file suffix
-              | suffix `isSuffixOf` file = Just $ SpecNode (dropEnd (length suffix) file) True []
-              | otherwise = Nothing
-
-            dropEnd :: Int -> [a] -> [a]
-            dropEnd n = reverse . drop n . reverse
-
-        -- remove empty leafs
-        filterSpecs :: [SpecNode] -> [SpecNode]
-        filterSpecs = filter (\x -> specNodeInhabited x || (not . null . specNodeChildren) x)
+  mapMaybe fileToSpec . filter (/= file) <$> getFilesRecursive dir
 
-        -- 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
+fileToSpec :: FilePath -> Maybe String
+fileToSpec f = intercalate "." . reverse <$> case reverse $ splitDirectories f of
+  x:xs -> case stripSuffix "Spec.hs" x <|> stripSuffix "Spec.lhs" x of
+    Nothing -> Nothing
+    Just "" -> Nothing
+    Just ys -> Just (ys : xs)
+  _ -> Nothing
+  where
+    stripSuffix :: Eq a => [a] -> [a] -> Maybe [a]
+    stripSuffix suffix str = reverse <$> stripPrefix (reverse suffix) (reverse str)
 
-            x `combine` y = SpecNode name inhabited children
-              where
-                name      = specNodeName x
-                inhabited = specNodeInhabited x || specNodeInhabited y
-                children  = specNodeChildren x ++ specNodeChildren y
+getFilesRecursive :: FilePath -> IO [FilePath]
+getFilesRecursive baseDir = sort <$> go []
+  where
+    go :: FilePath -> IO [FilePath]
+    go dir = do
+      c <- map (dir </>) . filter (`notElem` [".", ".."]) <$> getDirectoryContents (baseDir </> dir)
+      dirs <- filterM (doesDirectoryExist . (baseDir </>)) c >>= mapM go
+      files <- filterM (doesFileExist . (baseDir </>)) c
+      return (files ++ concat dirs)
diff --git a/hspec-discover/test-data/lhs-spec/FooSpec.lhs b/hspec-discover/test-data/lhs-spec/FooSpec.lhs
deleted file mode 100644
--- a/hspec-discover/test-data/lhs-spec/FooSpec.lhs
+++ /dev/null
diff --git a/hspec-discover/test-data/lhs-spec/Spec.hs b/hspec-discover/test-data/lhs-spec/Spec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/lhs-spec/Spec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/no-intermediate-specs/Foo/Bar/BazSpec.hs b/hspec-discover/test-data/no-intermediate-specs/Foo/Bar/BazSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/no-intermediate-specs/Foo/Bar/BazSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/prefix-name/Foo/BazSpec.hs b/hspec-discover/test-data/prefix-name/Foo/BazSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/prefix-name/Foo/BazSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/prefix-name/FooBar/BazSpec.hs b/hspec-discover/test-data/prefix-name/FooBar/BazSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/prefix-name/FooBar/BazSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/prefix-name/FooBarSpec.hs b/hspec-discover/test-data/prefix-name/FooBarSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/prefix-name/FooBarSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/prefix-name/FooSpec.hs b/hspec-discover/test-data/prefix-name/FooSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/prefix-name/FooSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/several-specs/BarSpec.hs b/hspec-discover/test-data/several-specs/BarSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/several-specs/BarSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/several-specs/BazSpec.hs b/hspec-discover/test-data/several-specs/BazSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/several-specs/BazSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/several-specs/FooSpec.hs b/hspec-discover/test-data/several-specs/FooSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/several-specs/FooSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/single-spec-nested/Foo/BarSpec.hs b/hspec-discover/test-data/single-spec-nested/Foo/BarSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/single-spec-nested/Foo/BarSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/single-spec/FooSpec.hs b/hspec-discover/test-data/single-spec/FooSpec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/single-spec/FooSpec.hs
+++ /dev/null
diff --git a/hspec-discover/test-data/single-spec/Spec.hs b/hspec-discover/test-data/single-spec/Spec.hs
deleted file mode 100644
--- a/hspec-discover/test-data/single-spec/Spec.hs
+++ /dev/null
diff --git a/hspec-discover/test/ConfigSpec.hs b/hspec-discover/test/ConfigSpec.hs
--- a/hspec-discover/test/ConfigSpec.hs
+++ b/hspec-discover/test/ConfigSpec.hs
@@ -22,16 +22,16 @@
       parse ["--foo"] `shouldBe` (Left . unlines) [
           "hspec-discover: unrecognized option `--foo'"
         , ""
-        , "Usage: hspec-discover SRC CUR DST [--nested] [--formatter=FORMATTER]"
+        , "Usage: hspec-discover SRC CUR DST [--formatter=FORMATTER]"
         ]
 
     it "returns error message on unexpected argument" $ do
       parse ["foo"]   `shouldBe` (Left . unlines) [
           "hspec-discover: unexpected argument `foo'"
         , ""
-        , "Usage: hspec-discover SRC CUR DST [--nested] [--formatter=FORMATTER]"
+        , "Usage: hspec-discover SRC CUR DST [--formatter=FORMATTER]"
         ]
 
     context "when option is given multiple times" $ do
-      it "the last occurrence takes precedence" $ do
+      it "gives the last occurrence precedence" $ do
         parse ["--formatter", "foo", "--formatter", "bar"] `shouldBe` Right (defaultConfig {configFormatter = Just "bar"})
diff --git a/hspec-discover/test/RunSpec.hs b/hspec-discover/test/RunSpec.hs
--- a/hspec-discover/test/RunSpec.hs
+++ b/hspec-discover/test/RunSpec.hs
@@ -2,47 +2,82 @@
 
 import           Test.Hspec.Meta
 
-import           Data.List (intercalate)
+import           Control.Applicative
+import           System.IO
+import           System.Directory
+import           System.FilePath
+import           Data.List (intercalate, sort)
 
 import           Run
 
 main :: IO ()
 main = hspec spec
 
+withTempFile :: (FilePath -> IO a) -> IO a
+withTempFile action = do
+  dir <- getTemporaryDirectory
+  (file, h) <- openTempFile dir ""
+  hClose h
+  action file <* removeFile file
+
+
 spec :: Spec
 spec = do
-  describe "findSpecs" $ do
-    context "when specs are not nested" $ do
-      it "finds a single spec" $ do
-        findSpecs "hspec-discover/test-data/single-spec/Spec.hs" `shouldReturn` [SpecNode "Foo" True []]
+  describe "run" $ do
+    it "generates test driver" $ withTempFile $ \f -> do
+      run ["hspec-discover/test-data/nested-spec/Spec.hs", "", f]
+      readFile f `shouldReturn` unlines [
+          "{-# LINE 1 \"hspec-discover/test-data/nested-spec/Spec.hs\" #-}module Main where"
+        , "import qualified Foo.Bar.BazSpec"
+        , "import qualified Foo.BarSpec"
+        , "import qualified FooSpec"
+        , "import Test.Hspec"
+        , "main :: IO ()"
+        , "main = hspec $ describe \"Foo.Bar.Baz\" Foo.Bar.BazSpec.spec >> describe \"Foo.Bar\" Foo.BarSpec.spec >> describe \"Foo\" FooSpec.spec"
+        ]
 
-      it "finds several specs" $ do
-        findSpecs "hspec-discover/test-data/several-specs/Spec.hs" `shouldReturn` [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []]
+    it "generates test driver for an empty directory" $ withTempFile $ \f -> do
+      run ["hspec-discover/test-data/empty-dir/Spec.hs", "", f]
+      readFile f `shouldReturn` unlines [
+          "{-# LINE 1 \"hspec-discover/test-data/empty-dir/Spec.hs\" #-}module Main where"
+        , "import Test.Hspec"
+        , "main :: IO ()"
+        , "main = hspec $ return ()"
+        ]
 
-      it "discovers .lhs files" $ do
-        findSpecs "hspec-discover/test-data/lhs-spec/Spec.hs" `shouldReturn` [SpecNode "Foo" True []]
+  describe "getFilesRecursive" $ do
+    it "recursively returns all file entries of a given directory" $ do
+      getFilesRecursive "hspec-discover/test-data" `shouldReturn` sort [
+          "empty-dir/Foo/Bar/Baz/.placeholder"
+        , "nested-spec/Foo/Bar/BazSpec.hs"
+        , "nested-spec/Foo/BarSpec.hs"
+        , "nested-spec/FooSpec.hs"
+        ]
 
-    context "when specs are nested" $ do
-      it "finds a single spec" $ do
-        findSpecs "hspec-discover/test-data/single-spec-nested/Spec.hs" `shouldReturn` [SpecNode "Foo" False [SpecNode "Bar" True []]]
+  describe "fileToSpec" $ do
+    it "converts path to spec name" $ do
+      fileToSpec "FooSpec.hs" `shouldBe` Just "Foo"
 
-      it "properly groups nested specs" $ do
-        findSpecs "hspec-discover/test-data/nested-spec/Spec.hs" `shouldReturn` [SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]]
+    it "rejects spec with empty name" $ do
+      fileToSpec "Spec.hs" `shouldBe` Nothing
 
-    context "given a nested spec, without specs at the intermediate nodes" $ do
-      it "finds a single spec" $ do
-        findSpecs "hspec-discover/test-data/no-intermediate-specs/Spec.hs" `shouldReturn` [SpecNode "Foo" False [SpecNode "Bar" False [SpecNode "Baz" True []]]]
+    it "works for lhs files" $ do
+      fileToSpec "FooSpec.lhs" `shouldBe` Just "Foo"
 
-    context "given a nested specs, with specs at the intermediate nodes" $ do
-      context "with two top-level specs, where one spec name is a prefix of the other" $ do
-        it "properly sorts specs" $ do
-          findSpecs "hspec-discover/test-data/prefix-name/Spec.hs" `shouldReturn`
-            [SpecNode "Foo" True [SpecNode "Baz" True []], SpecNode "FooBar" True [SpecNode "Baz" True []]]
+    it "returns Nothing for invalid spec name" $ do
+      fileToSpec "foo" `shouldBe` Nothing
 
-    context "when there are no specs" $ do
-      it "returns an empty list" $ do
-        findSpecs "hspec-discover/test-data/empty-dir/Spec.hs" `shouldReturn` []
+    context "when path has directory component" $ do
+      it "converts path to spec name" $ do
+        fileToSpec ("Foo" </> "Bar" </> "BazSpec.hs") `shouldBe` Just "Foo.Bar.Baz"
 
+      it "rejects spec with empty name" $ do
+        fileToSpec ("Foo" </> "Bar" </> "Spec.hs") `shouldBe` Nothing
+
+  describe "findSpecs" $ do
+    it "finds specs" $ do
+      findSpecs "hspec-discover/test-data/nested-spec/Spec.hs" `shouldReturn` ["Foo.Bar.Baz","Foo.Bar","Foo"]
+
   describe "driverWithFormatter" $ do
     it "generates a test driver that uses a custom formatter" $ do
       driverWithFormatter False "Some.Module.formatter" "" `shouldBe` intercalate "\n" [
@@ -57,52 +92,9 @@
     it "returns the module name of an fully qualified identifier" $ do
       moduleName "Some.Module.someId" `shouldBe` "Some.Module"
 
-  describe "formatSpec" $ do
-    it "generates code for a spec" $
-      formatSpec (SpecNode "Foo" True []) "" `shouldBe` "describe \"Foo\" FooSpec.spec"
-
-    it "generates code for a nested spec" $
-      formatSpec (SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]) "" `shouldBe`
-        "describe \"Foo\" FooSpec.spec >> describe \"Foo.Bar\" Foo.BarSpec.spec >> describe \"Foo.Bar.Baz\" Foo.Bar.BazSpec.spec"
-
-  describe "formatSpecs" $ do
-    it "generates code for a list of specs" $ do
-      formatSpecs [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []] "" `shouldBe`
-        "describe \"Bar\" BarSpec.spec >> describe \"Baz\" BazSpec.spec >> describe \"Foo\" FooSpec.spec"
-
-    it "generates code for an empty list" $ do
-      formatSpecs [] "" `shouldBe`
-        "return ()"
-
-  describe "formatSpecNested" $ do
-    it "generates code for a spec" $
-      formatSpecNested (SpecNode "Foo" True []) "" `shouldBe` "describe \"Foo\" (FooSpec.spec)"
-
-    it "generates code for a nested spec" $
-      formatSpecNested (SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]) "" `shouldBe`
-        "describe \"Foo\" (FooSpec.spec >> describe \"Bar\" (Foo.BarSpec.spec >> describe \"Baz\" (Foo.Bar.BazSpec.spec)))"
-
-  describe "formatSpecsNested" $ do
-    it "generates code for a list of specs" $ do
-      formatSpecsNested [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []] "" `shouldBe`
-        "describe \"Bar\" (BarSpec.spec) >> describe \"Baz\" (BazSpec.spec) >> describe \"Foo\" (FooSpec.spec)"
-
-    it "generates code for an empty list" $ do
-      formatSpecsNested [] "" `shouldBe`
-        "return ()"
-
   describe "importList" $ do
-    it "generates imports for a spec" $ do
-      importList [SpecNode "Foo" True []] "" `shouldBe` "import qualified FooSpec\n"
-
-    it "generates imports for a nested spec" $
-      importList [SpecNode "Foo" True [SpecNode "Bar" True [SpecNode "Baz" True []]]] "" `shouldBe`
-        "import qualified FooSpec\nimport qualified Foo.BarSpec\nimport qualified Foo.Bar.BazSpec\n"
-
     it "generates imports for a list of specs" $ do
-      importList [SpecNode "Bar" True [], SpecNode "Baz" True [], SpecNode "Foo" True []] "" `shouldBe`
-        "import qualified BarSpec\nimport qualified BazSpec\nimport qualified FooSpec\n"
-
-    it "generates imports for a nested spec that has no specs at the intermediate nodes" $ do
-      importList [SpecNode "Foo" False [SpecNode "Bar" False [SpecNode "Baz" True []]]] "" `shouldBe`
-        "import qualified Foo.Bar.BazSpec\n"
+      importList ["Foo", "Bar"] "" `shouldBe` unlines [
+          "import qualified FooSpec"
+        , "import qualified BarSpec"
+        ]
diff --git a/hspec.cabal b/hspec.cabal
--- a/hspec.cabal
+++ b/hspec.cabal
@@ -1,5 +1,5 @@
 name:             hspec
-version:          1.7.2.1
+version:          1.8.0
 license:          MIT
 license-file:     LICENSE
 copyright:        (c) 2011-2013 Simon Hengel,
@@ -24,23 +24,10 @@
 
 -- find hspec-discover/test-data/ -type f
 extra-source-files:
-  hspec-discover/test-data/single-spec/FooSpec.hs
-  hspec-discover/test-data/single-spec/Spec.hs
-  hspec-discover/test-data/single-spec-nested/Foo/BarSpec.hs
   hspec-discover/test-data/nested-spec/FooSpec.hs
   hspec-discover/test-data/nested-spec/Foo/Bar/BazSpec.hs
   hspec-discover/test-data/nested-spec/Foo/BarSpec.hs
-  hspec-discover/test-data/lhs-spec/FooSpec.lhs
-  hspec-discover/test-data/lhs-spec/Spec.hs
-  hspec-discover/test-data/several-specs/BarSpec.hs
-  hspec-discover/test-data/several-specs/FooSpec.hs
-  hspec-discover/test-data/several-specs/BazSpec.hs
   hspec-discover/test-data/empty-dir/Foo/Bar/Baz/.placeholder
-  hspec-discover/test-data/prefix-name/FooSpec.hs
-  hspec-discover/test-data/prefix-name/Foo/BazSpec.hs
-  hspec-discover/test-data/prefix-name/FooBarSpec.hs
-  hspec-discover/test-data/prefix-name/FooBar/BazSpec.hs
-  hspec-discover/test-data/no-intermediate-specs/Foo/Bar/BazSpec.hs
 
 source-repository head
   type: git
@@ -62,7 +49,7 @@
     , HUnit         >= 1.2.5
     , QuickCheck    >= 2.5.1
     , quickcheck-io
-    , hspec-expectations == 0.3.3.*
+    , hspec-expectations == 0.4.0.*
   exposed-modules:
       Test.Hspec
       Test.Hspec.Core
@@ -75,6 +62,7 @@
       Test.Hspec.Util
       Test.Hspec.Compat
       Test.Hspec.Core.Type
+      Test.Hspec.Core.QuickCheckUtil
       Test.Hspec.Config
       Test.Hspec.Options
       Test.Hspec.FailureReport
@@ -119,7 +107,7 @@
     , quickcheck-io
     , hspec-expectations
 
-    , hspec-meta >= 1.7.1
+    , hspec-meta >= 1.8.0
     , process
     , ghc-paths
 
diff --git a/src/Test/Hspec.hs b/src/Test/Hspec.hs
--- a/src/Test/Hspec.hs
+++ b/src/Test/Hspec.hs
@@ -1,23 +1,12 @@
 -- |
 -- Stability: stable
 --
--- 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 is a testing library for Haskell.
 --
--- 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
--- /textual descriptions/ of behavior and /examples/ for that behavior.  The
--- examples serve as test cases for the specified behavior.  Hspec's mechanism
--- for examples is extensible.  Support for QuickCheck properties and HUnit
--- tests is included in the core package.
+-- This is the library reference for Hspec.
+-- The <http://hspec.github.io/ User's Manual> contains more in-depth
+-- documentation.
 module Test.Hspec (
-
--- * Introduction
--- $intro
-
 -- * Types
   Spec
 , Example
@@ -45,73 +34,9 @@
 import           Test.Hspec.Runner
 import           Test.Hspec.HUnit ()
 import           Test.Hspec.Expectations
+import           Test.Hspec.Core (mapSpecItem)
 import qualified Test.Hspec.Core as Core
 
-import           Data.IORef
-import           Control.Applicative
-
--- $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
--- > import Test.QuickCheck
--- > import Test.HUnit
--- >
--- > 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
--- implement each behavior one at a time, ensuring that each behavior is met
--- and there is no undocumented behavior.
---
--- > unformatPhoneNumber :: String -> String
--- > unformatPhoneNumber = undefined
--- >
--- > formatPhoneNumber :: String -> String
--- > formatPhoneNumber = undefined
---
--- The 'describe' function takes a list of behaviors and examples bound
--- together with the 'it' function
---
--- > spec :: Spec
--- > spec = do
--- >   describe "unformatPhoneNumber" $ do
---
--- A `Bool` can be used as an 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.Lang.Assertion' can be used as an example.
---
--- >     it "converts letters to numbers" $ do
--- >       let expected = "6862377"
--- >           actual   = unformatPhoneNumber "NUMBERS"
--- >       actual @?= expected
---
---
--- 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
--- >
--- > phoneNumber :: Gen String
--- > phoneNumber = do
--- >   n <- elements [7,10,11,12,13,14,15]
--- >   vectorOf n (elements "0123456789")
-
-
 -- | Combine a list of specs into a larger spec.
 describe :: String -> Spec -> Spec
 describe label action = fromSpecList [Core.describe label (runSpecM action)]
@@ -151,29 +76,16 @@
 
 -- | Run examples of given spec in parallel.
 parallel :: Spec -> Spec
-parallel = mapSpecItem $ \_ r e -> SpecItem True r e
+parallel = mapSpecItem $ \item -> item {itemIsParallelizable = True}
 
 -- | Run a custom action before every spec item.
 before :: IO () -> Spec -> Spec
-before action = mapSpecItem $ \b r e -> SpecItem b r (\params -> action *> e params)
+before action = around (action >>)
 
 -- | Run a custom action after every spec item.
 after :: IO () -> Spec -> Spec
-after action = mapSpecItem $ \b r e -> SpecItem b r (\params -> e params <* action)
+after action = around (>> action)
 
 -- | Run a custom action before and/or after every spec item.
 around :: (IO () -> IO ()) -> Spec -> Spec
-around action = mapSpecItem $ \b r e -> SpecItem b r (\params -> wrap (e params))
-  where
-    wrap e = do
-      ref <- newIORef (Fail "")
-      action (e >>= writeIORef ref)
-      readIORef ref
-
-mapSpecItem :: (Bool -> String -> (Params -> IO Result) -> SpecTree) -> Spec -> Spec
-mapSpecItem f = fromSpecList . map go . runSpecM
-  where
-    go :: SpecTree -> SpecTree
-    go spec = case spec of
-      SpecItem b r e -> f b r e
-      SpecGroup d es -> SpecGroup d (map go es)
+around a2 = mapSpecItem $ \item -> item {itemExample = \params a1 -> itemExample item params (a1 . a2)}
diff --git a/src/Test/Hspec/Compat.hs b/src/Test/Hspec/Compat.hs
--- a/src/Test/Hspec/Compat.hs
+++ b/src/Test/Hspec/Compat.hs
@@ -2,7 +2,6 @@
 module Test.Hspec.Compat (
   showType
 , showFullType
-, isUserInterrupt
 , readMaybe
 , module Data.IORef
 #if !MIN_VERSION_base(4,6,0)
@@ -11,7 +10,6 @@
 ) where
 
 import           Data.Typeable (Typeable, typeOf, typeRepTyCon)
-import qualified Test.QuickCheck as QC
 import           Text.Read
 import           Data.IORef
 
@@ -71,12 +69,3 @@
 #else
   show t
 #endif
-
-isUserInterrupt :: QC.Result -> Bool
-isUserInterrupt r = case r of
-#if MIN_VERSION_QuickCheck(2,6,0)
-  QC.Failure {QC.interrupted = x} -> x
-#else
-  QC.Failure {QC.reason = "Exception: 'user interrupt'"} -> True
-#endif
-  _ -> False
diff --git a/src/Test/Hspec/Core.hs b/src/Test/Hspec/Core.hs
--- a/src/Test/Hspec/Core.hs
+++ b/src/Test/Hspec/Core.hs
@@ -18,11 +18,13 @@
 
 -- * Internal representation of a spec tree
 , SpecTree (..)
+, Item (..)
+, mapSpecItem
+, modifyParams
 , describe
 , it
 
 -- * Deprecated types and functions
-, Spec
 , Specs
 , hspecB
 , hspecX
@@ -33,13 +35,24 @@
 import           Control.Applicative
 import           System.IO (Handle)
 
-import           Test.Hspec.Core.Type hiding (Spec)
+import           Test.Hspec.Core.Type
 import qualified Test.Hspec.Runner as Runner
 import           Test.Hspec.Runner (Summary(..), Config(..), defaultConfig)
 
 hspecWith :: Config -> [SpecTree] -> IO Summary
 hspecWith c = Runner.hspecWith c . fromSpecList
 
+mapSpecItem :: (Item -> Item) -> Spec -> Spec
+mapSpecItem f = fromSpecList . map go . runSpecM
+  where
+    go :: SpecTree -> SpecTree
+    go spec = case spec of
+      SpecItem item -> SpecItem (f item)
+      SpecGroup d es -> SpecGroup d (map go es)
+
+modifyParams :: (Params -> Params) -> Spec -> Spec
+modifyParams f = mapSpecItem $ \item -> item {itemExample = \p -> (itemExample item) (f p)}
+
 {-# DEPRECATED hspecX "use `Test.Hspec.Runner.hspec` instead" #-}     -- since 1.2.0
 hspecX :: [SpecTree] -> IO ()
 hspecX = hspec
@@ -55,9 +68,6 @@
 {-# DEPRECATED hHspec "use `Test.Hspec.Runner.hspecWith` instead" #-} -- since 1.4.0
 hHspec :: Handle -> [SpecTree] -> IO Summary
 hHspec h = hspecWith defaultConfig {configHandle = Left h}
-
-{-# DEPRECATED Spec "use `SpecTree` instead" #-}                      -- since 1.4.0
-type Spec = SpecTree
 
 {-# DEPRECATED Specs "use `[SpecTree]` instead" #-}                   -- since 1.4.0
 type Specs = [SpecTree]
diff --git a/src/Test/Hspec/Core/QuickCheckUtil.hs b/src/Test/Hspec/Core/QuickCheckUtil.hs
new file mode 100644
--- /dev/null
+++ b/src/Test/Hspec/Core/QuickCheckUtil.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE CPP #-}
+module Test.Hspec.Core.QuickCheckUtil where
+
+import Data.IORef
+import Test.QuickCheck hiding (Result(..))
+import Test.QuickCheck as QC
+import Test.QuickCheck.Property hiding (Result(..))
+import qualified Test.QuickCheck.Property as QCP
+import Test.QuickCheck.IO ()
+import Control.Applicative
+
+aroundProperty :: (IO () -> IO ()) -> Property -> Property
+aroundProperty action p = MkProp . aroundRose action . unProp <$> p
+
+aroundRose :: (IO () -> IO ()) -> Rose QCP.Result -> Rose QCP.Result
+aroundRose action r = ioRose $ do
+  ref <- newIORef (return QCP.succeeded)
+  action (reduceRose r >>= writeIORef ref)
+  readIORef ref
+
+isUserInterrupt :: QC.Result -> Bool
+isUserInterrupt r = case r of
+#if MIN_VERSION_QuickCheck(2,6,0)
+  QC.Failure {QC.interrupted = x} -> x
+#else
+  QC.Failure {QC.reason = "Exception: 'user interrupt'"} -> True
+#endif
+  _ -> False
diff --git a/src/Test/Hspec/Core/Type.hs b/src/Test/Hspec/Core/Type.hs
--- a/src/Test/Hspec/Core/Type.hs
+++ b/src/Test/Hspec/Core/Type.hs
@@ -5,6 +5,7 @@
 , runSpecM
 , fromSpecList
 , SpecTree (..)
+, Item (..)
 , Example (..)
 , Result (..)
 , Params (..)
@@ -34,10 +35,9 @@
 import qualified Test.QuickCheck.Property as QCP
 import qualified Test.QuickCheck.IO ()
 
-import           Test.Hspec.Compat (isUserInterrupt)
+import           Test.Hspec.Core.QuickCheckUtil
 import           Control.DeepSeq (deepseq)
 
-
 type Spec = SpecM ()
 
 -- | A writer monad for `SpecTree` forests.
@@ -75,8 +75,14 @@
 -- | Internal representation of a spec.
 data SpecTree =
     SpecGroup String [SpecTree]
-  | SpecItem Bool String (Params -> IO Result)
+  | SpecItem Item
 
+data Item = Item {
+  itemIsParallelizable :: Bool
+, itemRequirement :: String
+, itemExample :: Params -> (IO () -> IO ()) -> IO Result
+}
+
 -- | The @describe@ function combines a list of specs into a larger spec.
 describe :: String -> [SpecTree] -> SpecTree
 describe s = SpecGroup msg
@@ -87,7 +93,7 @@
 
 -- | Create a spec item.
 it :: Example a => String -> a -> SpecTree
-it s e = SpecItem False msg (`evaluateExample` e)
+it s e = SpecItem $ Item False msg (evaluateExample e)
   where
     msg
       | null s = "(unspecified behavior)"
@@ -95,23 +101,23 @@
 
 -- | A type class for examples.
 class Example a where
-  evaluateExample :: Params -> a -> IO Result
+  evaluateExample :: a -> Params -> (IO () -> IO ()) -> IO Result
 
 instance Example Bool where
-  evaluateExample _ b = if b then return Success else return (Fail "")
+  evaluateExample b _ _ = if b then return Success else return (Fail "")
 
 instance Example Expectation where
-  evaluateExample _ action = (action >> return Success) `E.catches` [
-      E.Handler (\(HUnitFailure err) -> (return . Fail) err)
+  evaluateExample e _ action = (action e >> return Success) `E.catches` [
+      E.Handler (\(HUnitFailure err) -> return (Fail err))
     , E.Handler (return :: Result -> IO Result)
     ]
 
 instance Example Result where
-  evaluateExample _ = return
+  evaluateExample r _ _ = return r
 
 instance Example QC.Property where
-  evaluateExample c p = do
-    r <- QC.quickCheckWithResult (paramsQuickCheckArgs c) {QC.chatty = False} (QCP.callback progressCallback p)
+  evaluateExample p c action = do
+    r <- QC.quickCheckWithResult (paramsQuickCheckArgs c) {QC.chatty = False} (QCP.callback progressCallback $ aroundProperty action p)
     when (isUserInterrupt r) $ do
       E.throwIO E.UserInterrupt
 
diff --git a/src/Test/Hspec/HUnit.hs b/src/Test/Hspec/HUnit.hs
--- a/src/Test/Hspec/HUnit.hs
+++ b/src/Test/Hspec/HUnit.hs
@@ -12,7 +12,7 @@
 
 -- | This instance is deprecated, use `Test.Hspec.HUnit.fromHUnitTest` instead!
 instance Example Test where
-  evaluateExample _ test = do
+  evaluateExample test _ _ = do
     (counts, fails) <- HU.runTestText HU.putTextToShowS test
     let r = if HU.errors counts + HU.failures counts == 0
              then Success
diff --git a/src/Test/Hspec/QuickCheck.hs b/src/Test/Hspec/QuickCheck.hs
--- a/src/Test/Hspec/QuickCheck.hs
+++ b/src/Test/Hspec/QuickCheck.hs
@@ -1,19 +1,24 @@
 -- |
 -- Stability: provisional
 module Test.Hspec.QuickCheck (
+-- * Params
+  modifyMaxSuccess
+, modifyMaxDiscardRatio
+, modifyMaxSize
 -- * Re-exports from QuickCheck
 -- |
 -- Previous versions of Hspec provided a distinct `property` combinator, but
 -- it's now possible to use QuickCheck's `property` instead.  For backward
 -- compatibility we now re-export QuickCheck's `property`, but it is advisable
 -- to import it from "Test.QuickCheck" instead.
-  property
+, property
 -- * Shortcuts
 , prop
 ) where
 
 import           Test.QuickCheck
 import           Test.Hspec
+import           Test.Hspec.Core (Params(..), modifyParams)
 
 -- |
 -- > prop ".." $
@@ -25,3 +30,30 @@
 -- >   ..
 prop :: Testable prop => String -> prop -> Spec
 prop s = it s . property
+
+-- | Use a modified `maxSuccess` for given spec.
+modifyMaxSuccess :: (Int -> Int) -> Spec -> Spec
+modifyMaxSuccess = modifyArgs . modify
+  where
+    modify :: (Int -> Int) -> Args -> Args
+    modify f args = args {maxSuccess = f (maxSuccess args)}
+
+-- | Use a modified `maxDiscardRatio` for given spec.
+modifyMaxDiscardRatio :: (Int -> Int) -> Spec -> Spec
+modifyMaxDiscardRatio = modifyArgs . modify
+  where
+    modify :: (Int -> Int) -> Args -> Args
+    modify f args = args {maxDiscardRatio = f (maxDiscardRatio args)}
+
+-- | Use a modified `maxSize` for given spec.
+modifyMaxSize :: (Int -> Int) -> Spec -> Spec
+modifyMaxSize = modifyArgs . modify
+  where
+    modify :: (Int -> Int) -> Args -> Args
+    modify f args = args {maxSize = f (maxSize args)}
+
+modifyArgs :: (Args -> Args) -> Spec -> Spec
+modifyArgs = modifyParams . modify
+  where
+    modify :: (Args -> Args) -> Params -> Params
+    modify f p = p {paramsQuickCheckArgs = f (paramsQuickCheckArgs p)}
diff --git a/src/Test/Hspec/Runner.hs b/src/Test/Hspec/Runner.hs
--- a/src/Test/Hspec/Runner.hs
+++ b/src/Test/Hspec/Runner.hs
@@ -53,7 +53,7 @@
 
     goSpec :: [String] -> SpecTree -> Maybe SpecTree
     goSpec groups spec = case spec of
-      SpecItem _ requirement _ -> guard (p (groups, requirement)) >> return spec
+      SpecItem item -> guard (p (groups, itemRequirement item)) >> return spec
       SpecGroup group specs     -> case goSpecs (groups ++ [group]) specs of
         [] -> Nothing
         xs -> Just (SpecGroup group xs)
diff --git a/src/Test/Hspec/Runner/Eval.hs b/src/Test/Hspec/Runner/Eval.hs
--- a/src/Test/Hspec/Runner/Eval.hs
+++ b/src/Test/Hspec/Runner/Eval.hs
@@ -40,8 +40,8 @@
       defer (exampleGroupStarted formatter n (reverse rGroups) group)
       forM_ (zip [0..] xs) (queueSpec (group : rGroups))
       defer (exampleGroupDone formatter)
-    queueSpec rGroups (_, SpecItem isParallelizable requirement e) =
-      queueExample isParallelizable (reverse rGroups, requirement) e
+    queueSpec rGroups (_, SpecItem (Item isParallelizable requirement e)) =
+      queueExample isParallelizable (reverse rGroups, requirement) (`e` id)
 
     queueExample :: Bool -> Path -> (Params -> IO Result) -> IO ()
     queueExample isParallelizable path e
diff --git a/src/Test/Hspec/Util.hs b/src/Test/Hspec/Util.hs
--- a/src/Test/Hspec/Util.hs
+++ b/src/Test/Hspec/Util.hs
@@ -85,7 +85,7 @@
 getEnv :: String -> IO (Maybe String)
 getEnv key = either (const Nothing) Just <$> safeTry (Environment.getEnv key)
 
--- ensure that lines are not longer then given `n`, insert line beraks at word
+-- ensure that lines are not longer then given `n`, insert line breaks at word
 -- boundaries
 lineBreaksAt :: Int -> String -> [String]
 lineBreaksAt n input = case words input of
diff --git a/test/Helper.hs b/test/Helper.hs
--- a/test/Helper.hs
+++ b/test/Helper.hs
@@ -34,7 +34,8 @@
 import           Test.Hspec.Meta
 import           Test.QuickCheck hiding (Result(..))
 
-import qualified Test.Hspec.Core as H (Result(..), Params(..), fromSpecList, SpecTree(..))
+import qualified Test.Hspec as H
+import qualified Test.Hspec.Core as H (Params(..), Item(..), mapSpecItem)
 import qualified Test.Hspec.Runner as H
 
 ignoreExitCode :: IO () -> IO ()
@@ -73,6 +74,8 @@
 shouldUseArgs :: [String] -> (Args -> Bool) -> Expectation
 shouldUseArgs args p = do
   spy <- newIORef (H.paramsQuickCheckArgs defaultParams)
-  let spec = H.fromSpecList [H.SpecItem False "foo" $ \params -> writeIORef spy (H.paramsQuickCheckArgs params) >> return (H.Fail "example failed")]
+  let interceptArgs item = item {H.itemExample = \params action -> writeIORef spy (H.paramsQuickCheckArgs params) >> H.itemExample item params action}
+      spec = H.mapSpecItem interceptArgs $
+        H.it "foo" False
   (silence . ignoreExitCode . withArgs args . H.hspec) spec
   readIORef spy >>= (`shouldSatisfy` p)
diff --git a/test/Test/Hspec/Core/TypeSpec.hs b/test/Test/Hspec/Core/TypeSpec.hs
--- a/test/Test/Hspec/Core/TypeSpec.hs
+++ b/test/Test/Hspec/Core/TypeSpec.hs
@@ -3,6 +3,7 @@
 import           Helper
 import           Mock
 import           Data.List
+import           Data.IORef
 import           Control.Exception (AsyncException(..), throwIO)
 
 import qualified Test.Hspec.Core.Type as H hiding (describe, it)
@@ -13,8 +14,11 @@
 main = hspec spec
 
 evaluateExample :: H.Example e => e -> IO H.Result
-evaluateExample = H.evaluateExample (defaultParams {H.paramsQuickCheckArgs = (H.paramsQuickCheckArgs defaultParams) {replay = Just (read "", 0)}})
+evaluateExample e = H.evaluateExample e (defaultParams {H.paramsQuickCheckArgs = (H.paramsQuickCheckArgs defaultParams) {replay = Just (read "", 0)}}) id
 
+evaluateExampleWith :: H.Example e => (IO () -> IO ()) -> e -> IO H.Result
+evaluateExampleWith action e = H.evaluateExample e (defaultParams {H.paramsQuickCheckArgs = (H.paramsQuickCheckArgs defaultParams) {replay = Just (read "", 0)}}) action
+
 spec :: Spec
 spec = do
   describe "evaluateExample" $ do
@@ -38,6 +42,17 @@
       it "propagates exceptions" $ do
         evaluateExample (error "foobar" :: Expectation) `shouldThrow` errorCall "foobar"
 
+      it "runs provided action around expectation" $ do
+        ref <- newIORef (0 :: Int)
+        let action :: IO () -> IO ()
+            action e = do
+              n <- readIORef ref
+              e
+              readIORef ref `shouldReturn` succ n
+              modifyIORef ref succ
+        evaluateExampleWith action (modifyIORef ref succ) `shouldReturn` H.Success
+        readIORef ref `shouldReturn` 2
+
       context "when used with `pending`" $ do
         it "returns Pending" $ do
           evaluateExample (H.pending) `shouldReturn` H.Pending Nothing
@@ -62,6 +77,17 @@
           , "1"
           ]
 
+      it "runs provided action around each single check of the property" $ do
+        ref <- newIORef (0 :: Int)
+        let action :: IO () -> IO ()
+            action e = do
+              n <- readIORef ref
+              e
+              readIORef ref `shouldReturn` succ n
+              modifyIORef ref succ
+        H.Success <- evaluateExampleWith action (property $ modifyIORef ref succ)
+        readIORef ref `shouldReturn` 200
+
       context "when used with shouldBe" $ do
         it "shows what falsified it" $ do
           H.Fail r <- evaluateExample $ property $ \x y -> x + y `shouldBe` (x * y :: Int)
@@ -78,7 +104,7 @@
         evaluateExample p `shouldThrow` (== UserInterrupt)
 
       it "propagates exceptions" $ do
-        pendingWith "this probaly needs a patch to QuickCheck"
+        pendingWith "this probably needs a patch to QuickCheck"
         -- evaluateExample (property $ (error "foobar" :: Int -> Bool)) `shouldThrow` errorCall "foobar"
 
       context "when used with `pending`" $ do
@@ -99,7 +125,7 @@
             (reverse . reverse) xs `shouldBe` (xs :: [Int])
         mockCounter e `shouldReturn` 100
 
-      it "can be used with expecatations/HUnit assertions" $ do
+      it "can be used with expectations/HUnit assertions" $ do
         silence . H.hspecResult $ do
           H.describe "readIO" $ do
             H.it "is inverse to show" $ property $ \x -> do
diff --git a/test/Test/Hspec/FormattersSpec.hs b/test/Test/Hspec/FormattersSpec.hs
--- a/test/Test/Hspec/FormattersSpec.hs
+++ b/test/Test/Hspec/FormattersSpec.hs
@@ -154,9 +154,6 @@
       r <- runSpec testSpec
       r `shouldSatisfy` any (== "     # PENDING: pending message")
 
-    it "outputs failed examples in red, pending in yellow, and successful in green" $ do
-      pending
-
     context "same as failed_examples" $ do
       failed_examplesSpec H.progress
 
diff --git a/test/Test/Hspec/HUnitSpec.hs b/test/Test/Hspec/HUnitSpec.hs
--- a/test/Test/Hspec/HUnitSpec.hs
+++ b/test/Test/Hspec/HUnitSpec.hs
@@ -4,7 +4,7 @@
 
 import qualified Test.Hspec as H
 import qualified Test.Hspec.Runner as H
-import           Test.Hspec.Core.Type (SpecTree(..), runSpecM)
+import           Test.Hspec.Core.Type (SpecTree(..), Item(..), runSpecM)
 import           Test.Hspec.HUnit
 import           Test.HUnit
 
@@ -24,7 +24,7 @@
         go :: SpecTree -> Tree
         go x = case x of
           SpecGroup s xs  -> Group s (map go xs)
-          SpecItem _ s _  -> Example s
+          SpecItem item -> Example (itemRequirement item)
 
 spec :: Spec
 spec = do
diff --git a/test/Test/HspecSpec.hs b/test/Test/HspecSpec.hs
--- a/test/Test/HspecSpec.hs
+++ b/test/Test/HspecSpec.hs
@@ -2,10 +2,10 @@
 
 import           Helper
 import           Mock
+import           Data.IORef
 import           Data.List (isPrefixOf)
 
-import           Data.IORef
-import           Test.Hspec.Core (SpecTree(..), Result(..), runSpecM)
+import           Test.Hspec.Core (SpecTree(..), Item(..), Result(..), runSpecM)
 import qualified Test.Hspec as H
 import qualified Test.Hspec.Runner as H (hspecResult)
 
@@ -42,7 +42,7 @@
       length r `shouldBe` 3
 
     it "can be nested" $ do
-      let [SpecGroup foo [SpecGroup bar [SpecItem _ baz _]]] = runSpecM $ do
+      let [SpecGroup foo [SpecGroup bar [SpecItem Item {itemRequirement = baz}]]] = runSpecM $ do
             H.describe "foo" $ do
               H.describe "bar" $ do
                 H.it "baz" True
@@ -55,17 +55,17 @@
 
   describe "it" $ do
     it "takes a description of a desired behavior" $ do
-      let [SpecItem _ d _] = runSpecM (H.it "whatever" True)
-      d `shouldBe` "whatever"
+      let [SpecItem item] = runSpecM (H.it "whatever" True)
+      itemRequirement item `shouldBe` "whatever"
 
     it "takes an example of that behavior" $ do
-      let [SpecItem _ _ e] = runSpecM (H.it "whatever" True)
-      e defaultParams `shouldReturn` Success
+      let [SpecItem item] = runSpecM (H.it "whatever" True)
+      itemExample item defaultParams id `shouldReturn` Success
 
     context "when no description is given" $ do
       it "uses a default description" $ do
-        let [SpecItem _ d _] = runSpecM (H.it "" True)
-        d `shouldBe` "(unspecified behavior)"
+        let [SpecItem item] = runSpecM (H.it "" True)
+        itemRequirement item `shouldBe` "(unspecified behavior)"
 
   describe "example" $ do
     it "fixes the type of an expectation" $ do
@@ -76,15 +76,15 @@
 
   describe "parallel" $ do
     it "marks examples for parallel execution" $ do
-      let [SpecItem isParallelizable _ _] = runSpecM . H.parallel $ H.it "whatever" True
-      isParallelizable `shouldBe` True
+      let [SpecItem item] = runSpecM . H.parallel $ H.it "whatever" True
+      itemIsParallelizable item `shouldBe` True
 
     it "is applied recursively" $ do
-      let [SpecGroup _ [SpecGroup _ [SpecItem isParallelizable _ _]]] = runSpecM . H.parallel $ do
+      let [SpecGroup _ [SpecGroup _ [SpecItem item]]] = runSpecM . H.parallel $ do
             H.describe "foo" $ do
               H.describe "bar" $ do
                 H.it "baz" True
-      isParallelizable `shouldBe` True
+      itemIsParallelizable item `shouldBe` True
 
   describe "before" $ do
     it "runs an action before each spec item" $ do
@@ -96,6 +96,19 @@
           mockCounter mock `shouldReturn` 2
       mockCounter mock `shouldReturn` 2
 
+    context "when used multiple times" $ do
+      it "is evaluated outside in" $ do
+        ref <- newIORef (0 :: Int)
+        let action1 = do
+              readIORef ref `shouldReturn` 0
+              modifyIORef ref succ
+            action2 = do
+              readIORef ref `shouldReturn` 1
+              modifyIORef ref succ
+        silence $ H.hspec $ H.before action1 $ H.before action2 $ do
+          H.it "foo" $ do
+            readIORef ref `shouldReturn` 2
+
   describe "after" $ do
     it "runs an action after each spec item" $ do
       mock <- newMock
@@ -107,16 +120,16 @@
       mockCounter mock `shouldReturn` 2
 
   describe "around" $ do
-    it "runs an action before and/or after each spec item" $ do
+    it "wraps each spec item with an action" $ do
       ref <- newIORef (0 :: Int)
-      let wrapper :: IO () -> IO ()
-          wrapper e = do
+      let action :: IO () -> IO ()
+          action e = do
             readIORef ref `shouldReturn` 0
             writeIORef ref 1
             e
             readIORef ref `shouldReturn` 2
             writeIORef ref 3
-      silence $ H.hspec $ H.around wrapper $ do
+      silence $ H.hspec $ H.around action $ do
         H.it "foo" $ do
           readIORef ref `shouldReturn` 1
           writeIORef ref 2
