tasty-rerun 1.0.1 → 1.1.0
raw patch · 3 files changed
+54/−67 lines, 3 files
Files
- Changelog.md +11/−0
- src/Test/Tasty/Ingredients/Rerun.hs +41/−66
- tasty-rerun.cabal +2/−1
Changelog.md view
@@ -1,3 +1,14 @@+# 1.1.0++* The `TestTree` is filtered using a custom traversal now, rather than a+ `TreeFold`. This gives better guarantees that the `TestTree` is only+ reduced and that nodes (such as `WithResources`) continue to work. The+ resulting filtered `TestTree` now has the same shape as the original+ tree, but filtered tests are transformed into `TestGroup`s with no tests.+ This is a fairly major change to how the filtering is performed, so this+ is a new major release, and previous versions are now considered+ deprecated.+ # 1.0.1 * Now supports filtering `TestTree`s that use resources.
src/Test/Tasty/Ingredients/Rerun.hs view
@@ -5,8 +5,7 @@ import Control.Applicative import Control.Arrow ((>>>))-import Control.Exception (throwIO)-import Control.Monad (guard, when)+import Control.Monad (when) import Control.Monad.Trans.Class (lift) import Data.Char (isSpace) import Data.Foldable (asum)@@ -26,7 +25,6 @@ import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Options.Applicative as OptParse-import qualified Test.Tasty as Tasty import qualified Test.Tasty.Options as Tasty import qualified Test.Tasty.Providers as Tasty import qualified Test.Tasty.Runners as Tasty@@ -119,44 +117,35 @@ let UpdateLog updateLog = Tasty.lookupOption options let FilterOption filter = Tasty.lookupOption options - testTree' <- maybe (Just testTree) (filterTestTree options testTree filter)- <$> tryLoadStateFrom stateFile-- case testTree' of- -- We filtered the test tree down to 0 tests- Nothing -> return True-- -- There are tests to run so we try and find an Ingredient to run the- -- tests- Just filteredTestTree -> do- let tryAndRun (Tasty.TestReporter _ f) = do- runner <- f options filteredTestTree- return $ do- statusMap <- Tasty.launchTestTree options filteredTestTree- let getTestResults =- fmap getConst $- flip State.evalStateT 0 $- Functor.getCompose $- getTraversal $- Tasty.foldTestTree (observeResults statusMap)- options filteredTestTree- outcome <- runner statusMap- when updateLog (saveStateTo stateFile getTestResults)- return outcome-- tryAndRun (Tasty.TestManager _ f) =- f options filteredTestTree+ filteredTestTree <- maybe testTree (filterTestTree testTree filter)+ <$> tryLoadStateFrom stateFile - case asum (map tryAndRun ingredients) of- -- No Ingredients chose to run the tests, we should really return- -- Nothing, but we've already commited to run by the act of- -- filtering the TestTree.- Nothing -> return False+ let tryAndRun (Tasty.TestReporter _ f) = do+ runner <- f options filteredTestTree+ return $ do+ statusMap <- Tasty.launchTestTree options filteredTestTree+ let getTestResults =+ fmap getConst $+ flip State.evalStateT 0 $+ Functor.getCompose $+ getTraversal $+ Tasty.foldTestTree (observeResults statusMap)+ options filteredTestTree+ outcome <- runner statusMap+ when updateLog (saveStateTo stateFile getTestResults)+ return outcome - -- Otherwise, an Ingredient did choose to run the tests, so we- -- simply run the above constructed IO action.- Just e -> e+ tryAndRun (Tasty.TestManager _ f) =+ f options filteredTestTree + case asum (map tryAndRun ingredients) of+ -- No Ingredients chose to run the tests, we should really return+ -- Nothing, but we've already commited to run by the act of+ -- filtering the TestTree.+ Nothing -> return False+ -- Otherwise, an Ingredient did choose to run the tests, so we+ -- simply run the above constructed IO action.+ Just e -> e where existingOptions = flip concatMap ingredients $ \ingredient -> case ingredient of@@ -169,45 +158,31 @@ ] ------------------------------------------------------------------------------- filterTestTree options testTree filter lastRecord =- let foldSingle _ name t = \prefix ->+ filterTestTree testTree filter lastRecord =+ let go prefix (Tasty.SingleTest name t) = let requiredFilter = case Map.lookup (prefix ++ [name]) lastRecord of Just (Completed False) -> Failures Just ThrewException -> Exceptions Just (Completed True) -> Successful Nothing -> New-- in do guard (requiredFilter `Set.member` filter)- return (Tasty.SingleTest name t)+ in if (requiredFilter `Set.member` filter)+ then Tasty.SingleTest name t+ else Tasty.TestGroup "" [] - foldGroup name tests = \prefix ->- [ Tasty.testGroup name (tests (prefix ++ [name])) ]+ go prefix (Tasty.TestGroup name tests) =+ Tasty.TestGroup name (go (prefix ++ [name]) <$> tests) - foldResource rSpec k = \prefix ->- let peek = k (error "Resources unavailable during test tree filtering")- in case peek prefix of- [x] -> [ Tasty.WithResource rSpec (\io -> head $ k io prefix) ]- [] -> []- _ -> error "Resource claims to initialize multiple tests. \- \Please report this as a bug."+ go prefix (Tasty.PlusTestOptions f t) =+ Tasty.PlusTestOptions f (go prefix t) - treeFold = Tasty.TreeFold { Tasty.foldSingle = foldSingle- , Tasty.foldGroup = foldGroup- , Tasty.foldResource = foldResource- }+ go prefix (Tasty.WithResource rSpec k) =+ Tasty.WithResource rSpec (go prefix <$> k) - in case Tasty.foldTestTree treeFold options testTree [] of- [t] -> Just t- [] -> Nothing+ go prefix (Tasty.AskOptions k) =+ Tasty.AskOptions (go prefix <$> k) - -- This state is impossible as a TestTree is either a single test- -- or a test group. Test groups are folded into a single list element- -- and single tests to 0-or-1. Thus I believe this state is impossible.- _ ->- error "tasty-rerun found multiple tests when one was expected. \- \If you can produce this error, please report this as a bug!"+ in go [] testTree - ------------------------------------------------------------------------------ tryLoadStateFrom filePath = do fileContents <- (Just <$> readFile filePath) `catchIOError` (\e -> if isDoesNotExistError e
tasty-rerun.cabal view
@@ -1,5 +1,5 @@ name: tasty-rerun-version: 1.0.1+version: 1.1.0 homepage: http://github.com/ocharles/tasty-rerun license: BSD3 license-file: LICENSE@@ -84,3 +84,4 @@ transformers >= 0.3.0.0 hs-source-dirs: src default-language: Haskell2010+ ghc-options: -Wall