packages feed

tasty-coverage (empty) → 0.1.0.0

raw patch · 5 files changed

+177/−0 lines, 5 filesdep +basedep +filepathdep +hpc

Dependencies added: base, filepath, hpc, tasty

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for tasty-test++## 0.1.0.0 -- 2023-08-07++* Release of first version on Hackage
+ LICENSE view
@@ -0,0 +1,28 @@+BSD 3-Clause License++Copyright (c) 2023, David Binder++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+   list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+   this list of conditions and the following disclaimer in the documentation+   and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+   contributors may be used to endorse or promote products derived from+   this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,32 @@+# tasty-coverage++A [tasty](https://hackage.haskell.org/package/tasty) ingredient which allows to generate per-test coverage data.++If the GHC compiler is passed the `-fhpc` flag, then the generated code is instrumented in order to also emit information about the executed parts of the sourcecode at runtime.+This coverage information is written to a file with the suffix `.tix`.+For testsuites it is sometimes more useful to have the coverage information for each test individually.+This information can be collected using the methods from the `Trace.Hpc.Reflect` module from the [hpc](https://hackage.haskell.org/package/hpc) library.+The `tasty-coverage` package provides a simple ingredient for the [tasty](https://hackage.haskell.org/package/tasty) testsuite driver which allows to run the testsuite with the `--report-coverage` option.+When this option is passed, one `.tix` file is generated for each individual test.+Passing tests have the file suffix `PASSED.tix`, whereas failing tests have the suffix `FAILED.tix`.++```console+> cabal run tasty-coverage-test -- --help+Mmm... tasty test suite++Usage: tasty-coverage-test [-p|--pattern PATTERN] [-t|--timeout DURATION] +                           [--report-coverage]++Available options:+  -h,--help                Show this help text+  -p,--pattern PATTERN     Select only tests which satisfy a pattern or awk+                           expression+  -t,--timeout DURATION    Timeout for individual tests (suffixes: ms,s,m,h;+                           default: s)+  --report-coverage        Generate per-test coverage data++> cabal run tasty-coverage-test -- --report-coverage+Wrote coverage file: tix/UnitTests.testOne.PASSED.tix+Wrote coverage file: tix/UnitTests.testTwo.PASSED.tix+Wrote coverage file: tix/UnitTests.testThree.FAILED.tix+```
+ src/Test/Tasty/CoverageReporter.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE InstanceSigs #-}+module Test.Tasty.CoverageReporter (coverageReporter) where++import Test.Tasty+import Test.Tasty.Ingredients+import Test.Tasty.Options+import Test.Tasty.Runners+import Test.Tasty.Providers+import Data.Typeable+import Trace.Hpc.Reflect ( clearTix, examineTix )+import Trace.Hpc.Tix ( writeTix )+import System.FilePath ( (<.>), (</>) )+import Control.Monad (forM_)+import qualified Data.List.NonEmpty as NE+import Data.List.NonEmpty ( NonEmpty )+import Data.Foldable (fold)+import Data.Bifunctor (first)++newtype ReportCoverage = MkReportCoverage   Bool+  deriving (Eq, Ord, Typeable)++instance IsOption ReportCoverage where+    defaultValue  = MkReportCoverage False+    parseValue = fmap MkReportCoverage . safeReadBool+    optionName = pure "report-coverage"+    optionHelp = pure "Generate per-test coverage data"+    optionCLParser = mkFlagCLParser mempty (MkReportCoverage True)+++tixDir :: FilePath+tixDir = "tix"++-- | Obtain the list of all tests in the suite+testNames :: OptionSet -> TestTree -> IO ()+testNames  os tree = forM_ (foldTestTree coverageFold os tree) $ \(s,f) -> f (fold (NE.intersperse "." s))++++-- | Collect all tests and+coverageFold :: TreeFold [(NonEmpty TestName, String -> IO ())]+coverageFold = trivialFold+       { foldSingle = \opts name test -> do+          let f n = do+                -- Collect the coverage data for exactly this test.+                clearTix+                result <- run opts test (\_ -> pure ())+                tix <- examineTix+                let filepath = tixFilePath n result+                writeTix filepath tix+                putStrLn ("Wrote coverage file: " <> filepath)+          pure (NE.singleton name, f),+          -- Append the name of the testgroup to the list of TestNames+          foldGroup = \_ groupName acc -> fmap (first (NE.cons groupName)) acc+        }++tixFilePath :: TestName -> Result -> FilePath+tixFilePath tn Result { resultOutcome = Success }  = tixDir </> tn <.> "PASSED" <.> ".tix"+tixFilePath tn Result { resultOutcome = Failure _ } = tixDir </> tn <.> "FAILED" <.> ".tix"++coverageReporter :: Ingredient+coverageReporter = TestManager coverageOptions coverageRunner++coverageOptions :: [OptionDescription]+coverageOptions = [Option (Proxy :: Proxy ReportCoverage)]++coverageRunner :: OptionSet -> TestTree -> Maybe (IO Bool)+coverageRunner opts tree = case lookupOption opts of+  MkReportCoverage False -> Nothing+  MkReportCoverage True -> Just $ do+    testNames opts tree+    pure True++  
+ tasty-coverage.cabal view
@@ -0,0 +1,39 @@+cabal-version:   3.0+name:            tasty-coverage+version:         0.1.0.0+license:         BSD-3-Clause+license-file:    LICENSE+copyright:       David Binder, 2023+maintainer:      david.binder@uni-tuebingen.de+author:          David Binder+tested-with:     ghc ==9.2.7 || ==9.4.5 || ==9.6.2+homepage:        https://github.com/BinderDavid/tasty-coverage+bug-reports:     https://github.com/BinderDavid/tasty-coverage/issues+synopsis:+    Ingredient for tasty which generates per-test coverage reports++description:+    An ingredient for the tasty testing framework which allows to generate per-test coverage reports.+    For every test "foo" a file "foo.PASSED.tix" or "foo.FAILED.tix" is generated, depending on whether the test passed or failed. ++category:        Testing+build-type:      Simple+extra-doc-files:+    CHANGELOG.md+    README.md++source-repository head+    type:     git+    location: git@github.com:BinderDavid/tasty-coverage.git++library+    exposed-modules:  Test.Tasty.CoverageReporter+    hs-source-dirs:   src+    default-language: Haskell2010+    ghc-options:      -Wall+    build-depends:+        base >=4.16 && <4.20,+        tasty ^>=1.4,+        hpc >=0.6 && <0.8,+        filepath >=1.3.8 && <1.4.100+