Skip to content

Commit a551127

Browse files
gridaphobeUnkindPartition
authored andcommitted
Add resultTime field to T.T.Core.Result.
`resultTime` is initialized to 0 by default, and then overriden with the actual test time by `executeTest`. `TestReporter`s reporter is modified to return a continuation that accepts the runtime of the entire suite before finishing.
1 parent c89c3a7 commit a551127

File tree

8 files changed

+49
-22
lines changed

8 files changed

+49
-22
lines changed

core-tests/Resources.hs

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ testResources1 = testCase "Normal; a test excluded by a pattern" $ do
5959
rs <- runSMap smap
6060
assertBool "Resource is not available" $ all resultSuccessful rs
6161
readIORef ref >>= assertBool "Resource was not released" . not
62+
return $ const $ return ()
6263

6364
------------------------------
6465
-- Exceptions
@@ -76,6 +77,7 @@ testResources2 = testCase "Exception during resource initialization" $
7677
Failure (TestThrewException (fromException -> Just (ErrorCall "exInit"))) ->
7778
return ()
7879
c -> assertFailure $ "Unexpected outcome: " ++ show c
80+
return $ const $ return ()
7981

8082
testTree3 :: IORef Bool -> TestTree
8183
testTree3 ref =
@@ -93,6 +95,7 @@ testResources3 = testCase "Exception in test body; resource is released" $ do
9395
c -> assertFailure $ "Unexpected outcome: " ++ show c
9496
b <- readIORef ref
9597
assertBool "Resource wasn't released" (not b)
98+
return $ const $ return ()
9699

97100
testTree4 :: IORef Bool -> TestTree
98101
testTree4 ref =
@@ -108,3 +111,4 @@ testResources4 = testCase "Exception in finalizer" $ do
108111
Failure (TestThrewException (fromException -> Just (ErrorCall "exFin"))) ->
109112
return ()
110113
c -> assertFailure $ "Unexpected outcome: " ++ show c
114+
return $ const $ return ()

core-tests/Timeouts.hs

+1
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@ testTimeouts = testCase "Timeouts" $ do
3131
Result { resultOutcome = Success } -> assertFailure "Slow test passed"
3232
Result { resultOutcome = Failure (TestTimedOut 200000) } -> return ()
3333
_ -> assertFailure $ "Slow test failed for wrong reason: " ++ resultDescription fast
34+
return $ const $ return ()

core/Test/Tasty/Core.hs

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ data Result = Result
5050
--
5151
-- For a failed test, 'resultDescription' should typically provide more
5252
-- information about the failure.
53+
, resultTime :: Double
54+
-- ^ How long it took to run the test, in seconds.
5355
}
5456

5557
-- | 'True' for a passed test, 'False' for a failed one.
@@ -64,6 +66,7 @@ exceptionResult :: SomeException -> Result
6466
exceptionResult e = Result
6567
{ resultOutcome = Failure $ TestThrewException e
6668
, resultDescription = "Exception: " ++ show e
69+
, resultTime = 0
6770
}
6871

6972
-- | Test progress information.

core/Test/Tasty/Ingredients.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ import Test.Tasty.Options.Core
6464
data Ingredient
6565
= TestReporter
6666
[OptionDescription]
67-
(OptionSet -> TestTree -> Maybe (StatusMap -> IO Bool))
67+
(OptionSet -> TestTree -> Maybe (StatusMap -> IO (Double -> IO Bool)))
6868
| TestManager
6969
[OptionDescription]
7070
(OptionSet -> TestTree -> Maybe (IO Bool))

core/Test/Tasty/Ingredients/ConsoleReporter.hs

+11-10
Original file line numberDiff line numberDiff line change
@@ -305,16 +305,17 @@ consoleTestReporter =
305305
| otherwise -> consoleOutput output smap
306306
}
307307

308-
if quiet
309-
then do
310-
fst <- failureStatus smap
311-
return $ case fst of
312-
OK -> True
313-
_ -> False
314-
else do
315-
stats <- computeStatistics smap
316-
printStatistics stats
317-
return $ statFailures stats == 0
308+
return $ \time ->
309+
if quiet
310+
then do
311+
fst <- failureStatus smap
312+
return $ case fst of
313+
OK -> True
314+
_ -> False
315+
else do
316+
stats <- computeStatistics smap
317+
printStatistics stats
318+
return $ statFailures stats == 0
318319

319320
-- | Do not print test results (see README for details)
320321
newtype Quiet = Quiet Bool

