broadcast-chan-tests-0.2.1.1: Helpers for generating tests for broadcast-chan

Copyright(C) 2014-2018 Merijn Verstraaten
LicenseBSD-style (see the file LICENSE)
MaintainerMerijn Verstraaten <merijn@inconsistent.nl>
Stabilityexperimental
Portabilityhaha
Safe HaskellTrustworthy
LanguageHaskell2010

BroadcastChan.Test

Contents

Description

Module containing testing helpers shared across all broadcast-chan packages.

Synopsis

Documentation

(@?) :: IO Bool -> String -> Assertion infix 0 Source #

Monomorphised version of @? to avoid ambiguous type errors when combined with predicates that are MonadIO m => m Bool.

expect :: (Eq e, Exception e) => e -> IO () -> Assertion Source #

Test which fails if the expected exception is not thrown by the IO action.

genStreamTests Source #

Arguments

:: (Eq r, Show r) 
=> String

Name to group tests under

-> ([Int] -> (Int -> IO Int) -> IO r)

Sequential sink

-> (Handler IO Int -> [Int] -> (Int -> IO Int) -> Int -> IO r)

Parallel sink

-> TestTree 

Takes a name, a sequential sink, and a parallel sink and generates tasty tests from these.

The parallel and sequential sink should perform the same tasks so their results can be compared to check correctness.

The sinks should take a list of input data, a function processing the data, and return a result that can be compared for equality.

Furthermore the parallel sink should take a number indicating how many concurrent consumers should be used.

runTests :: String -> [TestTree] -> IO () Source #

Run a list of TestTree​'s and group them under the specified name.

withLoggedOutput :: FilePath -> (Handle -> IO r) -> IO (r, Text) Source #

Run an IO action while logging the output to a Handle. Returns the result and the logged output.

class Monad m => MonadIO (m :: Type -> Type) where #

Monads in which IO computations may be embedded. Any monad built by applying a sequence of monad transformers to the IO monad will be an instance of this class.

Instances should satisfy the following laws, which state that liftIO is a transformer of monads:

Methods

liftIO :: IO a -> m a #

Lift a computation from the IO monad.

Instances
MonadIO IO

Since: base-4.9.0.0

Instance details

Defined in Control.Monad.IO.Class

Methods

liftIO :: IO a -> IO a #

MonadIO Q 
Instance details

Defined in Language.Haskell.TH.Syntax

Methods

liftIO :: IO a -> Q a #

(Error e, MonadIO m) => MonadIO (ErrorT e m) 
Instance details

Defined in Control.Monad.Trans.Error

Methods

liftIO :: IO a -> ErrorT e m a #

mapHandler :: (m Action -> n Action) -> Handler m a -> Handler n a #

Convenience function for changing the monad the exception handler runs in.

Re-exports of tasty and tasty-hunit

module Test.Tasty

type HasCallStack = ?callStack :: CallStack #

Request a CallStack.

NOTE: The implicit parameter ?callStack :: CallStack is an implementation detail and should not be considered part of the CallStack API, we may decide to change the implementation in the future.

Since: base-4.9.0.0

testCaseInfo :: TestName -> IO String -> TestTree #

Like testCase, except in case the test succeeds, the returned string will be shown as the description. If the empty string is returned, it will be ignored.

testCase :: TestName -> Assertion -> TestTree #

Turn an Assertion into a tasty test case

testCaseSteps :: TestName -> ((String -> IO ()) -> Assertion) -> TestTree #

Create a multi-step unit test.

Example:

main = defaultMain $ testCaseSteps "Multi-step test" $ \step -> do
  step "Preparing..."
  -- do something

  step "Running part 1"
  -- do something

  step "Running part 2"
  -- do something
  assertFailure "BAM!"

  step "Running part 3"
  -- do something

The step calls are mere annotations. They let you see which steps were performed successfully, and which step failed.

You can think of step as putStrLn, except putStrLn would mess up the output with the console reporter and get lost with the others.

For the example above, the output will be

Multi-step test: FAIL
  Preparing...
  Running part 1
  Running part 2
    BAM!

1 out of 1 tests failed (0.00s)

