From a23bac268515af2c66dbb0dbc3ec94d57694cdab Mon Sep 17 00:00:00 2001 From: Bodigrim Date: Wed, 17 Jul 2024 20:56:57 +0100 Subject: [PATCH 1/2] Revert "Simplify further: \r is sufficient to clear whole line, no need for additional escape sequence" This reverts commit b152a0bc63166a4592e1f3639ef09e78a43f2b57. In fact, unless in Emacs, \r is not sufficient to clear the whole line. --- core/Test/Tasty/Ingredients/ConsoleReporter.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/Test/Tasty/Ingredients/ConsoleReporter.hs b/core/Test/Tasty/Ingredients/ConsoleReporter.hs index 6bda388b..10693242 100644 --- a/core/Test/Tasty/Ingredients/ConsoleReporter.hs +++ b/core/Test/Tasty/Ingredients/ConsoleReporter.hs @@ -169,9 +169,10 @@ buildTestOutput opts tree = ("", pct) -> printf "%.0f%% " pct (txt, 0.0) -> printf "%s" txt (txt, pct) -> printf "%s: %.0f%% " txt pct + putChar '\r' -- A new progress message may be shorter than the previous one -- so we must clean whole line and print anew. - putChar '\r' + clearLine putStr testNamePadded infoOk msg hFlush stdout @@ -190,6 +191,7 @@ buildTestOutput opts tree = when getAnsiTricks $ do putChar '\r' + clearLine putStr testNamePadded printFn (resultShortDescription result) From 3f95f549cedbaf393b37126fb5edb258df5cd290 Mon Sep 17 00:00:00 2001 From: Bodigrim Date: Wed, 17 Jul 2024 20:58:02 +0100 Subject: [PATCH 2/2] QuickCheck: implement --quickcheck-timeout for individual tests within a property --- quickcheck/CHANGELOG.md | 5 +++++ quickcheck/Test/Tasty/QuickCheck.hs | 24 ++++++++++++++++++++++-- quickcheck/tasty-quickcheck.cabal | 2 +- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/quickcheck/CHANGELOG.md b/quickcheck/CHANGELOG.md index ddbd82c6..2d2eaff2 100644 --- a/quickcheck/CHANGELOG.md +++ b/quickcheck/CHANGELOG.md @@ -1,6 +1,11 @@ Changes ======= +Version 0.11.1 +-------------- + +* Add timeouts for individual tests within a property. + Version 0.11 -------------- diff --git a/quickcheck/Test/Tasty/QuickCheck.hs b/quickcheck/Test/Tasty/QuickCheck.hs index 3e8ca625..fa1a5b15 100644 --- a/quickcheck/Test/Tasty/QuickCheck.hs +++ b/quickcheck/Test/Tasty/QuickCheck.hs @@ -10,6 +10,7 @@ module Test.Tasty.QuickCheck , QuickCheckMaxRatio(..) , QuickCheckVerbose(..) , QuickCheckMaxShrinks(..) + , QuickCheckTimeout(..) -- * Re-export of Test.QuickCheck , module Test.QuickCheck -- * Internal @@ -20,7 +21,7 @@ module Test.Tasty.QuickCheck , optionSetToArgs ) where -import Test.Tasty ( testGroup ) +import Test.Tasty ( testGroup, Timeout(..) ) import Test.Tasty.Providers import Test.Tasty.Options import qualified Test.QuickCheck as QC @@ -118,6 +119,12 @@ newtype QuickCheckVerbose = QuickCheckVerbose Bool newtype QuickCheckMaxShrinks = QuickCheckMaxShrinks Int deriving (Num, Ord, Eq, Real, Enum, Integral, Typeable) +-- | Timeout for individual tests within a property. +-- +-- @since 0.11.1 +newtype QuickCheckTimeout = QuickCheckTimeout Timeout + deriving (Eq, Ord, Typeable) + instance IsOption QuickCheckTests where defaultValue = 100 parseValue = @@ -175,6 +182,13 @@ instance IsOption QuickCheckMaxShrinks where optionHelp = return "Number of shrinks allowed before QuickCheck will fail a test" optionCLParser = mkOptionCLParser $ metavar "NUMBER" +instance IsOption QuickCheckTimeout where + defaultValue = QuickCheckTimeout defaultValue + parseValue = fmap QuickCheckTimeout . parseValue + optionName = return "quickcheck-timeout" + optionHelp = return "Timeout for individual tests within a QuickCheck property (suffixes: ms,s,m,h; default: s)" + optionCLParser = mkOptionCLParser $ metavar "DURATION" + -- | Convert tasty options into QuickCheck options. -- -- This is a low-level function that was originally added for tasty-hspec @@ -221,6 +235,7 @@ instance IsTest QC where , Option (Proxy :: Proxy QuickCheckMaxRatio) , Option (Proxy :: Proxy QuickCheckVerbose) , Option (Proxy :: Proxy QuickCheckMaxShrinks) + , Option (Proxy :: Proxy QuickCheckTimeout) ] run opts (QC prop) yieldProgress = do @@ -228,11 +243,16 @@ instance IsTest QC where let QuickCheckShowReplay showReplay = lookupOption opts QuickCheckVerbose verbose = lookupOption opts + QuickCheckTimeout timeout = lookupOption opts + applyTimeout = case timeout of + Timeout micros _ + | micros <= toInteger (maxBound :: Int) -> QC.within (fromInteger micros) + _ -> id -- Quickcheck already catches exceptions, no need to do it here. r <- quickCheck yieldProgress args - (if verbose then QC.verbose prop else prop) + (applyTimeout $ if verbose then QC.verbose prop else prop) qcOutput <- formatMessage $ QC.output r let qcOutputNl = diff --git a/quickcheck/tasty-quickcheck.cabal b/quickcheck/tasty-quickcheck.cabal index fb1ca921..6a27fedc 100644 --- a/quickcheck/tasty-quickcheck.cabal +++ b/quickcheck/tasty-quickcheck.cabal @@ -29,7 +29,7 @@ library other-extensions: GeneralizedNewtypeDeriving, DeriveDataTypeable build-depends: base >= 4.8 && < 5, tagged < 0.9, - tasty >= 1.5 && < 1.6, + tasty >= 1.5.1 && < 1.6, random < 1.3, QuickCheck >= 2.10 && < 2.16, optparse-applicative < 0.19