core/Test/Tasty/Providers.hs

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ testPassed
2424
testPassed desc = Result
2525
{ resultOutcome = Success
2626
, resultDescription = desc
27+
, resultTime = 0
2728
}
2829

2930
-- | 'Result' of a failed test
@@ -33,4 +34,5 @@ testFailed
3334
testFailed desc = Result
3435
{ resultOutcome = Failure TestFailed
3536
, resultDescription = desc
37+
, resultTime = 0
3638
}

core/Test/Tasty/Run.hs

+25-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
-- | Running tests
2-
{-# LANGUAGE ScopedTypeVariables, ExistentialQuantification, RankNTypes, FlexibleContexts #-}
2+
{-# LANGUAGE ScopedTypeVariables, ExistentialQuantification, RankNTypes,
3+
FlexibleContexts, BangPatterns #-}
34
module Test.Tasty.Run
45
( Status(..)
56
, StatusMap
@@ -10,6 +11,7 @@ import qualified Data.IntMap as IntMap
1011
import qualified Data.Sequence as Seq
1112
import qualified Data.Foldable as F
1213
import Data.Maybe
14+
import Data.Time.Clock.POSIX
1315
import Control.Monad.State
1416
import Control.Monad.Writer
1517
import Control.Monad.Reader
@@ -95,15 +97,15 @@ executeTest action statusVar timeoutOpt inits fins = mask $ \restore -> do
9597
-- handler doesn't interfere with our timeout.
9698
withAsync (action yieldProgress) $ \asy -> do
9799
labelThread (asyncThreadId asy) "tasty_test_execution_thread"
98-
applyTimeout timeoutOpt $ wait asy
100+
timed $ applyTimeout timeoutOpt $ wait asy
99101

100102
-- no matter what, try to run each finalizer
101103
mbExn <- destroyResources restore
102104

103105
atomically . writeTVar statusVar $ Done $
104106
case resultOrExn <* maybe (Right ()) Left mbExn of
105107
Left ex -> exceptionResult ex
106-
Right r -> r
108+
Right (t,r) -> r { resultTime = t }
107109

108110
where
109111
initResources :: IO ()
@@ -138,6 +140,7 @@ executeTest action statusVar timeoutOpt inits fins = mask $ \restore -> do
138140
{ resultOutcome = Failure $ TestTimedOut t
139141
, resultDescription =
140142
"Timed out after " ++ tstr
143+
, resultTime = fromIntegral t
141144
}
142145
fromMaybe timeoutResult <$> timeout t a
143146

@@ -244,17 +247,19 @@ getResource var =
244247
launchTestTree
245248
:: OptionSet
246249
-> TestTree
247-
-> (StatusMap -> IO a)
250+
-> (StatusMap -> IO (Double -> IO a))
248251
-> IO a
249252
launchTestTree opts tree k = do
250253
(testActions, rvars) <- createTestActions opts tree
251254
let NumThreads numTheads = lookupOption opts
252-
abortTests <- runInParallel numTheads (fst <$> testActions)
253-
(do let smap = IntMap.fromList $ zip [0..] (snd <$> testActions)
254-
k smap)
255-
`finally` do
256-
abortTests
257-
waitForResources rvars
255+
(t,k) <- timed $ do
256+
abortTests <- runInParallel numTheads (fst <$> testActions)
257+
(do let smap = IntMap.fromList $ zip [0..] (snd <$> testActions)
258+
k smap)
259+
`finally` do
260+
abortTests
261+
waitForResources rvars
262+
k t
258263
where
259264
alive :: Resource r -> Bool
260265
alive r = case r of
@@ -271,3 +276,13 @@ launchTestTree opts tree k = do
271276

272277
unexpectedState :: String -> Resource r -> SomeException
273278
unexpectedState where_ r = toException $ UnexpectedState where_ (show r)
279+
280+
timed :: IO a -> IO (Double, a)
281+
timed t = do
282+
start <- getTime
283+
!r <- t
284+
end <- getTime
285+
return (end-start, r)
286+
287+
getTime :: IO Double
288+
getTime = realToFrac <$> getPOSIXTime

core/tasty.cabal

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ library
5757
deepseq >= 1.3,
5858
unbounded-delays >= 0.1,
5959
async >= 2.0,
60-
ansi-terminal >= 0.6.1
60+
ansi-terminal >= 0.6.1,
61+
time >= 1.4
6162

6263
if impl(ghc < 7.6)
6364
-- for GHC.Generics

0 commit comments

Comments
 (0)