{-# LANGUAGE NumericUnderscores #-}
module Main (main) where
import Control.Monad ( unless )
import Control.Concurrent ( threadDelay )
import Data.IORef as IORef
import Test.Tasty ( TestTree, testGroup, defaultMain, withResource )
import Test.Tasty.Flaky ( limitRetries, flakyTest )
import Test.Tasty.HUnit ( testCase, assertFailure )
import Control.Exception (throwIO)
main :: IO ()
main = defaultMain
$ testGroup "Test suite"
[ testSuccessOnFirstTry
, testFlakyWithRetries
, testFlakyWithException
, testFlakyWithRetriesProgressCallback
]
testSuccessOnFirstTry :: TestTree
testSuccessOnFirstTry = flakyTest (limitRetries 0) $ testCase "succeeds on the first try" $ do
pure ()
-- This test will fail until the contents of the IORef is zero
testFlakyWithRetries :: TestTree
testFlakyWithRetries
= flakyTest (limitRetries 4)
$ withResource (IORef.newIORef (3 :: Int)) (const $ pure ())
$ \getioref -> testCase "effectful" $ do
ioref <- getioref
n <- IORef.readIORef ioref
unless (n == 0) $ do
IORef.modifyIORef' ioref (\m -> m - 1)
assertFailure "Not yet"
-- This test will throw an exception until the contents of the IORef is zero
testFlakyWithException :: TestTree
testFlakyWithException
= flakyTest (limitRetries 4)
$ withResource (IORef.newIORef (3 :: Int)) (const $ pure ())
$ \getioref -> testCase "exception" $ do
ioref <- getioref
n <- IORef.readIORef ioref
unless (n == 0) $ do
IORef.modifyIORef' ioref (\m -> m - 1)
throwIO $ userError "Oh no!"
-- This test will fail until the contents of the IORef is zero
testFlakyWithRetriesProgressCallback :: TestTree
testFlakyWithRetriesProgressCallback
= flakyTest (limitRetries 4)
$ withResource (IORef.newIORef (3 :: Int)) (const $ pure ())
$ \getioref -> testCase "Showcasing progress report" $ do
-- Wait 1 second for tasty to consider this test 'long-running'
threadDelay 1_000_000
ioref <- getioref
n <- IORef.readIORef ioref
unless (n == 0) $ do
IORef.modifyIORef' ioref (\m -> m - 1)
assertFailure "Not yet"