tibbe avatar tibbe committed e0f57c7

Add option to dump results as JUnit XML

Comments (0)

Files changed (3)

     Just compareFile -> do
       liftIO $ writeFile compareFile $ resultForestToCSV rts
 
-  plotAll $ flatten rts
+  let rs = flatten rts
+  plotAll rs
+  junit rs
 
   where go :: String -> Benchmark -> Criterion ResultForest
         go pfx (Benchmark desc b)
       meanR   = mean r
 
       mean = estPoint . anMean . sampleAnalysis
+
+-- | Write summary JUnit file (if applicable)
+junit :: [Result] -> Criterion ()
+junit rs
+  = do junitOpt <- getConfigItem (getLast . cfgJUnitFile)
+       case junitOpt of
+         Just fn -> liftIO $ writeFile fn msg
+         Nothing -> return ()
+  where
+    msg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ++
+          printf "<testsuite name=\"Criterion benchmarks\" tests=\"%d\">\n"
+          (length rs) ++
+          concatMap single rs ++
+          "</testsuite>\n"
+    single r = printf "  <testcase name=\"%s\" time=\"%f\" />\n"
+               (attrEsc $ description r) (estPoint $ anMean $ sampleAnalysis r)
+    attrEsc = concatMap esc
+      where
+        esc '\'' = "&apos;"
+        esc '"'  = "&quot;"
+        esc '<'  = "&lt;"
+        esc '>'  = "&gt;"
+        esc '&'  = "&amp;"
+        esc c    = [c]

Criterion/Config.hs

     , cfgCompareFile  :: Last FilePath -- ^ Filename of the comparison CSV.
     , cfgTemplate     :: Last FilePath -- ^ Filename of report template.
     , cfgVerbosity    :: Last Verbosity -- ^ Whether to run verbosely.
+    , cfgJUnitFile    :: Last FilePath -- ^ Filename of JUnit report.
     } deriving (Eq, Read, Show, Typeable)
 
 instance Monoid Config where
                 , cfgCompareFile  = mempty
                 , cfgTemplate     = ljust "report.tpl"
                 , cfgVerbosity    = ljust Normal
+                , cfgJUnitFile    = mempty
                 }
 
 -- | Constructor for 'Last' values.
               , cfgCompareFile  = mempty
               , cfgTemplate     = mempty
               , cfgVerbosity    = mempty
+              , cfgJUnitFile    = mempty
               }
 
 appendConfig :: Config -> Config -> Config
     , cfgCompareFile  = app cfgCompareFile a b
     , cfgTemplate     = app cfgTemplate a b
     , cfgVerbosity    = app cfgVerbosity a b
+    , cfgJUnitFile    = app cfgJUnitFile a b
     }
   where app f = mappend `on` f

Criterion/Main.hs

           "display version, then exit"
  , Option ['v'] ["verbose"] (noArg mempty { cfgVerbosity = ljust Verbose })
           "print more output"
+ , Option [] ["junit"] (ReqArg (\s -> return $ mempty { cfgJUnitFile = ljust s }) "FILENAME")
+          "produce a JUnit report file of all results"
  ]
 
 printBanner :: Config -> IO ()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.