Note that:

  • Tasty still treats this as a single test, even though it consists of multiple steps.
  • The execution stops after the first failure. When we are looking at a failed test, we know that all displayed steps but the last one were successful, and the last one failed. The steps after the failed one are not displayed, since they didn't run.

assertString #

Arguments

:: HasCallStack

The message that is displayed with the assertion failure

-> String 
-> Assertion 

Signals an assertion failure if a non-empty message (i.e., a message other than "") is passed.

(@?=) infix 1 #

Arguments

:: (Eq a, Show a, HasCallStack) 
=> a

The actual value

-> a

The expected value

-> Assertion 

Asserts that the specified actual value is equal to the expected value (with the actual value on the left-hand side).

(@=?) infix 1 #

Arguments

:: (Eq a, Show a, HasCallStack) 
=> a

The expected value

-> a

The actual value

-> Assertion 

Asserts that the specified actual value is equal to the expected value (with the expected value on the left-hand side).

assertEqual #

Arguments

:: (Eq a, Show a, HasCallStack) 
=> String

The message prefix

-> a

The expected value

-> a

The actual value

-> Assertion 

Asserts that the specified actual value is equal to the expected value. The output message will contain the prefix, the expected value, and the actual value.

If the prefix is the empty string (i.e., ""), then the prefix is omitted and only the expected and actual values are output.

assertBool #

Arguments

:: HasCallStack

The message that is displayed if the assertion fails

-> String

The condition

-> Bool 
-> Assertion 

Asserts that the specified condition holds.

assertFailure #

Arguments

:: HasCallStack 
=> String

A message that is displayed with the assertion failure

-> IO a 

Unconditionally signals that a failure has occured. All other assertions can be expressed with the form:

   if conditionIsMet
       then return ()
       else assertFailure msg

type Assertion = IO () #

An assertion is simply an IO action. Assertion failure is indicated by throwing an exception, typically HUnitFailure.

Instead of throwing the exception directly, you should use functions like assertFailure and assertBool.

Test cases are composed of a sequence of one or more assertions.

class AssertionPredicable t where #

An ad-hoc class used to overload the @? operator.

The only intended instances of this class are Bool and IO Bool.

You shouldn't need to interact with this class directly.

Methods

assertionPredicate :: t -> IO Bool #

Instances
AssertionPredicable Bool 
Instance details

Defined in Test.Tasty.HUnit.Orig

AssertionPredicable t => AssertionPredicable (IO t) 
Instance details

Defined in Test.Tasty.HUnit.Orig

Methods

assertionPredicate :: IO t -> IO Bool #

class Assertable t where #

Allows the extension of the assertion mechanism.

Since an Assertion can be a sequence of Assertions and IO actions, there is a fair amount of flexibility of what can be achieved. As a rule, the resulting Assertion should be the body of a TestCase or part of a TestCase; it should not be used to assert multiple, independent conditions.

If more complex arrangements of assertions are needed, Tests and Testable should be used.

Methods

assert :: t -> Assertion #

Instances
Assertable Bool 
Instance details

Defined in Test.Tasty.HUnit.Orig

Methods

assert :: Bool -> Assertion #

Assertable () 
Instance details

Defined in Test.Tasty.HUnit.Orig

Methods

assert :: () -> Assertion #

Assertable String 
Instance details

Defined in Test.Tasty.HUnit.Orig

Methods

assert :: String -> Assertion #

Assertable t => Assertable (IO t) 
Instance details

Defined in Test.Tasty.HUnit.Orig

Methods

assert :: IO t -> Assertion #

type AssertionPredicate = IO Bool #

The result of an assertion that hasn't been evaluated yet.

Most test cases follow the following steps:

  1. Do some processing or an action.
  2. Assert certain conditions.

However, this flow is not always suitable. AssertionPredicate allows for additional steps to be inserted without the initial action to be affected by side effects. Additionally, clean-up can be done before the test case has a chance to end. A potential work flow is:

  1. Write data to a file.
  2. Read data from a file, evaluate conditions.
  3. Clean up the file.
  4. Assert that the side effects of the read operation meet certain conditions.
  5. Assert that the conditions evaluated in step 2 are met.