packages feed

tasty-silver 3.1.5 → 3.1.6

raw patch · 5 files changed

+118/−67 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Test.Tasty.Silver.Interactive: instance IsOption ExcludeFilters
- Test.Tasty.Silver.Interactive: instance IsOption IncludeFilters
- Test.Tasty.Silver.Interactive: instance Typeable ExcludeFilters
- Test.Tasty.Silver.Interactive: instance Typeable IncludeFilters
- Test.Tasty.Silver.Interactive: instance Typeable RegexFilter
+ Test.Tasty.Silver.Filter: ExcludeFilters :: [RegexFilter] -> ExcludeFilters
+ Test.Tasty.Silver.Filter: IncludeFilters :: [RegexFilter] -> IncludeFilters
+ Test.Tasty.Silver.Filter: RFExclude :: String -> RegexFilter
+ Test.Tasty.Silver.Filter: RFInclude :: String -> RegexFilter
+ Test.Tasty.Silver.Filter: data RegexFilter
+ Test.Tasty.Silver.Filter: filterWithRegex :: OptionSet -> TestTree -> TestTree
+ Test.Tasty.Silver.Filter: filterWithRegex1 :: OptionSet -> TestTree -> RegexFilter -> TestTree
+ Test.Tasty.Silver.Filter: instance IsOption ExcludeFilters
+ Test.Tasty.Silver.Filter: instance IsOption IncludeFilters
+ Test.Tasty.Silver.Filter: instance Typeable ExcludeFilters
+ Test.Tasty.Silver.Filter: instance Typeable IncludeFilters
+ Test.Tasty.Silver.Filter: instance Typeable RegexFilter
+ Test.Tasty.Silver.Filter: newtype ExcludeFilters
+ Test.Tasty.Silver.Filter: newtype IncludeFilters

Files

