hspec-junit-formatter 1.2.0.0 → 1.2.1.0
raw patch · 13 files changed
+311/−318 lines, 13 filesdep +pretty-simpledep ~xml-conduit
Dependencies added: pretty-simple
Dependency ranges changed: xml-conduit
Files
- hspec-junit-formatter.cabal +8/−7
- library/Test/Hspec/JUnit/Config.hs +17/−0
- library/Test/Hspec/JUnit/Config/Env.hs +1/−0
- library/Test/Hspec/JUnit/Format.hs +3/−1
- tests/Test/Hspec/JUnit/FormatterSpec.hs +14/−97
- tests/golden/default-base-4.21.xml +67/−0
- tests/golden/default-ghc-8.xml +0/−69
- tests/golden/default-ghc-9.xml +0/−6
- tests/golden/default.xml +67/−0
- tests/golden/prefixed-base-4.21.xml +67/−0
- tests/golden/prefixed-ghc-8.xml +0/−69
- tests/golden/prefixed-ghc-9.xml +0/−69
- tests/golden/prefixed.xml +67/−0
hspec-junit-formatter.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.18 name: hspec-junit-formatter-version: 1.2.0.0+version: 1.2.1.0 license: MIT license-file: LICENSE copyright: 2021 Renaissance Learning Inc@@ -15,10 +15,10 @@ category: Testing build-type: Simple extra-source-files:- tests/golden/default-ghc-8.xml- tests/golden/default-ghc-9.xml- tests/golden/prefixed-ghc-8.xml- tests/golden/prefixed-ghc-9.xml+ tests/golden/default-base-4.21.xml+ tests/golden/default.xml+ tests/golden/prefixed-base-4.21.xml+ tests/golden/prefixed.xml extra-doc-files: README.md@@ -69,7 +69,7 @@ regex-tdfa >=1.3.2.1, text >=1.2.5.0, time >=1.11.1.1,- xml-conduit >=1.9.1.2,+ xml-conduit >=1.10.0.0, xml-types >=0.3.8 if impl(ghc >=9.8)@@ -142,9 +142,10 @@ hspec >=2.10.0, hspec-golden >=0.2.1.0, hspec-junit-formatter,+ pretty-simple >=4.1.2.0, temporary >=1.3, text >=1.2.5.0,- xml-conduit >=1.9.1.2+ xml-conduit >=1.10.0.0 if impl(ghc >=9.8) ghc-options: -Wno-missing-role-annotations
library/Test/Hspec/JUnit/Config.hs view
@@ -9,12 +9,14 @@ , setJUnitConfigSuiteName , setJUnitConfigSourcePathPrefix , setJUnitConfigDropConsoleFormatting+ , setJUnitConfigPretty -- * Use , getJUnitConfigOutputFile , getJUnitConfigSuiteName , getJUnitPrefixSourcePath , getJUnitConfigDropConsoleFormatting+ , getJUnitConfigPretty ) where import Prelude@@ -30,6 +32,7 @@ , suiteName :: Text , sourcePathPrefix :: Maybe FilePath , dropConsoleFormatting :: Bool+ , pretty :: Bool } -- | Construct a 'JUnitConfig' given a suite name@@ -44,6 +47,7 @@ , suiteName = name , sourcePathPrefix = Nothing , dropConsoleFormatting = False+ , pretty = False } -- | Set the directory within which to generate the report@@ -83,6 +87,15 @@ setJUnitConfigDropConsoleFormatting :: Bool -> JUnitConfig -> JUnitConfig setJUnitConfigDropConsoleFormatting x config = config {dropConsoleFormatting = x} +-- | Set whether the file should be pretty-printed+--+-- @xml-conduit@ can pretty-print the contents of the XML file in order to make+-- it more human-readable. Note that this operation normalizes whitespace even+-- within nodes. This may turn multi-line failure messages into one line, for+-- example.+setJUnitConfigPretty :: Bool -> JUnitConfig -> JUnitConfig+setJUnitConfigPretty x config = config {pretty = x}+ -- | Retrieve the full path to the generated report getJUnitConfigOutputFile :: JUnitConfig -> FilePath getJUnitConfigOutputFile c = fromMaybe (c.outputDirectory </> c.outputName) c.outputFile@@ -101,3 +114,7 @@ -- failure reports. getJUnitConfigDropConsoleFormatting :: JUnitConfig -> Bool getJUnitConfigDropConsoleFormatting c = c.dropConsoleFormatting++-- | Retrieve whether the file should be pretty-printed+getJUnitConfigPretty :: JUnitConfig -> Bool+getJUnitConfigPretty c = c.pretty
library/Test/Hspec/JUnit/Config/Env.hs view
@@ -52,6 +52,7 @@ , readEnv "SOURCE_PATH_PREFIX" setJUnitConfigSourcePathPrefix , readEnv "DROP_CONSOLE_FORMATTING" $ setJUnitConfigDropConsoleFormatting . (== "1")+ , readEnv "PRETTY" $ setJUnitConfigPretty . (== "1") ] readEnv name setter =
library/Test/Hspec/JUnit/Format.hs view
@@ -19,6 +19,7 @@ import Test.Hspec.JUnit.Render (renderJUnit) import Test.Hspec.JUnit.Schema qualified as Schema import Text.XML.Stream.Render (def, renderBytes)+import Text.XML.Stream.Render.Internal (rsPretty) junit :: JUnitConfig -> FormatConfig -> IO Format junit junitConfig _config = pure $ \case@@ -53,13 +54,14 @@ runConduitRes $ yield output .| renderJUnit dropConsoleFormatting- .| renderBytes def+ .| renderBytes renderConfig .| sinkFile file where file = getJUnitConfigOutputFile junitConfig suiteName = getJUnitConfigSuiteName junitConfig applyPrefix = getJUnitPrefixSourcePath junitConfig dropConsoleFormatting = getJUnitConfigDropConsoleFormatting junitConfig+ renderConfig = def {rsPretty = getJUnitConfigPretty junitConfig} groupItems :: [(Path, Item)] -> [(Text, [(Text, Item)])] groupItems = Map.toList . Map.fromListWith (<>) . fmap group
tests/Test/Hspec/JUnit/FormatterSpec.hs view
@@ -7,10 +7,8 @@ import Prelude import Control.Monad (void)-import Data.Char (isSpace)-import Data.List (isInfixOf, isPrefixOf) import Data.Map.Strict qualified as Map-import Data.Text qualified as T+import Data.Text.Lazy qualified as LT import Example qualified import System.FilePath ((<.>), (</>)) import System.IO.Temp (withSystemTempDirectory)@@ -19,7 +17,9 @@ import Test.Hspec.JUnit.Config import Test.Hspec.JUnit.Formatter qualified as Formatter import Test.Hspec.Runner+import Text.Pretty.Simple (pShowNoColor) import Text.XML qualified as XML+import Text.XML.Stream.Render.Internal qualified as XML spec :: Spec spec = do@@ -40,6 +40,7 @@ actual <- withSystemTempDirectory "" $ \tmp -> do let junitConfig = modifyConfig+ $ setJUnitConfigPretty True $ setJUnitConfigOutputDirectory tmp $ setJUnitConfigOutputName "test.xml" $ defaultJUnitConfig "hspec-junit-format"@@ -50,11 +51,10 @@ pure Golden { output = actual- , encodePretty = show- , writeToFile = XML.writeFile XML.def+ , encodePretty = LT.unpack . pShowNoColor+ , writeToFile = XML.writeFile (XML.def {XML.rsPretty = True}) , readFromFile = readNormalizedXML- , goldenFile =- "tests" </> "golden" </> name <> "-" <> ghcSuffix <.> "xml"+ , goldenFile = "tests" </> "golden" </> name <> suffix <.> "xml" , actualFile = Nothing , failFirstTime = False }@@ -68,22 +68,7 @@ readNormalizedXML = fmap normalizeDoc . XML.readFile XML.def normalizeDoc :: XML.Document -> XML.Document-normalizeDoc = removeWhitespaceNodes . removeTimeAttributes . normalizeErrorMessages--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]+normalizeDoc = removeTimeAttributes -- | Remove volatile attributes so they don't invalidate comparison removeTimeAttributes :: XML.Document -> XML.Document@@ -106,79 +91,11 @@ XML.NodeElement el -> XML.NodeElement $ f el n -> n -normalizeErrorMessages :: XML.Document -> XML.Document-normalizeErrorMessages doc =- doc- { XML.documentRoot = go $ XML.documentRoot doc- }- where- go el =- el- { XML.elementNodes =- map (onNodeElement go . normalizeErrorContent . normalizeLineNumbers)- $ XML.elementNodes el- }-- normalizeErrorContent :: XML.Node -> XML.Node- normalizeErrorContent = \case- XML.NodeElement el- | XML.elementName el == XML.Name "failure" Nothing Nothing ->- XML.NodeElement- $ el {XML.elementNodes = map stripLocationPrefix $ XML.elementNodes el}- | XML.elementName el == XML.Name "skipped" Nothing Nothing ->- XML.NodeElement- $ el {XML.elementNodes = map stripLocationPrefix $ XML.elementNodes el}- | otherwise -> XML.NodeElement el- n -> n-- normalizeLineNumbers :: XML.Node -> XML.Node- normalizeLineNumbers = \case- XML.NodeElement el- | XML.elementName el == XML.Name "testcase" Nothing Nothing ->- let- attrs = XML.elementAttributes el- normalizedAttrs = Map.adjust normalizeLineAttr (XML.Name "line" Nothing Nothing) attrs- in- XML.NodeElement $ el {XML.elementAttributes = normalizedAttrs}- | otherwise -> XML.NodeElement el- n -> n-- normalizeLineAttr :: T.Text -> T.Text- normalizeLineAttr lineText- | lineText == "29" = "28" -- Normalize line 29 to 28 for version compatibility- | otherwise = lineText-- stripLocationPrefix :: XML.Node -> XML.Node- stripLocationPrefix = \case- XML.NodeContent content ->- let- contentText = T.unpack content- normalizedContent = case lines contentText of- (firstLine : rest)- | ( "tests/Example.hs:" `isPrefixOf` firstLine- || "lol/monorepo/tests/Example.hs:" `isPrefixOf` firstLine- )- && "\n" `isInfixOf` contentText ->- unlines rest- _ -> contentText- trimmedContent = case reverse normalizedContent of- '\n' : rest -> reverse rest- _ -> normalizedContent- in- XML.NodeContent $ T.pack trimmedContent- n -> n-- 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"+-- Store a separate golden for newer base because throwIO's behavior changed+-- such that different location data is present and so our output changes+suffix :: String+#if MIN_VERSION_base(4,21,0)+suffix = "-base-4.21" #else--- Fail to compile on other GHCs+suffix = "" #endif
+ tests/golden/default-base-4.21.xml view
@@ -0,0 +1,67 @@+<?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/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="29"+ name="throws a colourful exception">+ <failure type="error">+ tests/Example.hs:29:9 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/default-ghc-8.xml
@@ -1,69 +0,0 @@-<testsuites name="hspec-junit-format">- <testsuite- name="Some section"- package="Some section"- id="0"- hostname="localhost"- time="0.000032355"- timestamp="2021-05-17T15:36:10.205608409Z"- tests="2" failures="1" errors="0" skipped="0">- <properties/>- <testcase- file="tests/Example.hs"- line="19"- name="has a failure"- classname="Some section"- time="0.000015537">- <failure type="error">tests/Example.hs:19:7--expected: "False"- but got: "True"-</failure>- </testcase>- <testcase- file="tests/Example.hs"- line="16"- name="has an expectation"- classname="Some section"- time="0.000016818"/>- </testsuite>- <testsuite- name="Some section/A grouped context"- package="Some section/A grouped context"- id="1"- time="0.000021009"- timestamp="2021-05-17T15:36:10.205608409Z"- hostname="localhost"- tests="4" failures="1" errors="0" skipped="1">- <properties/>- <testcase- file="tests/Example.hs"- line="28"- name="throws a colourful exception"- classname="Some section/A grouped context"- time="0.000012194">- <failure type="error">ColourfulException</failure>- </testcase>- <testcase- file="tests/Example.hs"- line="27"- name="gets skipped"- classname="Some section/A grouped context"- time="0.000006765">- <skipped>tests/Example.hs:27:9-some reason</skipped>- </testcase>- <testcase- file="tests/Example.hs"- line="24"- name="also happens in a group"- classname="Some section/A grouped context"- time="0.000007421"/>- <testcase- file="tests/Example.hs"- line="22"- name="happens in a group"- classname="Some section/A grouped context"- time="0.000006823"/>- </testsuite>-</testsuites>
− tests/golden/default-ghc-9.xml
@@ -1,6 +0,0 @@-<?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/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/default.xml view
@@ -0,0 +1,67 @@+<?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/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-base-4.21.xml view
@@ -0,0 +1,67 @@+<?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="lol/monorepo/tests/Example.hs"+ line="19"+ name="has a failure">+ <failure type="error">+ lol/monorepo/tests/Example.hs:19:12 expected: "False" but got: "True"+ </failure>+ </testcase>+ <testcase+ classname="Some section"+ file="lol/monorepo/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="lol/monorepo/tests/Example.hs"+ line="29"+ name="throws a colourful exception">+ <failure type="error">+ lol/monorepo/tests/Example.hs:29:9 ColourfulException+ </failure>+ </testcase>+ <testcase+ classname="Some section/A grouped context"+ file="lol/monorepo/tests/Example.hs"+ line="27"+ name="gets skipped">+ <skipped>+ lol/monorepo/tests/Example.hs:27:9 some reason+ </skipped>+ </testcase>+ <testcase+ classname="Some section/A grouped context"+ file="lol/monorepo/tests/Example.hs"+ line="24"+ name="also happens in a group"/>+ <testcase+ classname="Some section/A grouped context"+ file="lol/monorepo/tests/Example.hs"+ line="22"+ name="happens in a group"/>+ </testsuite>+</testsuites>
− tests/golden/prefixed-ghc-8.xml
@@ -1,69 +0,0 @@-<testsuites name="hspec-junit-format">- <testsuite- name="Some section"- package="Some section"- id="0"- hostname="localhost"- time="0.000032355"- timestamp="2021-05-17T15:36:10.205608409Z"- tests="2" failures="1" errors="0" skipped="0">- <properties/>- <testcase- file="lol/monorepo/tests/Example.hs"- line="19"- name="has a failure"- classname="Some section"- time="0.000015537">- <failure type="error">lol/monorepo/tests/Example.hs:19:7--expected: "False"- but got: "True"-</failure>- </testcase>- <testcase- file="lol/monorepo/tests/Example.hs"- line="16"- name="has an expectation"- classname="Some section"- time="0.000016818"/>- </testsuite>- <testsuite- name="Some section/A grouped context"- package="Some section/A grouped context"- id="1"- time="0.000021009"- timestamp="2021-05-17T15:36:10.205608409Z"- hostname="localhost"- tests="4" failures="1" errors="0" skipped="1">- <properties/>- <testcase- file="lol/monorepo/tests/Example.hs"- line="28"- name="throws a colourful exception"- classname="Some section/A grouped context"- time="0.000012194">- <failure type="error">ColourfulException</failure>- </testcase>- <testcase- file="lol/monorepo/tests/Example.hs"- line="27"- name="gets skipped"- classname="Some section/A grouped context"- time="0.000006765">- <skipped>lol/monorepo/tests/Example.hs:27:9-some reason</skipped>- </testcase>- <testcase- 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/Example.hs"- line="22"- name="happens in a group"- classname="Some section/A grouped context"- time="0.000006823"/>- </testsuite>-</testsuites>
− tests/golden/prefixed-ghc-9.xml
@@ -1,69 +0,0 @@-<testsuites name="hspec-junit-format">- <testsuite- name="Some section"- package="Some section"- id="0"- hostname="localhost"- time="0.000032355"- timestamp="2021-05-17T15:36:10.205608409Z"- tests="2" failures="1" errors="0" skipped="0">- <properties/>- <testcase- file="lol/monorepo/tests/Example.hs"- line="19"- name="has a failure"- classname="Some section"- time="0.000015537">- <failure type="error">lol/monorepo/tests/Example.hs:19:12--expected: "False"- but got: "True"-</failure>- </testcase>- <testcase- file="lol/monorepo/tests/Example.hs"- line="16"- name="has an expectation"- classname="Some section"- time="0.000016818"/>- </testsuite>- <testsuite- name="Some section/A grouped context"- package="Some section/A grouped context"- id="1"- time="0.000021009"- timestamp="2021-05-17T15:36:10.205608409Z"- hostname="localhost"- tests="4" failures="1" errors="0" skipped="1">- <properties/>- <testcase- file="lol/monorepo/tests/Example.hs"- line="28"- name="throws a colourful exception"- classname="Some section/A grouped context"- time="0.000012194">- <failure type="error">ColourfulException</failure>- </testcase>- <testcase- file="lol/monorepo/tests/Example.hs"- line="27"- name="gets skipped"- classname="Some section/A grouped context"- time="0.000006765">- <skipped>lol/monorepo/tests/Example.hs:27:9-some reason</skipped>- </testcase>- <testcase- 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/Example.hs"- line="22"- name="happens in a group"- classname="Some section/A grouped context"- time="0.000006823"/>- </testsuite>-</testsuites>
+ tests/golden/prefixed.xml view
@@ -0,0 +1,67 @@+<?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="lol/monorepo/tests/Example.hs"+ line="19"+ name="has a failure">+ <failure type="error">+ lol/monorepo/tests/Example.hs:19:12 expected: "False" but got: "True"+ </failure>+ </testcase>+ <testcase+ classname="Some section"+ file="lol/monorepo/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="lol/monorepo/tests/Example.hs"+ line="28"+ name="throws a colourful exception">+ <failure type="error">+ ColourfulException+ </failure>+ </testcase>+ <testcase+ classname="Some section/A grouped context"+ file="lol/monorepo/tests/Example.hs"+ line="27"+ name="gets skipped">+ <skipped>+ lol/monorepo/tests/Example.hs:27:9 some reason+ </skipped>+ </testcase>+ <testcase+ classname="Some section/A grouped context"+ file="lol/monorepo/tests/Example.hs"+ line="24"+ name="also happens in a group"/>+ <testcase+ classname="Some section/A grouped context"+ file="lol/monorepo/tests/Example.hs"+ line="22"+ name="happens in a group"/>+ </testsuite>+</testsuites>