packages feed

tasty-autocollect 0.2.0.0 → 0.3.0.0

raw patch · 12 files changed

+351/−64 lines, 12 filesdep +tasty-expected-failurePVP ok

version bump matches the API change (PVP)

Dependencies added: tasty-expected-failure

API changes (from Hackage documentation)

+ Test.Tasty.AutoCollect.ConvertTest: instance GHC.Classes.Eq Test.Tasty.AutoCollect.ConvertTest.TestModifier
+ Test.Tasty.AutoCollect.ConvertTest: instance GHC.Show.Show Test.Tasty.AutoCollect.ConvertTest.TestModifier
+ Test.Tasty.AutoCollect.ExternalNames: [name_expectFailBecause] :: ExternalNames -> Name
+ Test.Tasty.AutoCollect.ExternalNames: [name_expectFail] :: ExternalNames -> Name
+ Test.Tasty.AutoCollect.ExternalNames: [name_ignoreTestBecause] :: ExternalNames -> Name
+ Test.Tasty.AutoCollect.ExternalNames: [name_ignoreTest] :: ExternalNames -> Name
+ Test.Tasty.AutoCollect.ExternalNames: [name_map] :: ExternalNames -> Name
- Test.Tasty.AutoCollect.ExternalNames: ExternalNames :: Name -> Name -> Name -> Name -> ExternalNames
+ Test.Tasty.AutoCollect.ExternalNames: ExternalNames :: Name -> Name -> Name -> Name -> Name -> Name -> Name -> Name -> Name -> ExternalNames

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Unreleased +# v0.3.0.0++* Fix bug when omitting signature after specifying a signature for a prior test+* Add support for `_expectFail`, `_expectFailBecause`, `_ignoreTest`, `_ignoreTestBecause` suffixes+ # v0.2.0.0  * Fix build for GHC 8.10.2
README.md view
@@ -25,6 +25,9 @@         build-tools:           - tasty-autocollect:tasty-autocollect         ...+        dependencies:+          - tasty-autocollect+          - ...     ```     ```cabal     test-suite my-library-tests@@ -32,6 +35,9 @@       build-tool-depends:         tasty-autocollect:tasty-autocollect       ...+      build-depends:+        tasty-autocollect+        ...     ```  1. Write your main file to contain just:@@ -58,6 +64,8 @@         1 + 1 @?= (2 :: Int)         2 + 2 @?= (4 :: Int) +    -- See the "Integration with QuickCheck/SmallCheck/etc." section+    -- for a more seamless integration     test =       testProperty "reverse . reverse === id" $ \xs ->         (reverse . reverse) xs === id (xs :: [Int])@@ -194,6 +202,41 @@ test = testCase "test #5" $ return ()  test = testCase "test #10" $ return ()+```++### Integration with `tasty-expected-failures`++If you need to mark a test as an expected failure or just unconditionally skip a test, you can add an appropriate suffix to your test. For example:++```hs+test_expectFail = testCase "this test should fail" $ ...++test_expectFailBecause "Issue #123" = testCase "this test should fail" $ ...++test_ignoreTest = testCase "this test is skipped" $ ...++test_ignoreTestBecause "Issue #123" = testCase "this test is skipped" $ ...+```++The last example will be converted into the equivalent of:++```hs+tasty_test_4 :: TestTree+tasty_test_4 =+  ignoreTestBecause "Issue #123" $+    testCase "this test is skipped" $ ...+```++It also works in combination with other test types, e.g. with `test_batch` to skip the entire batch of tests:++```hs+test_batch_expectFail =+  [ testCase ("this test should fail: " ++ show x) ...+  | x <- ...+  ]++test_prop_expectFailBecause :: Int -> Property+test_prop_expectFailBecause "Issue #123" "some property" x = x === x ```  ## Comparison with `tasty-discover`
src/Test/Tasty/AutoCollect/ConvertTest.hs view
@@ -1,17 +1,23 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-}  module Test.Tasty.AutoCollect.ConvertTest (   plugin, ) where -import Control.Monad (unless)+import Control.Arrow ((&&&))+import Control.Monad (unless, zipWithM) import Control.Monad.Trans.State.Strict (State) import qualified Control.Monad.Trans.State.Strict as State import Data.Foldable (toList)+import qualified Data.List.NonEmpty as NonEmpty+import Data.Maybe (isNothing) import Data.Sequence (Seq) import qualified Data.Sequence as Seq+import qualified Data.Text as Text  import Test.Tasty.AutoCollect.Constants import Test.Tasty.AutoCollect.Error@@ -91,7 +97,7 @@           ]      flattenTestList testsList =-      mkHsApp (lhsvar $ genLoc $ getRdrName $ name_concat names) $+      mkHsApp (mkHsVar $ name_concat names) $         mkExprTypeSig testsList . genLoc $           HsListTy noAnn (getListOfTestTreeType names) @@ -120,113 +126,155 @@     Just (FuncDef funcName funcDefs)       | Just testType <- parseTestType (fromRdrName funcName) -> do           mSigInfo <- getLastSeenSig-          concatMapM (convertSingleTest funcName testType mSigInfo . unLoc) funcDefs+          concat <$> zipWithM (convertSingleTest funcName testType) (mSigInfo : repeat Nothing) funcDefs     -- anything else leave unmodified     _ -> pure [ldecl]   where-    convertSingleTest funcName testType mSigInfo FuncSingleDef{..} = do-      (testName, mSigType, needsFuncSig) <-+    loc = getLocA ldecl++    convertSingleTest funcName testType mSigInfo (L _ FuncSingleDef{..}) = do+      (testName, mSigType) <-         case mSigInfo of           Nothing -> do             testName <- getNextTestName-            pure (testName, Nothing, True)+            pure (testName, Nothing)           Just SigInfo{testType = testTypeFromSig, ..}-            | testType == testTypeFromSig -> pure (testName, Just signatureType, False)+            | testType == testTypeFromSig -> pure (testName, Just signatureType)             | otherwise -> autocollectError $ "Found test with different type of signature: " ++ show (testType, testTypeFromSig) -      funcBody <-+      testBody <-         case funcDefGuards of-          [FuncGuardedBody [] body] -> pure body+          [FuncGuardedBody [] body] -> convertSingleTestBody testType mSigType funcDefArgs body           _ ->             autocollectError . unlines $               [ "Test should have no guards."-              , "Found guards at " ++ getSpanLine funcName+              , "Found guards at " ++ getSpanLine (getLocA funcName)               ] -      testBody <--        case testType of-          TestNormal -> do-            checkNoArgs testType funcDefArgs-            pure $ singleExpr funcBody-          TestProp -> do-            (name, remainingPats) <--              case funcDefArgs of-                [] -> autocollectError "test_prop requires at least the name of the test"-                L _ (LitPat _ (HsString _ s)) : rest -> return (unpackFS s, rest)-                arg : _ ->-                  autocollectError . unlines $-                    [ "test_prop expected a String for the name of the test."-                    , "Got: " ++ showPpr arg-                    ]-            let propBody = mkHsLam remainingPats funcBody-            pure . singleExpr $-              mkHsApps-                (lhsvar $ mkLRdrName "testProperty")-                [ genLoc $ HsLit noAnn $ mkHsString name-                , maybe propBody (genLoc . ExprWithTySig noAnn propBody) mSigType-                ]-          TestTodo -> do-            checkNoArgs testType funcDefArgs-            pure . singleExpr $-              mkHsApp-                (lhsvar $ genLoc $ getRdrName $ name_testTreeTodo names)-                (mkExprTypeSig funcBody $ mkHsTyVar (name_String names))-          TestBatch -> do-            checkNoArgs testType funcDefArgs-            pure funcBody-       pure . concat $-        [ if needsFuncSig+        [ if isNothing mSigInfo             then [genLoc $ genFuncSig testName (getListOfTestTreeType names)]             else []         , [genFuncDecl testName [] testBody (Just funcDefWhereClause) <$ ldecl]         ] +    convertSingleTestBody testType mSigType args body =+      case testType of+        TestNormal -> do+          checkNoArgs testType args+          pure $ singleExpr body+        TestProp -> do+          (name, remainingPats) <-+            case args of+              arg : rest | Just s <- parseLitStrPat arg -> return (s, rest)+              [] -> autocollectError "test_prop requires at least the name of the test"+              arg : _ ->+                autocollectError . unlines $+                  [ "test_prop expected a String for the name of the test."+                  , "Got: " ++ showPpr arg+                  ]+          let propBody = mkHsLam remainingPats body+          pure . singleExpr $+            mkHsApps+              (lhsvar $ mkLRdrName "testProperty")+              [ mkHsLitString name+              , maybe propBody (genLoc . ExprWithTySig noAnn propBody) mSigType+              ]+        TestTodo -> do+          checkNoArgs testType args+          pure . singleExpr $+            mkHsApp+              (mkHsVar $ name_testTreeTodo names)+              (mkExprTypeSig body $ mkHsTyVar (name_String names))+        TestBatch -> do+          checkNoArgs testType args+          pure body+        TestModify modifier testType' ->+          withTestModifier names modifier loc args $ \args' ->+            convertSingleTestBody testType' mSigType args' body+     singleExpr = genLoc . mkExplicitList . (: [])      checkNoArgs testType args =       unless (null args) $         autocollectError . unwords $           [ showTestType testType ++ " should not be used with arguments"-          , "(at " ++ getSpanLine ldecl ++ ")"+          , "(at " ++ getSpanLine loc ++ ")"           ]  -- | Identifier for the generated `tests` list. testListName :: LocatedN RdrName testListName = mkLRdrName testListIdentifier +-- | Return the `[TestTree]` type.+getListOfTestTreeType :: ExternalNames -> LHsType GhcPs+getListOfTestTreeType names = genLoc $ HsListTy noAnn $ mkHsTyVar (name_TestTree names)++{----- TestType -----}+ data TestType   = TestNormal   | TestProp   | TestTodo   | TestBatch+  | TestModify TestModifier TestType   deriving (Show, Eq) +data TestModifier+  = ExpectFail+  | ExpectFailBecause+  | IgnoreTest+  | IgnoreTestBecause+  deriving (Show, Eq)+ parseTestType :: String -> Maybe TestType-parseTestType = \case-  "test" -> Just TestNormal-  "test_prop" -> Just TestProp-  "test_todo" -> Just TestTodo-  "test_batch" -> Just TestBatch-  _ -> Nothing+parseTestType = go . Text.splitOn "_" . Text.pack+  where+    go = \case+      ["test"] -> Just TestNormal+      ["test", "prop"] -> Just TestProp+      ["test", "todo"] -> Just TestTodo+      ["test", "batch"] -> Just TestBatch+      (unsnoc -> Just (t, "expectFail")) -> TestModify ExpectFail <$> go t+      (unsnoc -> Just (t, "expectFailBecause")) -> TestModify ExpectFailBecause <$> go t+      (unsnoc -> Just (t, "ignoreTest")) -> TestModify IgnoreTest <$> go t+      (unsnoc -> Just (t, "ignoreTestBecause")) -> TestModify IgnoreTestBecause <$> go t+      _ -> Nothing +    unsnoc = fmap (NonEmpty.init &&& NonEmpty.last) . NonEmpty.nonEmpty+ showTestType :: TestType -> String showTestType = \case   TestNormal -> "test"   TestProp -> "test_prop"   TestTodo -> "test_todo"   TestBatch -> "test_batch"+  TestModify modifier tt -> showTestType tt ++ showModifier modifier+  where+    showModifier = \case+      ExpectFail -> "_expectFail"+      ExpectFailBecause -> "_expectFailBecause"+      IgnoreTest -> "_ignoreTest"+      IgnoreTestBecause -> "_ignoreTestBecause"  isValidForTestType :: ExternalNames -> TestType -> LHsSigWcType GhcPs -> Bool isValidForTestType names = \case-  TestNormal -> parsedTypeMatches $ isTypeVarNamed (name_TestTree names)+  TestNormal -> parsedTypeMatches isTestTreeTypeVar   TestProp -> const True   TestTodo -> parsedTypeMatches $ isTypeVarNamed (name_String names)   TestBatch -> parsedTypeMatches $ \case-    TypeList ty -> isTypeVarNamed (name_TestTree names) ty+    TypeList ty -> isTestTreeTypeVar ty     _ -> False+  TestModify modifier tt -> isValidForModifier tt modifier   where+    isValidForModifier tt = \case+      ExpectFail -> isValidForTestType names tt+      ExpectFailBecause -> isValidForTestType names tt+      IgnoreTest -> isValidForTestType names tt+      IgnoreTestBecause -> isValidForTestType names tt+     parsedTypeMatches f = maybe False f . parseSigWcType+    isTestTreeTypeVar = isTypeVarNamed (name_TestTree names)  typeForTestType :: TestType -> String typeForTestType = \case@@ -234,15 +282,57 @@   TestProp -> "(Testable prop => prop)"   TestTodo -> "String"   TestBatch -> "[TestTree]"+  TestModify modifier tt -> typeForTestModifier tt modifier+  where+    typeForTestModifier tt = \case+      ExpectFail -> typeForTestType tt+      ExpectFailBecause -> typeForTestType tt+      IgnoreTest -> typeForTestType tt+      IgnoreTestBecause -> typeForTestType tt  isTypeVarNamed :: Name -> ParsedType -> Bool isTypeVarNamed name = \case   TypeVar _ (L _ n) -> rdrNameOcc n == rdrNameOcc (getRdrName name)   _ -> False --- | Return the `[TestTree]` type.-getListOfTestTreeType :: ExternalNames -> LHsType GhcPs-getListOfTestTreeType names = genLoc $ HsListTy noAnn $ mkHsTyVar (name_TestTree names)+withTestModifier ::+  Monad m =>+  ExternalNames ->+  TestModifier ->+  SrcSpan ->+  [LPat GhcPs] ->+  ([LPat GhcPs] -> m (LHsExpr GhcPs)) ->+  m (LHsExpr GhcPs)+withTestModifier names modifier loc args f =+  case modifier of+    ExpectFail -> mapAllTests (mkHsVar $ name_expectFail names) <$> f args+    ExpectFailBecause ->+      case args of+        arg : rest+          | Just s <- parseLitStrPat arg ->+              mapAllTests (applyName (name_expectFailBecause names) [mkHsLitString s]) <$> f rest+        _ -> needsStrArg "_expectFailBecause"+    IgnoreTest -> mapAllTests (mkHsVar $ name_ignoreTest names) <$> f args+    IgnoreTestBecause ->+      case args of+        arg : rest+          | Just s <- parseLitStrPat arg ->+              mapAllTests (applyName (name_ignoreTestBecause names) [mkHsLitString s]) <$> f rest+        _ -> needsStrArg "_ignoreTestBecause"+  where+    needsStrArg label =+      autocollectError . unlines . concat $+        [ [label ++ " requires a String argument."]+        , case args of+            [] -> []+            arg : _ -> ["Got: " ++ showPpr arg]+        , ["At: " ++ getSpanLine loc]+        ]++    applyName name = mkHsApps (mkHsVar name)++    -- mapAllTests f e = [| map $f $e |]+    mapAllTests func expr = applyName (name_map names) [func, expr]  {----- Test converter monad -----} 
src/Test/Tasty/AutoCollect/ExternalNames.hs view
@@ -7,24 +7,35 @@ ) where  import Test.Tasty (TestTree)+import Test.Tasty.ExpectedFailure (expectFail, expectFailBecause, ignoreTest, ignoreTestBecause)  import Test.Tasty.AutoCollect.Error import Test.Tasty.AutoCollect.GHC import Test.Tasty.Ext.Todo (testTreeTodo)  data ExternalNames = ExternalNames-  { name_TestTree :: Name-  , name_testTreeTodo :: Name-  , name_String :: Name+  { name_String :: Name   , name_concat :: Name+  , name_map :: Name+  , name_TestTree :: Name+  , name_testTreeTodo :: Name+  , name_expectFail :: Name+  , name_expectFailBecause :: Name+  , name_ignoreTest :: Name+  , name_ignoreTestBecause :: Name   }  loadExternalNames :: HscEnv -> IO ExternalNames loadExternalNames env = do-  name_TestTree <- loadName ''TestTree-  name_testTreeTodo <- loadName 'testTreeTodo   name_String <- loadName ''String   name_concat <- loadName 'concat+  name_map <- loadName 'map+  name_TestTree <- loadName ''TestTree+  name_testTreeTodo <- loadName 'testTreeTodo+  name_expectFail <- loadName 'expectFail+  name_expectFailBecause <- loadName 'expectFailBecause+  name_ignoreTest <- loadName 'ignoreTest+  name_ignoreTestBecause <- loadName 'ignoreTestBecause   pure ExternalNames{..}   where     loadName name =
src/Test/Tasty/AutoCollect/GHC.hs view
@@ -7,13 +7,18 @@   -- * Output helpers   showPpr, +  -- * Parsers+  parseLitStrPat,+   -- * Builders   genFuncSig,   genFuncDecl,   lhsvar,+  mkHsVar,   mkHsAppTypes,   mkHsTyVar,   mkExprTypeSig,+  mkHsLitString,    -- * Located utilities   genLoc,@@ -42,6 +47,13 @@ showPpr :: Outputable a => a -> String showPpr = showSDocUnsafe . ppr +{----- Parsers ----}++parseLitStrPat :: LPat GhcPs -> Maybe String+parseLitStrPat = \case+  L _ (LitPat _ (HsString _ s)) -> Just (unpackFS s)+  _ -> Nothing+ {----- Builders -----}  genFuncSig :: LocatedN RdrName -> LHsType GhcPs -> HsDecl GhcPs@@ -63,6 +75,9 @@ lhsvar :: LocatedN RdrName -> LHsExpr GhcPs lhsvar = genLoc . HsVar NoExtField +mkHsVar :: Name -> LHsExpr GhcPs+mkHsVar = lhsvar . genLoc . getRdrName+ mkHsAppTypes :: LHsExpr GhcPs -> [LHsType GhcPs] -> LHsExpr GhcPs mkHsAppTypes = foldl' mkHsAppType @@ -72,12 +87,15 @@ mkHsTyVar :: Name -> LHsType GhcPs mkHsTyVar = genLoc . HsTyVar noAnn NotPromoted . genLoc . getRdrName --- | mkExprTypeSig <e> <t> = (<e> :: <t>)+-- | mkExprTypeSig e t = [| $e :: $t |] mkExprTypeSig :: LHsExpr GhcPs -> LHsType GhcPs -> LHsExpr GhcPs mkExprTypeSig e t =   genLoc . ExprWithTySig noAnn e $     HsWC NoExtField (hsTypeToHsSigType t) +mkHsLitString :: String -> LHsExpr GhcPs+mkHsLitString = genLoc . HsLit noAnn . mkHsString+ {----- Located utilities -----}  genLoc :: e -> GenLocated (SrcAnn ann) e@@ -86,9 +104,9 @@ firstLocatedWhere :: Ord l => (GenLocated l e -> Maybe a) -> [GenLocated l e] -> Maybe a firstLocatedWhere f = listToMaybe . mapMaybe f . sortOn getLoc -getSpanLine :: GenLocated (SrcSpanAnn' a) e -> String+getSpanLine :: SrcSpan -> String getSpanLine loc =-  case srcSpanStart $ getLocA loc of+  case srcSpanStart loc of     Right srcLoc -> "line " ++ show (srcLocLine srcLoc)     Left s -> s 
tasty-autocollect.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           tasty-autocollect-version:        0.2.0.0+version:        0.3.0.0 synopsis:       Autocollection of tasty tests. description:    Autocollection of tasty tests. See README.md for more details. category:       Testing@@ -26,7 +26,12 @@     test/golden/output_group_type_tree.golden     test/golden/test_args.golden     test/golden/test_batch_args.golden+    test/golden/test_batch_expectFailBecause_output.golden     test/golden/test_batch_type.golden+    test/golden/test_expectFail_output.golden+    test/golden/test_expectFailBecause_output.golden+    test/golden/test_ignoreTest_output.golden+    test/golden/test_ignoreTestBecause_output.golden     test/golden/test_prop_bad_arg.golden     test/golden/test_prop_no_args.golden     test/golden/test_todo_args.golden@@ -64,6 +69,7 @@     , filepath >=1.4.2.1 && <2     , ghc >=8.10 && <9.3     , tasty >=1.4.2.1 && <2+    , tasty-expected-failure >=0.11 && <1     , template-haskell >=2.16 && <2.19     , text >=1.2.3.2 && <3     , transformers >=0.5.6.2 && <1
test/Test/Tasty/AutoCollect/ConvertTestTest.hs view
@@ -153,6 +153,15 @@   getTestLines stdout @?~ containsStripped (eq "test 1: OK")   getTestLines stdout @?~ containsStripped (eq "test 2: OK") +test =+  testCase "tests may omit type after specifying a type prior" $+    assertSuccess_ . runQCTest $+      [ "test :: TestTree"+      , "test = testCase \"test 1\" $ return ()"+      , ""+      , "test = testCase \"test 2\" $ return ()"+      ]+ {----- test_batch -----}  test = testCase "test_batch generates multiple tests" $ do@@ -220,6 +229,15 @@       ]  test =+  testCase "test_prop may omit type after specifying a different type prior" $+    assertSuccess_ . runQCTest $+      [ "test_prop :: Property"+      , "test_prop \"test 1\" = 1 === 1"+      , ""+      , "test_prop \"test 2\" x = (x :: Int) === x"+      ]++test =   testCase "test_prop uses any 'testProperty' function in scope" $ do     (stdout, _) <-       assertSuccess . runTest $@@ -256,3 +274,57 @@  addQuickCheck :: GHCProject -> GHCProject addQuickCheck proj = proj{dependencies = "tasty-quickcheck" : dependencies proj}++{----- tasty-expected-failure integration -----}++test =+  testGolden "expectFail succeeds when test fails" "test_expectFail_output.golden" $ do+    (stdout, _) <-+      assertSuccess . runTest $+        [ "test_expectFail = testCase \"failing test\" $ 1 @?= 2"+        ]+    return (normalizeTestOutput stdout)++test =+  testGolden "expectFailBecause succeeds when test fails" "test_expectFailBecause_output.golden" $ do+    (stdout, _) <-+      assertSuccess . runTest $+        [ "test_expectFailBecause \"some reason\" = testCase \"failing test\" $ 1 @?= 2"+        ]+    return (normalizeTestOutput stdout)++test =+  testGolden "ignoreTest succeeds when test fails" "test_ignoreTest_output.golden" $ do+    (stdout, _) <-+      assertSuccess . runTest $+        [ "test_ignoreTest = testCase \"failing test\" $ 1 @?= 2"+        ]+    return (normalizeTestOutput stdout)++test =+  testGolden "ignoreTestBecause succeeds when test fails" "test_ignoreTestBecause_output.golden" $ do+    (stdout, _) <-+      assertSuccess . runTest $+        [ "test_ignoreTestBecause \"some reason\" = testCase \"failing test\" $ 1 @?= 2"+        ]+    return (normalizeTestOutput stdout)++test =+  testGolden "expected-failure modifiers work on test_batch" "test_batch_expectFailBecause_output.golden" $ do+    (stdout, _) <-+      assertAnyFailure . runTest $+        [ "test_batch_expectFailBecause \"some reason\" ="+        , "  [ testCase (\"failing test #\" ++ show x) $ x @?= 1"+        , "  | x <- [1 .. 3 :: Int]"+        , "  ]"+        ]+    return (normalizeTestOutput stdout)++test =+  testCase "expected-failure modifiers work on test_prop" $ do+    (stdout, _) <-+      assertSuccess . runQCTest $+        [ "test_prop_expectFailBecause :: [Int] -> Bool"+        , "test_prop_expectFailBecause \"some reason\" \"my property\" xs = length xs < 0"+        ]+    getTestLines stdout @?~ containsStripped (eq "my property: FAIL (expected: some reason)")
+ test/golden/test_batch_expectFailBecause_output.golden view
@@ -0,0 +1,15 @@+Main.hs+  Test+    failing test #1: OK (unexpected: some reason)+       (unexpected success: some reason)+      Use -p '/failing test #1/' to rerun this test only.+    failing test #2: FAIL (expected: some reason)+      ./Test.hs:6:+      expected: 1+       but got: 2 (expected failure)+    failing test #3: FAIL (expected: some reason)+      ./Test.hs:6:+      expected: 1+       but got: 3 (expected failure)++1 out of 3 tests failed
+ test/golden/test_expectFailBecause_output.golden view
@@ -0,0 +1,8 @@+Main.hs+  Test+    failing test: FAIL (expected: some reason)+      ./Test.hs:5:+      expected: 2+       but got: 1 (expected failure)++All 1 tests passed
+ test/golden/test_expectFail_output.golden view
@@ -0,0 +1,8 @@+Main.hs+  Test+    failing test: FAIL (expected)+      ./Test.hs:5:+      expected: 2+       but got: 1 (expected failure)++All 1 tests passed
+ test/golden/test_ignoreTestBecause_output.golden view
@@ -0,0 +1,6 @@+Main.hs+  Test+    failing test: IGNORED+      some reason++All 1 tests passed
+ test/golden/test_ignoreTest_output.golden view
@@ -0,0 +1,5 @@+Main.hs+  Test+    failing test: IGNORED++All 1 tests passed