packages feed

hspec-junit-formatter 1.1.1.0 → 1.1.2.0

raw patch · 16 files changed

+336/−210 lines, 16 files

Files

CHANGELOG.md view
@@ -1,4 +1,10 @@-## [_Unreleased_](https://github.com/freckle/hspec-junit-formatter/compare/v1.1.1.0...main)+## [_Unreleased_](https://github.com/freckle/hspec-junit-formatter/compare/v1.1.2.0...main)++## [v1.1.2.0](https://github.com/freckle/hspec-junit-formatter/compare/v1.1.1.0...v1.1.2.0)++- Replace the string `{base}` by the basename of the current directory+  (typically the package name) when reading any `JUNIT` environment variable+  values.  ## [v1.1.1.0](https://github.com/freckle/hspec-junit-formatter/compare/v1.1.0.2...v1.1.1.0) 
README.lhs view
@@ -108,8 +108,8 @@ ## Golden Testing  This project's test suite uses [hspec-golden][] to generate an XML report for-[`ExampleSpec.hs`](./tests/ExampleSpec.hs) and then compare that with golden XML-files checked into the repository. If your work changes things in a+[`Example.hs`](./tests/Example.hs) and then compare that with golden XML files+checked into the repository. If your work changes things in a functionally-correct way, but that diverges from the golden XML files, you need to regenerate them. 
README.md view
@@ -108,8 +108,8 @@ ## Golden Testing  This project's test suite uses [hspec-golden][] to generate an XML report for-[`ExampleSpec.hs`](./tests/ExampleSpec.hs) and then compare that with golden XML-files checked into the repository. If your work changes things in a+[`Example.hs`](./tests/Example.hs) and then compare that with golden XML files+checked into the repository. If your work changes things in a functionally-correct way, but that diverges from the golden XML files, you need to regenerate them. 
hspec-junit-formatter.cabal view
@@ -1,6 +1,6 @@ cabal-version:      1.18 name:               hspec-junit-formatter-version:            1.1.1.0+version:            1.1.2.0 license:            MIT license-file:       LICENSE copyright:          2021 Renaissance Learning Inc@@ -124,10 +124,13 @@  test-suite spec     type:               exitcode-stdio-1.0-    main-is:            Main.hs+    main-is:            Spec.hs     hs-source-dirs:     tests     other-modules:-        ExampleSpec+        Example+        SpecHook+        Test.Hspec.JUnit.Config.EnvSpec+        Test.Hspec.JUnit.FormatterSpec         Paths_hspec_junit_formatter      default-language:   Haskell2010
library/Test/Hspec/JUnit/Config/Env.hs view
@@ -2,14 +2,18 @@ module Test.Hspec.JUnit.Config.Env   ( envJUnitEnabled   , envJUnitConfig++    -- * Exported for testing+  , readJUnitConfig   ) where  import Prelude  import Data.Semigroup (Endo (..))-import Data.Text (pack)+import Data.Text (pack, unpack)+import qualified Data.Text as T import System.Directory (getCurrentDirectory)-import System.Environment (lookupEnv)+import System.Environment (getEnvironment, lookupEnv) import System.FilePath (takeBaseName) import Test.Hspec.JUnit.Config @@ -22,30 +26,39 @@ -- Variable names align with setter functions from "Test.Hspec.JUnit.Config": -- -- * @JUNIT_OUTPUT_DIRECTORY@ 'setJUnitConfigOutputDirectory'--- * @JUNIT_OUTPUT_NAME@ 'setJUnitConfigOutputName+-- * @JUNIT_OUTPUT_NAME@ 'setJUnitConfigOutputName' -- * and so on+--+-- Environment variable values will have the string @{base}@ replaced with the+-- basename of the current directory. This can be useful in a monorepository of+-- multiple packages, for example: @JUNIT_OUTPUT_FILE={base}.xml@ envJUnitConfig :: IO JUnitConfig envJUnitConfig = do-  modify <--    appEndo . foldMap Endo-      <$> sequence-        [ lookupEnvOverride "OUTPUT_DIRECTORY" setJUnitConfigOutputDirectory-        , lookupEnvOverride "OUTPUT_NAME" setJUnitConfigOutputName-        , lookupEnvOverride "OUTPUT_FILE" setJUnitConfigOutputFile-        , lookupEnvOverride "SUITE_NAME" $ setJUnitConfigSuiteName . pack-        , lookupEnvOverride "SOURCE_PATH_PREFIX" setJUnitConfigSourcePathPrefix-        , lookupEnvOverride "DROP_CONSOLE_FORMATTING" $+  env <- getEnvironment+  base <- takeBaseName <$> getCurrentDirectory+  pure $ readJUnitConfig base env++readJUnitConfig :: FilePath -> [(String, String)] -> JUnitConfig+readJUnitConfig base env = modify $ defaultJUnitConfig $ pack base+ where+  modify =+    appEndo $+      foldMap+        Endo+        [ readEnv "OUTPUT_DIRECTORY" setJUnitConfigOutputDirectory+        , readEnv "OUTPUT_NAME" setJUnitConfigOutputName+        , readEnv "OUTPUT_FILE" setJUnitConfigOutputFile+        , readEnv "SUITE_NAME" $ setJUnitConfigSuiteName . pack+        , readEnv "SOURCE_PATH_PREFIX" setJUnitConfigSourcePathPrefix+        , readEnv "DROP_CONSOLE_FORMATTING" $             setJUnitConfigDropConsoleFormatting . (== "1")         ] -  modify . defaultJUnitConfig . pack . takeBaseName <$> getCurrentDirectory--lookupEnvOverride-  :: String-  -> (String -> JUnitConfig -> JUnitConfig)-  -> IO (JUnitConfig -> JUnitConfig)-lookupEnvOverride name setter =-  maybe id setter <$> lookupEnv (envPrefix <> name)+  readEnv name setter =+    maybe id (setter . replaceBase base) $ lookup (envPrefix <> name) env  envPrefix :: String envPrefix = "JUNIT_"++replaceBase :: String -> String -> String+replaceBase base = unpack . T.replace "{base}" (pack base) . pack
+ tests/Example.hs view
@@ -0,0 +1,35 @@+-- | Example used by golden testing of XML reports+--+-- The path name and line numbers of this file are part of the golden report+-- being tested with. So if this file changes, they will need to be regenerated.+-- In fact, this sentence was added to retain them across a formatting change.+module Example (spec) where++import Control.Exception+import Prelude++import Test.Hspec++spec :: Spec+spec = do+  describe "Some section" $ do+    it "has an expectation" $ do+      True `shouldBe` True+    it "has a failure" $ do+      True `shouldBe` False++    context "A grouped context" $ do+      it "happens in a group" $ do+        True `shouldBe` True+      it "also happens in a group" $ do+        True `shouldBe` True+      it "gets skipped" $ do+        pendingWith "some reason"+      it "throws a colourful exception" $ do+        throwIO ColourfulException :: IO ()++data ColourfulException = ColourfulException+  deriving stock (Show)++instance Exception ColourfulException where+  displayException _ = "\x1b[32mColour\x1b[31mful\x1b[0mException"
− tests/ExampleSpec.hs
@@ -1,35 +0,0 @@--- | Example used by golden testing of XML reports------ The path name and line numbers of this file are part of the golden report--- being tested with. So if this file changes, they will need to be regenerated.--- In fact, this sentence was added to retain them across a formatting change.-module ExampleSpec (spec) where--import Control.Exception-import Prelude--import Test.Hspec--spec :: Spec-spec = do-  describe "Some section" $ do-    it "has an expectation" $ do-      True `shouldBe` True-    it "has a failure" $ do-      True `shouldBe` False--    context "A grouped context" $ do-      it "happens in a group" $ do-        True `shouldBe` True-      it "also happens in a group" $ do-        True `shouldBe` True-      it "gets skipped" $ do-        pendingWith "some reason"-      it "throws a colourful exception" $ do-        throwIO ColourfulException :: IO ()--data ColourfulException = ColourfulException-  deriving stock (Show)--instance Exception ColourfulException where-  displayException _ = "\x1b[32mColour\x1b[31mful\x1b[0mException"
− tests/Main.hs
@@ -1,120 +0,0 @@-{-# LANGUAGE CPP #-}--module Main-  ( main-  )-where--import Prelude--import Control.Monad (void)-import Data.Char (isSpace)-import qualified Data.Map.Strict as Map-import qualified Data.Text as T-import qualified ExampleSpec-import System.FilePath ((<.>), (</>))-import System.IO.Temp (withSystemTempDirectory)-import Test.Hspec-import Test.Hspec.Golden-import Test.Hspec.JUnit.Config-import qualified Test.Hspec.JUnit.Formatter as Formatter-import Test.Hspec.Runner-import qualified Text.XML as XML--main :: IO ()-main = hspec $ do-  describe "XML output" $ do-    it "matches golden file" $-      junitGolden "default" id--    it "matches golden file with prefixing" $-      junitGolden "prefixed" $-        setJUnitConfigSourcePathPrefix "lol/monorepo"---- | Run @ExampleSpec.spec@ and compare XML to a golden file-junitGolden-  :: String-  -- ^ Unique name-  -> (JUnitConfig -> JUnitConfig)-  -- ^ Any modification to make to the 'JUnitConfig' before running-  -> IO (Golden XML.Document)-junitGolden name modifyConfig = do-  actual <- withSystemTempDirectory "" $ \tmp -> do-    let junitConfig =-          modifyConfig $-            setJUnitConfigOutputDirectory tmp $-              setJUnitConfigOutputName "test.xml" $-                defaultJUnitConfig "hspec-junit-format"--    void $ runSpec' $ Formatter.use junitConfig ExampleSpec.spec-    readNormalizedXML $ tmp </> "test.xml"--  pure-    Golden-      { output = actual-      , encodePretty = show-      , writeToFile = XML.writeFile XML.def-      , readFromFile = readNormalizedXML-      , goldenFile =-          "tests" </> "golden" </> name <> "-" <> ghcSuffix <.> "xml"-      , actualFile = Nothing-      , failFirstTime = False-      }--runSpec' :: Spec -> IO ()-runSpec' spec = do-  (config, forest) <- evalSpec defaultConfig spec-  void $ runSpecForest forest config--readNormalizedXML :: FilePath -> IO XML.Document-readNormalizedXML = fmap normalizeDoc . XML.readFile XML.def--normalizeDoc :: XML.Document -> XML.Document-normalizeDoc = removeWhitespaceNodes . removeTimeAttributes--removeWhitespaceNodes :: XML.Document -> XML.Document-removeWhitespaceNodes doc =-  doc-    { XML.documentRoot = go $ XML.documentRoot doc-    }- where-  go el =-    el {XML.elementNodes = concatMap filterWhitespace $ XML.elementNodes el}--  filterWhitespace :: XML.Node -> [XML.Node]-  filterWhitespace = \case-    XML.NodeElement el -> [XML.NodeElement $ go el]-    XML.NodeContent c | T.all isSpace c -> []-    n -> [n]---- | Remove volatile attributes so they don't invalidate comparison-removeTimeAttributes :: XML.Document -> XML.Document-removeTimeAttributes =-  removeAttributesByName "time" . removeAttributesByName "timestamp"--removeAttributesByName :: XML.Name -> XML.Document -> XML.Document-removeAttributesByName name doc =-  doc-    { XML.documentRoot = go $ XML.documentRoot doc-    }- where-  go el =-    el-      { XML.elementAttributes = Map.delete name $ XML.elementAttributes el-      , XML.elementNodes = map (onNodeElement go) $ XML.elementNodes el-      }--  onNodeElement f = \case-    XML.NodeElement el -> XML.NodeElement $ f el-    n -> n---- GHC can change certain aspects, mainly about source-location, so we can--- incorpate that by tracking separate Golden files as necessary-ghcSuffix :: String-#if __GLASGOW_HASKELL__ >= 900-ghcSuffix = "ghc-9"-#elif __GLASGOW_HASKELL__ >= 800-ghcSuffix = "ghc-8"-#else--- Fail to compile on other GHCs-#endif
+ tests/Spec.hs view
@@ -0,0 +1,2 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+{-# OPTIONS_GHC -Wno-missing-export-lists #-}
+ tests/SpecHook.hs view
@@ -0,0 +1,9 @@+module SpecHook+  ( hook+  ) where++import Test.Hspec+import Test.Hspec.JUnit.Formatter.Env as Formatter++hook :: Spec -> Spec+hook = Formatter.whenEnabled Formatter.add
+ tests/Test/Hspec/JUnit/Config/EnvSpec.hs view
@@ -0,0 +1,95 @@+module Test.Hspec.JUnit.Config.EnvSpec+  ( spec+  ) where++import Prelude++import Test.Hspec+import Test.Hspec.JUnit.Config+import Test.Hspec.JUnit.Config.Env++spec :: Spec+spec = do+  describe "envJUnitConfig" $ do+    it "has sensible defaults" $ do+      let config = readJUnitConfig "base-directory" []++      getJUnitConfigOutputFile config `shouldBe` "./junit.xml"+      getJUnitConfigSuiteName config `shouldBe` "base-directory"+      getJUnitPrefixSourcePath config "path" `shouldBe` "path"+      getJUnitConfigDropConsoleFormatting config `shouldBe` False++    it "respects JUNIT_OUTPUT_DIRECTORY" $ do+      let config =+            readJUnitConfig+              "base-directory"+              [("JUNIT_OUTPUT_DIRECTORY", "/tmp")]++      getJUnitConfigOutputFile config `shouldBe` "/tmp/junit.xml"++    it "respects JUNIT_OUTPUT_NAME" $ do+      let config =+            readJUnitConfig+              "base-directory"+              [("JUNIT_OUTPUT_NAME", "report.xml")]++      getJUnitConfigOutputFile config `shouldBe` "./report.xml"++    it "respects JUNIT_OUTPUT_FILE" $ do+      let config =+            readJUnitConfig+              "base-directory"+              [ ("JUNIT_OUTPUT_DIRECTORY", "/home")+              , ("JUNIT_OUTPUT_NAME", "results.xml")+              , ("JUNIT_OUTPUT_FILE", "/tmp/report.xml")+              ]++      getJUnitConfigOutputFile config `shouldBe` "/tmp/report.xml"++    it "respects JUNIT_SUITE_NAME" $ do+      let config =+            readJUnitConfig+              "base-directory"+              [("JUNIT_SUITE_NAME", "hspec")]++      getJUnitConfigSuiteName config `shouldBe` "hspec"++    it "respects JUNIT_SOURCE_PATH_PREFIX" $ do+      let config =+            readJUnitConfig+              "base-directory"+              [("JUNIT_SOURCE_PATH_PREFIX", "package")]++      getJUnitPrefixSourcePath config "path" `shouldBe` "package/path"++    it "handles trailing-slash in JUNIT_SOURCE_PATH_PREFIX" $ do+      let config =+            readJUnitConfig+              "base-directory"+              [("JUNIT_SOURCE_PATH_PREFIX", "package/")]++      getJUnitPrefixSourcePath config "path" `shouldBe` "package/path"++    it "respects JUNIT_DROP_CONSOLE_FORMATTING" $ do+      let+        config1 =+          readJUnitConfig+            "base-directory"+            [("JUNIT_DROP_CONSOLE_FORMATTING", "1")]+        config0 =+          readJUnitConfig+            "base-directory"+            [("JUNIT_DROP_CONSOLE_FORMATTING", "0")]++      getJUnitConfigDropConsoleFormatting config1 `shouldBe` True+      getJUnitConfigDropConsoleFormatting config0 `shouldBe` False++    it "interpolates {base}" $ do+      let config =+            readJUnitConfig+              "some-package"+              [ ("JUNIT_OUTPUT_FILE", "{base}/test_results.xml")+              ]++      getJUnitConfigOutputFile config+        `shouldBe` "some-package/test_results.xml"
+ tests/Test/Hspec/JUnit/FormatterSpec.hs view
@@ -0,0 +1,118 @@+{-# LANGUAGE CPP #-}++module Test.Hspec.JUnit.FormatterSpec+  ( spec+  ) where++import Prelude++import Control.Monad (void)+import Data.Char (isSpace)+import qualified Data.Map.Strict as Map+import qualified Data.Text as T+import qualified Example+import System.FilePath ((<.>), (</>))+import System.IO.Temp (withSystemTempDirectory)+import Test.Hspec+import Test.Hspec.Golden+import Test.Hspec.JUnit.Config+import qualified Test.Hspec.JUnit.Formatter as Formatter+import Test.Hspec.Runner+import qualified Text.XML as XML++spec :: Spec+spec = do+  it "matches golden file" $+    junitGolden "default" id++  it "matches golden file with prefixing" $+    junitGolden "prefixed" $+      setJUnitConfigSourcePathPrefix "lol/monorepo"++-- | Run @Example.spec@ and compare XML to a golden file+junitGolden+  :: String+  -- ^ Unique name+  -> (JUnitConfig -> JUnitConfig)+  -- ^ Any modification to make to the 'JUnitConfig' before running+  -> IO (Golden XML.Document)+junitGolden name modifyConfig = do+  actual <- withSystemTempDirectory "" $ \tmp -> do+    let junitConfig =+          modifyConfig $+            setJUnitConfigOutputDirectory tmp $+              setJUnitConfigOutputName "test.xml" $+                defaultJUnitConfig "hspec-junit-format"++    runSpec' $ Formatter.use junitConfig Example.spec+    readNormalizedXML $ tmp </> "test.xml"++  pure+    Golden+      { output = actual+      , encodePretty = show+      , writeToFile = XML.writeFile XML.def+      , readFromFile = readNormalizedXML+      , goldenFile =+          "tests" </> "golden" </> name <> "-" <> ghcSuffix <.> "xml"+      , actualFile = Nothing+      , failFirstTime = False+      }++runSpec' :: Spec -> IO ()+runSpec' x = do+  (config, forest) <- evalSpec defaultConfig x+  void $ runSpecForest forest config++readNormalizedXML :: FilePath -> IO XML.Document+readNormalizedXML = fmap normalizeDoc . XML.readFile XML.def++normalizeDoc :: XML.Document -> XML.Document+normalizeDoc = removeWhitespaceNodes . removeTimeAttributes++removeWhitespaceNodes :: XML.Document -> XML.Document+removeWhitespaceNodes doc =+  doc+    { XML.documentRoot = go $ XML.documentRoot doc+    }+ where+  go el =+    el {XML.elementNodes = concatMap filterWhitespace $ XML.elementNodes el}++  filterWhitespace :: XML.Node -> [XML.Node]+  filterWhitespace = \case+    XML.NodeElement el -> [XML.NodeElement $ go el]+    XML.NodeContent c | T.all isSpace c -> []+    n -> [n]++-- | Remove volatile attributes so they don't invalidate comparison+removeTimeAttributes :: XML.Document -> XML.Document+removeTimeAttributes =+  removeAttributesByName "time" . removeAttributesByName "timestamp"++removeAttributesByName :: XML.Name -> XML.Document -> XML.Document+removeAttributesByName name doc =+  doc+    { XML.documentRoot = go $ XML.documentRoot doc+    }+ where+  go el =+    el+      { XML.elementAttributes = Map.delete name $ XML.elementAttributes el+      , XML.elementNodes = map (onNodeElement go) $ XML.elementNodes el+      }++  onNodeElement f = \case+    XML.NodeElement el -> XML.NodeElement $ f el+    n -> n++-- GHC can change certain aspects, mainly about source-location, so we can+-- incorpate that by tracking separate Golden files as necessary+ghcSuffix :: String+#if __GLASGOW_HASKELL__ >= 900+ghcSuffix = "ghc-9"+#elif __GLASGOW_HASKELL__ >= 800+ghcSuffix = "ghc-8"+#else+-- Fail to compile on other GHCs+#endif
tests/golden/default-ghc-8.xml view
@@ -9,19 +9,19 @@     tests="2" failures="1" errors="0" skipped="0">     <properties/>     <testcase-      file="tests/ExampleSpec.hs"+      file="tests/Example.hs"       line="19"       name="has a failure"       classname="Some section"       time="0.000015537">-      <failure type="error">tests/ExampleSpec.hs:19:7+      <failure type="error">tests/Example.hs:19:7  expected: &#34;False&#34;  but got: &#34;True&#34; </failure>     </testcase>     <testcase-      file="tests/ExampleSpec.hs"+      file="tests/Example.hs"       line="16"       name="has an expectation"       classname="Some section"@@ -37,7 +37,7 @@     tests="4" failures="1" errors="0" skipped="1">     <properties/>     <testcase-      file="tests/ExampleSpec.hs"+      file="tests/Example.hs"       line="28"       name="throws a colourful exception"       classname="Some section/A grouped context"@@ -45,22 +45,22 @@       <failure type="error">ColourfulException</failure>     </testcase>     <testcase-      file="tests/ExampleSpec.hs"+      file="tests/Example.hs"       line="27"       name="gets skipped"       classname="Some section/A grouped context"       time="0.000006765">-      <skipped>tests/ExampleSpec.hs:27:9+      <skipped>tests/Example.hs:27:9 some reason</skipped>     </testcase>     <testcase-      file="tests/ExampleSpec.hs"+      file="tests/Example.hs"       line="24"       name="also happens in a group"       classname="Some section/A grouped context"       time="0.000007421"/>     <testcase-      file="tests/ExampleSpec.hs"+      file="tests/Example.hs"       line="22"       name="happens in a group"       classname="Some section/A grouped context"
tests/golden/default-ghc-9.xml view
@@ -1,6 +1,6 @@-<?xml version="1.0" encoding="UTF-8"?><testsuites name="hspec-junit-format"><testsuite errors="0" failures="1" hostname="localhost" id="0" name="Some section" package="Some section" skipped="0" tests="2"><properties/><testcase classname="Some section" file="tests/ExampleSpec.hs" line="19" name="has a failure"><failure type="error">tests/ExampleSpec.hs:19:12+<?xml version="1.0" encoding="UTF-8"?><testsuites name="hspec-junit-format"><testsuite errors="0" failures="1" hostname="localhost" id="0" name="Some section" package="Some section" skipped="0" tests="2"><properties/><testcase classname="Some section" file="tests/Example.hs" line="19" name="has a failure"><failure type="error">tests/Example.hs:19:12  expected: "False"  but got: "True"-</failure></testcase><testcase classname="Some section" file="tests/ExampleSpec.hs" line="16" name="has an expectation"/></testsuite><testsuite errors="0" failures="1" hostname="localhost" id="1" name="Some section/A grouped context" package="Some section/A grouped context" skipped="1" tests="4"><properties/><testcase classname="Some section/A grouped context" file="tests/ExampleSpec.hs" line="28" name="throws a colourful exception"><failure type="error">ColourfulException</failure></testcase><testcase classname="Some section/A grouped context" file="tests/ExampleSpec.hs" line="27" name="gets skipped"><skipped>tests/ExampleSpec.hs:27:9-some reason</skipped></testcase><testcase classname="Some section/A grouped context" file="tests/ExampleSpec.hs" line="24" name="also happens in a group"/><testcase classname="Some section/A grouped context" file="tests/ExampleSpec.hs" line="22" name="happens in a group"/></testsuite></testsuites>+</failure></testcase><testcase classname="Some section" file="tests/Example.hs" line="16" name="has an expectation"/></testsuite><testsuite errors="0" failures="1" hostname="localhost" id="1" name="Some section/A grouped context" package="Some section/A grouped context" skipped="1" tests="4"><properties/><testcase classname="Some section/A grouped context" file="tests/Example.hs" line="28" name="throws a colourful exception"><failure type="error">ColourfulException</failure></testcase><testcase classname="Some section/A grouped context" file="tests/Example.hs" line="27" name="gets skipped"><skipped>tests/Example.hs:27:9+some reason</skipped></testcase><testcase classname="Some section/A grouped context" file="tests/Example.hs" line="24" name="also happens in a group"/><testcase classname="Some section/A grouped context" file="tests/Example.hs" line="22" name="happens in a group"/></testsuite></testsuites>
tests/golden/prefixed-ghc-8.xml view
@@ -9,19 +9,19 @@     tests="2" failures="1" errors="0" skipped="0">     <properties/>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="19"       name="has a failure"       classname="Some section"       time="0.000015537">-      <failure type="error">lol/monorepo/tests/ExampleSpec.hs:19:7+      <failure type="error">lol/monorepo/tests/Example.hs:19:7  expected: &#34;False&#34;  but got: &#34;True&#34; </failure>     </testcase>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="16"       name="has an expectation"       classname="Some section"@@ -37,7 +37,7 @@     tests="4" failures="1" errors="0" skipped="1">     <properties/>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="28"       name="throws a colourful exception"       classname="Some section/A grouped context"@@ -45,22 +45,22 @@       <failure type="error">ColourfulException</failure>     </testcase>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="27"       name="gets skipped"       classname="Some section/A grouped context"       time="0.000006765">-      <skipped>lol/monorepo/tests/ExampleSpec.hs:27:9+      <skipped>lol/monorepo/tests/Example.hs:27:9 some reason</skipped>     </testcase>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="24"       name="also happens in a group"       classname="Some section/A grouped context"       time="0.000007421"/>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="22"       name="happens in a group"       classname="Some section/A grouped context"
tests/golden/prefixed-ghc-9.xml view
@@ -9,19 +9,19 @@     tests="2" failures="1" errors="0" skipped="0">     <properties/>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="19"       name="has a failure"       classname="Some section"       time="0.000015537">-      <failure type="error">lol/monorepo/tests/ExampleSpec.hs:19:12+      <failure type="error">lol/monorepo/tests/Example.hs:19:12  expected: &#34;False&#34;  but got: &#34;True&#34; </failure>     </testcase>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="16"       name="has an expectation"       classname="Some section"@@ -37,7 +37,7 @@     tests="4" failures="1" errors="0" skipped="1">     <properties/>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="28"       name="throws a colourful exception"       classname="Some section/A grouped context"@@ -45,22 +45,22 @@       <failure type="error">ColourfulException</failure>     </testcase>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="27"       name="gets skipped"       classname="Some section/A grouped context"       time="0.000006765">-      <skipped>lol/monorepo/tests/ExampleSpec.hs:27:9+      <skipped>lol/monorepo/tests/Example.hs:27:9 some reason</skipped>     </testcase>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="24"       name="also happens in a group"       classname="Some section/A grouped context"       time="0.000007421"/>     <testcase-      file="lol/monorepo/tests/ExampleSpec.hs"+      file="lol/monorepo/tests/Example.hs"       line="22"       name="happens in a group"       classname="Some section/A grouped context"