Turn an Assertion into a tasty test case
Moduletasty-hunit-0.10.2Haskell2010
Test.Tasty.HUnit
Unit testing support for tasty, inspired by the HUnit package.
Here's an example (a single tasty test case consisting of three assertions):
import Test.Tasty
import Test.Tasty.HUnit
main = defaultMain $
testCase "Example test case" $ do
-- assertion no. 1 (passes)
2 + 2 @?= 4
-- assertion no. 2 (fails)
assertBool "the list is not empty" $ null [1]
-- assertion no. 3 (would have failed, but won't be executed because
-- the previous assertion has already failed)
"foo" @?= "bar"- 4 types
- 2 classes
- 10 values
- Packagetasty-hunit-0.10.2
- Exports16
- LanguageHaskell2010
- LicenceMIT
- SourceHUnit.hs
Constructing test cases
3 declarationsLike 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.
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 somethingThe 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.
Constructing assertions
7 declarationsassertFailure :: HasCallStack=> StringA 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
assertBool :: HasCallStack=> StringThe message that is displayed if the assertion fails
-> BoolThe condition
-> Assertion
Asserts that the specified condition holds.
assertEqual :: (Eq a, Show a, HasCallStack)=> StringThe message prefix
-> aThe expected value
-> aThe 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.
Asserts that the specified actual value is equal to the expected value (with the expected value on the left-hand side).
Asserts that the specified actual value is equal to the expected value (with the actual value on the left-hand side).
(@?) :: (AssertionPredicable t, HasCallStack)=> tA value of which the asserted condition is predicated
-> StringA message that is displayed if the assertion fails
-> Assertion
An infix and flipped version of assertBool. E.g. instead of
assertBool "Non-empty list" (null [1])you can write
null [1] @? "Non-empty list"@? is also overloaded to accept IO Bool predicates, so instead
of
do
e <- doesFileExist "test"
e @? "File does not exist"you can write
doesFileExist "test" @? "File does not exist"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
Instances2AssertionPredicable
AssertionPredicable BoolDefined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.OrigAssertionPredicable t => AssertionPredicable (IO t)Defined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.Orig
Data types
2 declarationsAn 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.
Exception thrown by assertFailure etc.
Constructors
Instances3Eq, Show, Exception
Eq HUnitFailureDefined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.OrigShow HUnitFailureDefined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.OrigException HUnitFailureDefined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.Orig
Accurate location for domain-specific assertion functions
1 declarationIt is common to define domain-specific assertion functions based on the standard ones, e.g.
assertNonEmpty = assertBool "List is empty" . not . nullThe problem is that if a test fails, tasty-hunit will point to the
definition site of assertNonEmpty as the source of failure, not
its use site.
To correct this, add a HasCallStack constraint (re-exported from this module) to your function:
assertNonEmpty :: HasCallStack => [a] -> Assertion
assertNonEmpty = assertBool "List is empty" . not . nullRequest 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.
Deprecated functions and types
3 declarationsThese definitions come from HUnit, but I don't see why one would need them. If you have a valid use case for them, please contact me or file an issue for tasty. Otherwise, they will eventually be removed.
assertString :: HasCallStack=> StringThe message that is displayed with the assertion failure
-> Assertion
Deprecated. Why not use assertBool instead?
Signals an assertion failure if a non-empty message (i.e., a message
other than "") is passed.
Deprecated. This class or type seems dubious. If you have a good use case for it, please create an issue for tasty. Otherwise, it may be removed in a future version.
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, Test and
Testable should be used.
Instances4Assertable
Assertable StringDefined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.OrigAssertable BoolDefined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.OrigAssertable ()Defined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.OrigAssertable t => Assertable (IO t)Defined in tasty-hunit-0.10.2 · Test.Tasty.HUnit.Orig
Deprecated. This class or type seems dubious. If you have a good use case for it, please create an issue for tasty. Otherwise, it may be removed in a future version.
The result of an assertion that hasn't been evaluated yet.
Most test cases follow the following steps:
Do some processing or an action.
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:
Write data to a file.
Read data from a file, evaluate conditions.
Clean up the file.
Assert that the side effects of the read operation meet certain conditions.
Assert that the conditions evaluated in step 2 are met.