CHANGELOG.md view
@@ -1,6 +1,12 @@ Changes ======= +Version 3.1.6+-------------++* Expose regex filter modules.+* Fix issue with regex filters when used together with withResource nodes.+ Version 3.1.5 ------------- 
+ Test/Tasty/Silver/Filter.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE GeneralizedNewtypeDeriving, PatternGuards, DeriveDataTypeable #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+-- | Regex filtering for test trees.+module Test.Tasty.Silver.Filter+  ( filterWithRegex+  , filterWithRegex1+  , RegexFilter (..)+  , IncludeFilters (..)+  , ExcludeFilters (..)+  )+  where++import Prelude hiding (fail)+import Test.Tasty hiding (defaultMain)+import Test.Tasty.Runners+import Test.Tasty.Options+import Data.Tagged+import Data.Typeable+import Data.Maybe+import Data.Monoid+#if __GLASGOW_HASKELL__ < 708+import Data.Foldable (foldMap)+#endif+#if __GLASGOW_HASKELL__ < 708+import Data.Proxy+#endif+import Options.Applicative+import qualified Text.Regex.TDFA.String as RS+import qualified Text.Regex.TDFA as R++-- we have to store the regex as String, as there is no Typeable instance+-- for the Regex data type with GHC < 7.8+data RegexFilter+  = RFInclude String -- include tests that match+  | RFExclude String -- exclude tests that match+  deriving (Typeable)++newtype ExcludeFilters = ExcludeFilters [RegexFilter]+  deriving (Typeable)++newtype IncludeFilters = IncludeFilters [RegexFilter]+  deriving (Typeable)++compileRegex :: String -> Maybe RS.Regex+compileRegex = either (const Nothing) Just . RS.compile R.defaultCompOpt R.defaultExecOpt++parseFilter :: forall v . IsOption v => (String -> RegexFilter) -> ([RegexFilter] -> v) -> Parser v+parseFilter mkRF mkV = mkV <$> many ( option parse ( long name <> help helpString))+  where+    name = untag (optionName :: Tagged v String)+    helpString = untag (optionHelp :: Tagged v String)+    parse = (str >>=+        either (\err -> readerError $ "Could not parse " ++ name ++ ": " ++ err) (\_ -> mkRF <$> str)+        <$> RS.compile R.defaultCompOpt R.defaultExecOpt)++parseValue1 :: (String -> RegexFilter) -> String -> Maybe [RegexFilter]+parseValue1 f x = fmap (const $ [f x]) $ compileRegex x++instance IsOption ExcludeFilters where+  defaultValue = ExcludeFilters []+  parseValue = fmap ExcludeFilters . parseValue1 RFExclude+  optionName = return "regex-exclude"+  optionHelp = return "Exclude tests matching a regex (experimental)."+  optionCLParser = parseFilter RFExclude ExcludeFilters++instance IsOption IncludeFilters where+  defaultValue = IncludeFilters []+  parseValue = fmap IncludeFilters . parseValue1 RFInclude+  optionName = return "regex-include"+  optionHelp = return "Include only tests matching a regex (experimental)."+  optionCLParser = parseFilter RFInclude IncludeFilters+++filterWithRegex :: OptionSet -> TestTree -> TestTree+filterWithRegex opts tree = foldl (filterWithRegex1 opts) tree (excRgxs ++ incRgxs)+  where ExcludeFilters excRgxs = lookupOption opts+        IncludeFilters incRgxs = lookupOption opts+++filterWithRegex1 :: OptionSet -> TestTree -> RegexFilter -> TestTree+filterWithRegex1 _ tree rf = fromMaybe emptyTest (filter' "/" tree)+  where x <//> y = x ++ "/" ++ y++        prd = case rf of+            RFInclude rgx -> R.matchTest (fromJust $ compileRegex rgx)+            RFExclude rgx -> not . R.matchTest (fromJust $ compileRegex rgx)++        filter' :: String -> TestTree -> Maybe TestTree+        filter' pth (SingleTest n t) = if prd (pth <//> n) then Just $ SingleTest n t else Nothing+        filter' pth (TestGroup n ts) = if prd pth' then Just $ TestGroup n (catMaybes $ map (filter' pth') ts) else Nothing+          where pth' = pth <//> n+        filter' pth (PlusTestOptions o t) = PlusTestOptions o <$> filter' pth t+        -- we don't know at tree construction time what the tree wrapped inside an AskOptions/WithResource+        -- is going to look like. We always return something, and just return an empty test group+        -- if later on we see that the child subtree was excluded.+        filter' pth (WithResource r t) = Just $ WithResource r (\x -> fromMaybe emptyTest (filter' pth (t x)))+        filter' pth (AskOptions t) = Just $ AskOptions (\o -> fromMaybe emptyTest (filter' pth (t o)))++        emptyTest = testGroup "" []+
Test/Tasty/Silver/Interactive.hs view
@@ -25,6 +25,7 @@ import Test.Tasty hiding (defaultMain) import Test.Tasty.Runners import Test.Tasty.Options+import Test.Tasty.Silver.Filter import Test.Tasty.Silver.Internal import Test.Tasty.Silver.Interactive.Run import Data.Typeable@@ -60,8 +61,8 @@ import qualified Data.Map as M import System.Console.ANSI import qualified System.Process.Text as PTL-import qualified Text.Regex.TDFA.String as RS-import qualified Text.Regex.TDFA as R++ -- | Like @defaultMain@ from the main tasty package, but also includes the -- golden test management capabilities. defaultMain :: TestTree -> IO ()@@ -76,48 +77,7 @@   optionHelp = return "Run tests in interactive mode."   optionCLParser = flagCLParser (Just 'i') (Interactive True) --- we have to store the regex as String, as there is no Typeable instance--- for the Regex data type with GHC < 7.8-data RegexFilter-  = RFInclude String -- include tests that match-  | RFExclude String -- exclude tests that match-  deriving (Typeable) -newtype ExcludeFilters = ExcludeFilters [RegexFilter]-  deriving (Typeable)--newtype IncludeFilters = IncludeFilters [RegexFilter]-  deriving (Typeable)--compileRegex :: String -> Maybe RS.Regex-compileRegex = either (const Nothing) Just . RS.compile R.defaultCompOpt R.defaultExecOpt--parseFilter :: forall v . IsOption v => (String -> RegexFilter) -> ([RegexFilter] -> v) -> Parser v-parseFilter mkRF mkV = mkV <$> many ( option parse ( long name <> help helpString))-  where-    name = untag (optionName :: Tagged v String)-    helpString = untag (optionHelp :: Tagged v String)-    parse = (str >>=-        either (\err -> readerError $ "Could not parse " ++ name ++ ": " ++ err) (\_ -> mkRF <$> str)-        <$> RS.compile R.defaultCompOpt R.defaultExecOpt)--parseValue1 :: (String -> RegexFilter) -> String -> Maybe [RegexFilter]-parseValue1 f x = fmap (const $ [f x]) $ compileRegex x--instance IsOption ExcludeFilters where-  defaultValue = ExcludeFilters []-  parseValue = fmap ExcludeFilters . parseValue1 RFExclude-  optionName = return "regex-exclude"-  optionHelp = return "Exclude tests matching a regex (experimental)."-  optionCLParser = parseFilter RFExclude ExcludeFilters--instance IsOption IncludeFilters where-  defaultValue = IncludeFilters []-  parseValue = fmap IncludeFilters . parseValue1 RFInclude-  optionName = return "regex-include"-  optionHelp = return "Include only tests matching a regex (experimental)."-  optionCLParser = parseFilter RFInclude IncludeFilters- data ResultStatus = RPass | RFail | RMismatch GoldenResultI  type GoldenStatus = GoldenResultI@@ -135,28 +95,6 @@     ] $   \opts tree ->       Just $ runTestsInteractive opts (filterWithRegex opts tree)--filterWithRegex :: OptionSet -> TestTree -> TestTree-filterWithRegex opts tree = foldl (filterWithRegex1 opts) tree (excRgxs ++ incRgxs)-  where ExcludeFilters excRgxs = lookupOption opts-        IncludeFilters incRgxs = lookupOption opts---filterWithRegex1 :: OptionSet -> TestTree -> RegexFilter -> TestTree-filterWithRegex1 opts tree rf = case rf of-    RFInclude rgx -> filter' (R.matchTest (fromJust $ compileRegex rgx))-    RFExclude rgx -> filter' (not . R.matchTest (fromJust $ compileRegex rgx))-  where x <//> y = x ++ "/" ++ y-        filter' :: (String -> Bool) -> TestTree-        filter' pred' =-            let alg :: TreeFold [String -> Maybe TestTree]-                alg = trivialFold-                    { foldSingle = \_ nm t -> [\pth -> if pred' (pth <//> nm) then Just (SingleTest nm t) else Nothing]-                    , foldGroup  = \nm chlds -> [\pth -> Just $ TestGroup nm (catMaybes $ map (\x -> x (pth <//> nm)) chlds)]-                    }-                [root] = foldTestTree alg opts tree-             in maybe (testGroup "" []) (id) (root "")-  runSingleTest ::  IsTest t => GoldenStatusMap -> TestName -> OptionSet -> t -> (Progress -> IO ()) -> IO Result runSingleTest gs n opts t cb = do
tasty-silver.cabal view
@@ -1,5 +1,5 @@ name:                tasty-silver-version:             3.1.5+version:             3.1.6 synopsis:            Golden tests support for tasty. Fork of tasty-golden. description:   This package provides support for «golden testing».@@ -29,6 +29,7 @@     Haskell2010   exposed-modules:     Test.Tasty.Silver                        Test.Tasty.Silver.Advanced+                       Test.Tasty.Silver.Filter                        Test.Tasty.Silver.Interactive                        Test.Tasty.Silver.Interactive.Run                        Test.Tasty.Silver.Internal
tests/test.hs view
@@ -14,6 +14,7 @@ import Data.List (sort) import Control.Concurrent.MVar import Control.Monad.IO.Class+import Control.Concurrent  touch f = writeFile f "" @@ -49,7 +50,7 @@         free v = swapMVar v False >> return ()         test = \v -> goldenTest1 "check res" (return Nothing) (liftIO $ testAction v) (\_ _ -> Equal) (\_ -> ShowText mempty) upd         upd x = assertBool "Incorrect result" x >> return ()-        testAction = \v -> v >>= readMVar >>= assertBool "Resource not initialized." >> return True+        testAction = \v -> v >>= readMVar >>= assertBool "Resource not initialized." >> threadDelay 10000000 >> return True         tree = withResource acq free test      let r = tryIngredients [consoleTestReporter] (singleOption $ AcceptTests True) tree