tasty-travis (empty) → 0.1.0
raw patch · 5 files changed
+363/−0 lines, 5 filesdep +basedep +tastysetup-changed
Dependencies added: base, tasty
Files
- LICENSE +30/−0
- README.md +40/−0
- Setup.hs +2/−0
- Test/Tasty/Travis.hs +237/−0
- tasty-travis.cabal +54/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, Merijn Verstraaten++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * 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.++ * Neither the name of Merijn Verstraaten nor the names of other+ 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+OWNER 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,40 @@+Tasty Travis: Fancy Travis CI output for tasty tests+====================================================+[](https://en.wikipedia.org/wiki/BSD_License)+[](https://hackage.haskell.org/package/tasty-travis)+[](https://travis-ci.org/merijn/tasty-travis)++**Tasty Travis** provides fancy+[Tasty](https://hackage.haskell.org/package/tasty) test output on+[Travis CI](https://travis-ci.org/).++It allows you get coloured test output, folding and collapsing groups of tests,+and hiding the output of successful tests.++Example+-------++Here's what an example `test.hs` might look:++```haskell+import Test.Tasty+import Test.Tasty.Travis (travisTestReporter, defaultConfig, listingTests)+import Test.Tasty.HUnit++import Data.List+import Data.Ord++main = defaultMainWithIngredients ingredients tests+ where+ ingredients = [ listingTests, travisTestReporter defaultConfig ]++tests :: TestTree+tests = testGroup "Unit tests"+ [ testCase "List comparison (different length)" $+ [1, 2, 3] `compare` [1,2] @?= GT++ -- the following test does not hold+ , testCase "List comparison (same length)" $+ [1, 2, 3] `compare` [1,2,2] @?= LT+ ]+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Test/Tasty/Travis.hs view
@@ -0,0 +1,237 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE Trustworthy #-}+-------------------------------------------------------------------------------+-- |+-- Module : Test.Tasty.Travis+-- Copyright : (C) 2017 Merijn Verstraaten+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Merijn Verstraaten <merijn@inconsistent.nl>+-- Stability : experimental+-- Portability : haha+--+-- <https://travis-ci.org/ Travis CI> support for+-- <https://hackage.haskell.org/package/tasty tasty>.+--+-- This module provides a tasty 'Ingredient' which functions as a drop-in+-- replacement for the 'consoleTestReporter' from tasty. It detects whether the+-- \"TRAVIS\" environment variable is set to \"true\". If so, it produces+-- output as configured. If not, it falls back to the 'consoleTestReporter'.+-------------------------------------------------------------------------------+module Test.Tasty.Travis+ ( travisTestReporter+ , TravisConfig(..)+ , defaultConfig+ , FoldGroup(..)+ , FoldWhen(..)+ , SummaryWhen(..)+ , listingTests+ ) where++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative (Applicative(..), (<$>), (<$), (<*>))+import Data.Monoid (Monoid(..))+#endif+import Control.Monad (when)+import Data.Char (isSpace)+import Data.Monoid (Sum(..))+import System.Environment (lookupEnv)+import System.Exit (exitFailure)+import System.IO+ (BufferMode(LineBuffering), hPutStrLn, hSetBuffering, stderr, stdout)++import Test.Tasty.Ingredients.ConsoleReporter+import Test.Tasty.Options (IsOption(..), OptionSet, setOption)+import Test.Tasty.Runners++newtype WrapIO a = WrapIO { unwrapIO :: IO a }+ deriving (Applicative, Functor, Monad)++instance Monoid a => Monoid (WrapIO a) where+ mempty = WrapIO $ return mempty+ mappend x y = mappend <$> x <*> y++-- | Configuration for the output generated on Travis CI.+data TravisConfig+ = TravisConfig+ { travisQuiet :: Bool+ -- ^ Do not report individual tests, only overall pass/fail Statistics.+ , travisHideSuccesses :: Bool+ -- ^ If 'True', only report failures.+ , travisUseColour :: Bool+ -- ^ If 'True', generate coloured output+ , travisFoldGroup :: FoldGroup+ -- ^ How to group folds.+ , travisFoldWhen :: FoldWhen+ -- ^ When to fold.+ , travisSummaryWhen :: SummaryWhen+ -- ^ When to print a summary for a fold.+ }++-- | Default Travis configuration. Coloured output. Folds all successes away.+-- Adds summaries for folds with failures (which don't happen in this config).+defaultConfig :: TravisConfig+defaultConfig = TravisConfig+ { travisQuiet = quiet+ , travisHideSuccesses = hide+ , travisUseColour = True+ , travisFoldGroup = FoldAll+ , travisFoldWhen = FoldSuccess+ , travisSummaryWhen = SummaryFailures+ } where+ HideSuccesses hide = defaultValue+ Quiet quiet = defaultValue++-- | Control which parts of the test tree are folded away.+data FoldGroup+ = FoldMoreThan Int+ -- ^ Fold groups with more than N entries (groups or tests).+ | FoldBelow Int+ -- ^ Fold groups more than N levels from the root.+ | FoldTop Int+ -- ^ Fold groups N or less levels from the root.+ | FoldAll+ -- ^ Fold all groups.+ deriving (Eq, Show)++-- | Control when the tests/groups specified by 'FoldGroup' are folded.+data FoldWhen+ = FoldNever -- ^ Never fold output.+ | FoldSuccess -- ^ Fold all groups that have 0 failures.+ | FoldAlways -- ^ Always fold groups.+ deriving (Eq, Show)++-- | Control when a summary is printed before a fold.+data SummaryWhen+ = SummaryNever -- ^ Never print summaries.+ | SummaryFailures -- ^ Print summaries before folds with failures.+ | SummaryAlways -- ^ Always print summaries before folds.+ deriving (Eq, Show)++-- | Create a Tasty 'Ingredient' from a 'TravisConfig'. Defaults to the regular+-- console output when the TRAVIS environment variable is not set to \"true\".+--+-- Usage:+--+-- @'defaultMainWithIngredients' ['listingTests', 'travisTestReporter' yourConfig] yourTestTree@+travisTestReporter :: TravisConfig -> Ingredient+travisTestReporter cfg@TravisConfig{..} = TestReporter baseOpts runTests+ where+ TestReporter baseOpts consoleReporter = consoleTestReporter++ runTests :: OptionSet -> TestTree+ -> Maybe (StatusMap -> IO (Time -> IO Bool))+ runTests opts tree = Just $ \smap -> do+ isTravis <- maybe False (=="true") <$> lookupEnv "TRAVIS"+ if isTravis+ then runTravisTestReporter cfg travisOptions tree smap+ else runConsoleReporter smap+ where+ travisOptions :: OptionSet+ travisOptions = setOption (Quiet travisQuiet)+ . setOption (HideSuccesses travisHideSuccesses)+ . setOption (if travisUseColour then Always else Auto)+ $ opts++ errMsg :: String+ errMsg = "Unexpected failure in Tasty's 'consoleTestReporter'!"++ runConsoleReporter :: StatusMap -> IO (Time -> IO Bool)+ runConsoleReporter = case consoleReporter opts tree of+ Just f -> f+ Nothing -> const $ do+ hPutStrLn stderr errMsg+ exitFailure++runTravisTestReporter+ :: TravisConfig+ -> OptionSet+ -> TestTree+ -> StatusMap+ -> IO (Time -> IO Bool)+runTravisTestReporter cfg@TravisConfig{..} opts tree smap = do+ let ?colors = travisUseColour+ let testOutput = buildTestOutput opts tree++ hSetBuffering stdout LineBuffering+ (output, stats) <- travisOutput cfg testOutput smap+ when (not travisQuiet) $ unwrapIO $ output "" 0+ return $ \time ->+ (statFailures stats == 0) <$ printStatistics stats time++travisOutput+ :: (?colors :: Bool)+ => TravisConfig+ -> TestOutput+ -> StatusMap+ -> IO (String -> Int -> WrapIO (), Statistics)+travisOutput TravisConfig{..} output smap =+ fmap strip . unwrapIO $ foldTestOutput foldTest foldHeading output smap+ where+ strip (x,y,_) = (x,y)+ foldTest+ :: String+ -> IO ()+ -> IO Result+ -> (Result -> IO ())+ -> WrapIO (String -> Int -> WrapIO (), Statistics, Sum Int)+ foldTest _name printName getResult printResult = WrapIO $ do+ r <- getResult+ return $ case resultOutcome r of+ Success -> (success r, Statistics 1 0, Sum 1)+ Failure{} -> (doPrint r, Statistics 1 1, Sum 1)+ where+ success r | travisHideSuccesses = \_ _ -> return ()+ | otherwise = doPrint r++ doPrint r _ _ = WrapIO $ printName >> printResult r++ foldHeading+ :: String+ -> IO ()+ -> WrapIO (String -> Int -> WrapIO (), Statistics, Sum Int)+ -> WrapIO (String -> Int -> WrapIO (), Statistics, Sum Int)+ foldHeading name printHeading foldBody = do+ (printBody, stats@Statistics{..}, kids) <- foldBody+ let act label n = WrapIO $ do+ printHeading+ when mustSummarise $ printStatisticsNoTime stats+ when mustFold $+ putStrLn $ "travis_fold:start:" ++ foldMarker ++ "\\r"++ unwrapIO $ printBody (foldMarker ++ "/") (n+1)++ when mustFold $+ putStrLn $ "travis_fold:end:" ++ foldMarker ++ "\\r"+ where+ replace c | isSpace c = '_'+ | otherwise = c++ foldMarker = label ++ map replace name+ mustFold = doFold travisFoldWhen stats travisFoldGroup kids n+ mustSummarise = and [ n /= 0, mustFold+ , doSummary travisSummaryWhen stats]++ if statTotal == 0 || (statFailures == 0 && travisHideSuccesses)+ then return (\_ _ -> return (), stats, Sum 0)+ else return (act, stats, Sum 1)++doFold :: FoldWhen -> Statistics -> FoldGroup -> Sum Int -> Int -> Bool+doFold FoldNever _ = \_ _ _ -> False+doFold FoldSuccess stats+ | statFailures stats == 0 = doFoldGroup+ | otherwise = \_ _ _ -> False+doFold FoldAlways _ = doFoldGroup++doFoldGroup :: FoldGroup -> Sum Int -> Int -> Bool+doFoldGroup FoldAll _ _ = True+doFoldGroup (FoldBelow n) _ i = i > n+doFoldGroup (FoldTop n) _ i = i <= n+doFoldGroup (FoldMoreThan n) kids _ = getSum kids > n++doSummary :: SummaryWhen -> Statistics -> Bool+doSummary SummaryNever _ = False+doSummary SummaryFailures stats = statFailures stats /= 0+doSummary SummaryAlways _ = True
+ tasty-travis.cabal view
@@ -0,0 +1,54 @@+Name: tasty-travis+Version: 0.1.0++Homepage: https://github.com/merijn/tasty-travis+Bug-Reports: https://github.com/merijn/tasty-travis/issues++Author: Merijn Verstraaten+Maintainer: Merijn Verstraaten <merijn@inconsistent.nl>+Copyright: Copyright © 2017 Merijn Verstraaten++License: BSD3+License-File: LICENSE++Category: Testing+Cabal-Version: >= 1.10+Build-Type: Simple+Tested-With: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2,+ GHC == 8.2.1, GHC == 8.3.*++Extra-Source-Files: README.md++Synopsis: Fancy Travis CI output for tasty tests.++Description:+ Fancy <https://travis-ci.org/ Travis CI> output for+ <https://hackage.haskell.org/package/tasty tasty> tests. Features include:+ .+ * Folded output+ .+ * Coloured output+ .+ * Hiding successful tests++Library+ Default-Language: Haskell2010+ GHC-Options: -Wall -fno-warn-unused-do-bind++ Exposed-Modules: Test.Tasty.Travis+ Other-Extensions: CPP+ GeneralizedNewtypeDeriving+ ImplicitParams+ RecordWildCards+ Trustworthy++ Build-Depends: base >= 4.6 && < 5+ , tasty == 0.12.*++Source-Repository head+ Type: git+ Location: ssh://github.com:merijn/tasty-travis.git++Source-Repository head+ Type: mercurial+ Location: https://bitbucket.org/merijnv/tasty-travis