tasty-hspec 1.1.6 → 1.1.7
raw patch · 4 files changed
+202/−240 lines, 4 filesdep ~hspecdep ~hspec-corePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hspec, hspec-core
API changes (from Hackage documentation)
Files
- CHANGELOG.md +14/−0
- src/Test/Tasty/Hspec.hs +86/−200
- src/Test/Tasty/Hspec/Compat.hs +83/−0
- tasty-hspec.cabal +19/−40
CHANGELOG.md view
@@ -5,6 +5,20 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). +## [1.1.7] - 2021-05-12++### Changed+- Support hspec-2.8.0++### Removed+- Don't re-export `Test.Hspec`+- Drop support for hspec < 2.5++## [1.1.6-r1] - 2021-03-13++### Changed+- Support base-4.15+ ## [1.1.6] - 2020-11-11 ### Changed
src/Test/Tasty/Hspec.hs view
@@ -1,44 +1,38 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE CPP #-} -- | @hspec@ and @tasty@ serve similar purposes; consider using one or the -- other. -- -- However, in a pinch, this module allows you to run an @hspec@ 'H.Spec' as a -- @tasty@ 'T.TestTree'.- module Test.Tasty.Hspec- ( -- * Tests- testSpec- , testSpecs+ ( -- * Tests+ testSpec,+ testSpecs,+ -- * Options- , TreatPendingAs(..)- -- * Re-exports- , module Test.Hspec- -- * Examples- -- $examples- ) where+ TreatPendingAs (..), + -- * Examples+ -- $examples+ )+where+ import Control.Applicative ((<$>))-import Control.Exception (SomeException) import Control.Monad (guard) import Data.Maybe (catMaybes, fromMaybe, mapMaybe) import Data.Proxy import Data.Typeable (Typeable)- import qualified Test.Hspec as H import qualified Test.Hspec.Core.Formatters as H import qualified Test.Hspec.Core.Spec as H-import qualified Test.QuickCheck as QC import qualified Test.Tasty as T-import qualified Test.Tasty.SmallCheck as TSC+import Test.Tasty.Hspec.Compat import qualified Test.Tasty.Options as T import qualified Test.Tasty.Providers as T import qualified Test.Tasty.QuickCheck as TQC import qualified Test.Tasty.Runners as T---- For re-export.-import Test.Hspec+import qualified Test.Tasty.SmallCheck as TSC -- $examples --@@ -62,9 +56,9 @@ -- tests :: TestTree -- tests = -- localOption TreatPendingAsSuccess $ testGroup "My Hspec TestTree"--- $ [ unsafePerformIO (testSpec "My first Hspec test" spec_firstHspecTest)--- , ...--- ]+-- [ unsafePerformIO (testSpec "My first Hspec test" spec_firstHspecTest)+-- , ...+-- ] -- @ -- -- However, if you don't do any @IO@ during 'Spec' creation, or the @IO@ need@@ -83,194 +77,87 @@ -- | Create a <https://hackage.haskell.org/package/tasty tasty> 'T.TestTree' from an -- <https://hackage.haskell.org/package/hspec Hspec> 'H.Spec'. testSpec :: T.TestName -> H.Spec -> IO T.TestTree-testSpec name spec = T.testGroup name <$> testSpecs spec+testSpec name spec = do+ trees <- testSpecs spec+ pure (T.testGroup name trees) --- | Create a list of <https://hackage.haskell.org/package/tasty tasty>--- 'T.TestTree' from an <https://hackage.haskell.org/package/hspec Hspec>--- 'H.Spec'. This returns the same tests as 'testSpec' but doesn't create--- a <https://hackage.haskell.org/package/tasty tasty> test group from them.+-- | Create a list of <https://hackage.haskell.org/package/tasty tasty> 'T.TestTree' from an+-- <https://hackage.haskell.org/package/hspec Hspec> 'H.Spec'. This returns the same tests as 'testSpec'+-- but doesn't create a <https://hackage.haskell.org/package/tasty tasty> test group from them. testSpecs :: H.Spec -> IO [T.TestTree]-testSpecs spec =- catMaybes . map specTreeToTestTree <$>- -- In hspec 2.6.0, "focus" was introduced. Here we do as hspec does, which- -- is pre-process a spec by focusing the whole thing, which is a no-op if- -- anything inside is already focused, but otherwise focuses every item.- -- Then, when creating a tasty test tree, we just toss the unfocused items.- H.runSpecM (doFocus spec)- where- doFocus :: H.Spec -> H.Spec- doFocus =-#if MIN_VERSION_hspec(2,6,0)- H.focus-#else- id-#endif+testSpecs spec = do+ -- Here we do as hspec does, which is pre-process a spec by focusing the whole thing, which is a no-op if+ -- anything inside is already focused, but otherwise focuses every item. Then, when creating a tasty test tree,+ -- we just toss the unfocused items.+ trees <- H.runSpecM (focus spec)+ pure (mapMaybe specTreeToTestTree trees) specTreeToTestTree :: H.SpecTree () -> Maybe T.TestTree-specTreeToTestTree spec_tree =- case spec_tree of- H.Node name spec_trees ->- Just (T.testGroup name (mapMaybe specTreeToTestTree spec_trees))- H.NodeWithCleanup cleanup spec_trees ->- T.WithResource (T.ResourceSpec (return ()) cleanup) . const <$> test_tree- where- test_tree :: Maybe T.TestTree- test_tree = specTreeToTestTree (H.Node "(unnamed)" spec_trees)- H.Leaf item -> do- guard (hspecItemIsFocused item)- Just (T.singleTest (H.itemRequirement item) (Item item))+specTreeToTestTree = \case+ Node name trees -> pure (T.testGroup name (mapMaybe specTreeToTestTree trees))+ NodeWithCleanup cleanup trees -> do+ tree <- specTreeToTestTree (H.Node "(unnamed)" trees)+ pure (T.WithResource (T.ResourceSpec (return ()) cleanup) (const tree))+ Leaf item -> do+ guard (itemIsFocused item)+ pure (T.singleTest (H.itemRequirement item) (Item item)) newtype Item = Item (H.Item ())- deriving Typeable+ deriving (Typeable) instance T.IsTest Item where- -- run :: T.OptionSet -> Item -> (T.Progress -> IO ()) -> IO T.Result run opts (Item item) progress = do- qc_args <- tastyOptionSetToQuickCheckArgs opts-- let- pending_ :: String -> T.Result- pending_ =- case T.lookupOption opts of- TreatPendingAsFailure -> T.testFailed- TreatPendingAsSuccess -> T.testPassed-- let- params :: H.Params- params = H.Params- { H.paramsQuickCheckArgs = qc_args- , H.paramsSmallCheckDepth = sc_depth- }--#if MIN_VERSION_hspec(2,4,0) && !MIN_VERSION_hspec(2,5,0)- either handleUncaughtException (hspecResultToTastyResult pending_)-#else- hspecResultToTastyResult pending_-#endif- <$> hspecItemToExample item params ($ ()) hprogress-- where- sc_depth :: Int- sc_depth =- case T.lookupOption opts of- TSC.SmallCheckDepth depth ->- depth+ qcArgs <- optionSetToQuickCheckArgs opts+ H.Result _ result <- itemExample item (params qcArgs) ($ ()) progress'+ pure+ ( case result of+ H.Success -> T.testPassed ""+ H.Pending _ reason ->+ case T.lookupOption opts of+ TreatPendingAsFailure -> T.testFailed reason'+ TreatPendingAsSuccess -> T.testPassed reason'+ where+ reason' = "# PENDING: " ++ fromMaybe "No reason given" reason+ H.Failure _ reason ->+ case reason of+ H.NoReason -> T.testFailed ""+ H.Reason x -> T.testFailed x+ H.ExpectedButGot preface expected actual ->+ T.testFailed . unlines . catMaybes $+ [ preface,+ Just ("expected: " ++ expected),+ Just (" but got: " ++ actual)+ ]+ H.Error _ exception -> T.testFailed ("uncaught exception: " ++ H.formatException exception)+ )+ where+ params qcArgs =+ H.Params+ { H.paramsQuickCheckArgs = qcArgs,+ H.paramsSmallCheckDepth =+ case T.lookupOption opts of+ TSC.SmallCheckDepth depth ->+ depth+ } - hprogress :: H.Progress -> IO ()- hprogress (x,y) =- progress T.Progress- { T.progressText = ""- , T.progressPercent = fromIntegral x / fromIntegral y- }+ progress' (x, y) =+ progress+ T.Progress+ { T.progressText = "",+ T.progressPercent = fromIntegral x / fromIntegral y+ } - -- testOptions :: Tagged Item [T.OptionDescription] testOptions =- return- [ T.Option (Proxy :: Proxy TreatPendingAs)- , T.Option (Proxy :: Proxy TQC.QuickCheckTests)- , T.Option (Proxy :: Proxy TQC.QuickCheckReplay)- , T.Option (Proxy :: Proxy TQC.QuickCheckMaxSize)- , T.Option (Proxy :: Proxy TQC.QuickCheckMaxRatio)- , T.Option (Proxy :: Proxy TSC.SmallCheckDepth)+ pure+ [ T.Option (Proxy :: Proxy TreatPendingAs),+ T.Option (Proxy :: Proxy TQC.QuickCheckTests),+ T.Option (Proxy :: Proxy TQC.QuickCheckReplay),+ T.Option (Proxy :: Proxy TQC.QuickCheckMaxSize),+ T.Option (Proxy :: Proxy TQC.QuickCheckMaxRatio),+ T.Option (Proxy :: Proxy TSC.SmallCheckDepth) ] -tastyOptionSetToQuickCheckArgs :: T.OptionSet -> IO QC.Args-tastyOptionSetToQuickCheckArgs opts =-#if MIN_VERSION_tasty_quickcheck(0,9,1)- snd <$> TQC.optionSetToArgs opts-#else- return QC.stdArgs- { QC.chatty = False- , QC.maxDiscardRatio = max_ratio- , QC.maxSize = max_size- , QC.maxSuccess = num_tests- , QC.replay = replay- }- where- TQC.QuickCheckTests num_tests = T.lookupOption opts- TQC.QuickCheckReplay replay = T.lookupOption opts- TQC.QuickCheckMaxSize max_size = T.lookupOption opts- TQC.QuickCheckMaxRatio max_ratio = T.lookupOption opts-#endif--hspecResultToTastyResult :: (String -> T.Result) -> H.Result -> T.Result-#if MIN_VERSION_hspec(2,5,0)-hspecResultToTastyResult pending_ (H.Result _ result) =-#else-hspecResultToTastyResult pending_ result =-#endif- case result of- H.Success ->- T.testPassed ""--#if MIN_VERSION_hspec(2,5,0)- H.Pending _ x ->-#else- H.Pending x ->-#endif- handleResultPending pending_ x--#if MIN_VERSION_hspec(2,4,0)- H.Failure _ x ->- handleResultFailure x-#elif MIN_VERSION_hspec(2,2,0)- H.Fail _ str -> T.testFailed str-#else- H.Fail str -> T.testFailed str-#endif--hspecItemIsFocused :: H.Item a -> Bool-hspecItemIsFocused =-#if MIN_VERSION_hspec(2,6,0)- H.itemIsFocused-#else- const True-#endif--hspecItemToExample- :: H.Item a- -> H.Params- -> (H.ActionWith a -> IO ())- -> H.ProgressCallback- -> IO H.Result-#if MIN_VERSION_hspec(2,6,0)-hspecItemToExample (H.Item _ _ _ _ ex) = ex-#else-hspecItemToExample (H.Item _ _ _ ex) = ex-#endif---handleResultPending :: (String -> T.Result) -> Maybe String -> T.Result-handleResultPending pending_ x =- pending_ ("# PENDING: " ++ fromMaybe "No reason given" x)---- FailureReason------ - Introduced in 2.4.0--- - Error constructor added in 2.5.0-#if MIN_VERSION_hspec(2,4,0)-handleResultFailure :: H.FailureReason -> T.Result-handleResultFailure reason =- case reason of- H.NoReason -> T.testFailed ""- H.Reason x -> T.testFailed x- H.ExpectedButGot preface expected actual ->- T.testFailed . unlines . catMaybes $- [ preface- , Just ("expected: " ++ expected)- , Just (" but got: " ++ actual)- ]-#if MIN_VERSION_hspec(2,5,0)- H.Error _ ex ->- handleUncaughtException ex-#endif-#endif--handleUncaughtException :: SomeException -> T.Result-handleUncaughtException ex =- T.testFailed ("uncaught exception: " ++ H.formatException ex)- -- | How to treat @hspec@ pending tests. -- -- @tasty@ does not have the concept of pending tests, so we must map them to@@ -285,11 +172,10 @@ defaultValue = TreatPendingAsFailure - parseValue s =- case s of- "failure" -> Just TreatPendingAsFailure- "success" -> Just TreatPendingAsSuccess- _ -> Nothing+ parseValue = \case+ "failure" -> Just TreatPendingAsFailure+ "success" -> Just TreatPendingAsSuccess+ _ -> Nothing optionName = pure "treat-pending-as"
+ src/Test/Tasty/Hspec/Compat.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE CPP #-}++module Test.Tasty.Hspec.Compat+ ( itemExample,+ itemIsFocused,+ focus,+ optionSetToQuickCheckArgs,++ pattern Leaf,+ pattern Node,+ pattern NodeWithCleanup,+ )+where++import qualified Test.Hspec as Hspec+import qualified Test.Hspec.Core.Spec as Hspec+import qualified Test.QuickCheck as QuickCheck+import qualified Test.Tasty.Options as Tasty+import qualified Test.Tasty.QuickCheck as Tasty.QuickCheck++{-# COMPLETE Leaf, Node, NodeWithCleanup #-}++pattern Leaf :: a -> Hspec.Tree c a+pattern Leaf item <-+ Hspec.Leaf item++pattern Node :: String -> [Hspec.Tree c a] -> Hspec.Tree c a+pattern Node name trees <-+ Hspec.Node name trees++pattern NodeWithCleanup :: c -> [Hspec.Tree c a] -> Hspec.Tree c a+pattern NodeWithCleanup cleanup trees <-+#if MIN_VERSION_hspec(2,8,0)+ Hspec.NodeWithCleanup _loc cleanup trees+#else+ Hspec.NodeWithCleanup cleanup trees+#endif++itemExample :: Hspec.Item a -> Hspec.Params -> (Hspec.ActionWith a -> IO ()) -> Hspec.ProgressCallback -> IO Hspec.Result+itemExample item =+ case item of+#if MIN_VERSION_hspec(2,6,0)+ Hspec.Item _ _ _ _ example -> example+#else+ Hspec.Item _ _ _ example -> example+#endif++itemIsFocused :: Hspec.Item a -> Bool+itemIsFocused =+#if MIN_VERSION_hspec(2,6,0)+ Hspec.itemIsFocused+#else+ const True+#endif++focus :: Hspec.Spec -> Hspec.Spec+focus =+#if MIN_VERSION_hspec(2,6,0)+ Hspec.focus+#else+ id+#endif++optionSetToQuickCheckArgs :: Tasty.OptionSet -> IO QuickCheck.Args+optionSetToQuickCheckArgs opts =+#if MIN_VERSION_tasty_quickcheck(0,9,1)+ snd <$> Tasty.QuickCheck.optionSetToArgs opts+#else+ pure+ QuickCheck.stdArgs+ { QuickCheck.chatty = False,+ QuickCheck.maxDiscardRatio = max_ratio,+ QuickCheck.maxSize = max_size,+ QuickCheck.maxSuccess = num_tests,+ QuickCheck.replay = replay+ }+ where+ Tasty.QuickCheck.QuickCheckTests num_tests = T.lookupOption opts+ Tasty.QuickCheck.QuickCheckReplay replay = T.lookupOption opts+ Tasty.QuickCheck.QuickCheckMaxSize max_size = T.lookupOption opts+ Tasty.QuickCheck.QuickCheckMaxRatio max_ratio = T.lookupOption opts+#endif+
tasty-hspec.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.0 name: tasty-hspec-version: 1.1.6+version: 1.1.7 synopsis: Hspec support for the Tasty test framework. description: This package provides a Tasty provider for Hspec test suites.@@ -25,45 +25,24 @@ location: https://github.com/mitchellwrosen/tasty-hspec.git library- exposed-modules: Test.Tasty.Hspec- hs-source-dirs: src- build-depends: base- ^>= 4.9- || ^>= 4.10- || ^>= 4.11- || ^>= 4.12- || ^>= 4.13- || ^>= 4.14- , hspec >= 2 && < 2.8- , hspec-core >= 2 && < 2.8- , QuickCheck- ^>= 2.7- || ^>= 2.8- || ^>= 2.9- || ^>= 2.10- || ^>= 2.11- || ^>= 2.12- || ^>= 2.13- || ^>= 2.14- , tasty- ^>= 0.8- || ^>= 0.9- || ^>= 0.10- || ^>= 0.11- || ^>= 0.12- || ^>= 1.0- || ^>= 1.1- || ^>= 1.2- || ^>= 1.3- || ^>= 1.4- , tasty-smallcheck >= 0.1 && < 0.9- -- 0.9 is missing 'optionSetToArgs'- , tasty-quickcheck >=0.3 && <0.9 || ^>=0.9.1 || ^>= 0.10+ build-depends:+ base ^>= 4.9 || ^>= 4.10 || ^>= 4.11 || ^>= 4.12 || ^>= 4.13 || ^>= 4.14 || ^>= 4.15,+ hspec >= 2.5 && < 2.9,+ hspec-core >= 2.5 && < 2.9,+ QuickCheck ^>= 2.7 || ^>= 2.8 || ^>= 2.9 || ^>= 2.10 || ^>= 2.11 || ^>= 2.12 || ^>= 2.13 || ^>= 2.14,+ tasty ^>= 0.8 || ^>= 0.9 || ^>= 0.10 || ^>= 0.11 || ^>= 0.12 || ^>= 1.0 || ^>= 1.1 || ^>= 1.2 || ^>= 1.3 || ^>= 1.4,+ tasty-smallcheck >= 0.1 && < 0.9,+ -- 0.9 is missing 'optionSetToArgs'+ tasty-quickcheck >=0.3 && <0.9 || ^>=0.9.1 || ^>= 0.10 if impl(ghc < 7.8) build-depends: tagged >= 0.2- other-extensions: CPP- , DeriveDataTypeable- default-language: Haskell2010- ghc-options: -Wall+ default-extensions:+ LambdaCase+ PatternSynonyms+ default-language: Haskell2010+ exposed-modules: Test.Tasty.Hspec+ ghc-options: -Wall if impl(ghc >= 8.0)- ghc-options: -Wcompat+ ghc-options: -Wcompat+ hs-source-dirs: src+ other-modules: Test.Tasty.Hspec.Compat