Safe Haskell | None |
---|---|
Language | Haskell2010 |
A module containing functions for creating and managing tests.
Synopsis
- data Test
- test :: HasCallStack => Text -> (() -> Expectation) -> Test
- describe :: Text -> [Test] -> Test
- skip :: Test -> Test
- only :: Test -> Test
- todo :: HasCallStack => Text -> Test
- fuzz :: (HasCallStack, Show a) => Fuzzer a -> Text -> (a -> Expectation) -> Test
- fuzz2 :: (HasCallStack, Show a, Show b) => Fuzzer a -> Fuzzer b -> Text -> (a -> b -> Expectation) -> Test
- fuzz3 :: (HasCallStack, Show a, Show b, Show c) => Fuzzer a -> Fuzzer b -> Fuzzer c -> Text -> (a -> b -> c -> Expectation) -> Test
- run :: HasCallStack => Test -> IO ()
Organizing Tests
A test which has yet to be evaluated. When evaluated, it produces one
or more Expectation
s.
See test
and fuzz
for some ways to create a Test
.
test :: HasCallStack => Text -> (() -> Expectation) -> Test Source #
Return a Test
that evaluates a single
Expectation
import Test (fuzz) import Expect test "the empty list has 0 length" <| \_ -> List.length [] |> Expect.equal 0
describe :: Text -> [Test] -> Test Source #
Apply a description to a list of tests.
import Test (describe, test, fuzz) import Fuzz (int) import Expect describe "List" [ describe "reverse" [ test "has no effect on an empty list" <| \_ -> List.reverse [] |> Expect.equal [] , fuzz int "has no effect on a one-item list" <| \num -> List.reverse [ num ] |> Expect.equal [ num ] ] ]
Passing an empty list will result in a failing test, because you either made a mistake or are creating a placeholder.
Returns a Test
that gets skipped.
Calls to skip
aren't meant to be committed to version control. Instead,
use it when you want to focus on getting a particular subset of your tests
to pass. If you use skip
, your entire test suite will fail, even if each
of the individual tests pass. This is to help avoid accidentally committing
a skip
to version control.
See also only
. Note that skip
takes precedence over only
; if you use a
skip
inside an only
, it will still get skipped, and if you use an only
inside a skip
, it will also get skipped.
describe "List" [ skip <| describe "reverse" [ test "has no effect on an empty list" <| \_ -> List.reverse [] |> Expect.equal [] , fuzz int "has no effect on a one-item list" <| \num -> List.reverse [ num ] |> Expect.equal [ num ] ] , test "This is the only test that will get run; the other was skipped!" <| \_ -> List.length [] |> Expect.equal 0 ]
Returns a Test
that causes other tests to be skipped, and only runs the given one.
Calls to only
aren't meant to be committed to version control. Instead,
use them when you want to focus on getting a particular subset of your tests
to pass. If you use only
, your entire test suite will fail, even if each
of the individual tests pass. This is to help avoid accidentally committing
a only
to version control.
If you you use only
on multiple tests, only those tests will run. If you
put a only
inside another only
, only the outermost only
will affect
which tests gets run. See also skip
. Note that skip
takes precedence
over only
; if you use a skip
inside an only
, it will still get
skipped, and if you use an only
inside a skip
, it will also get skipped.
describe "List" [ only <| describe "reverse" [ test "has no effect on an empty list" <| \_ -> List.reverse [] |> Expect.equal [] , fuzz int "has no effect on a one-item list" <| \num -> List.reverse [ num ] |> Expect.equal [ num ] ] , test "This will not get run, because of the @only@ above!" <| \_ -> List.length [] |> Expect.equal 0 ]
todo :: HasCallStack => Text -> Test Source #
Returns a Test
that is "todo" (not yet implemented). These tests always
fail.
These tests aren't meant to be committed to version control. Instead, use
them when you're brainstorming lots of tests you'd like to write, but you
can't implement them all at once. When you replace todo
with a real test,
you'll be able to see if it fails without clutter from tests still not
implemented. But, unlike leaving yourself comments, you'll be prompted to
implement these tests because your suite will fail.
describe "a new thing" [ todo "does what is expected in the common case" , todo "correctly handles an edge case I just thought of" ]
This functionality is similar to "pending" tests in other frameworks, except that a todo test is considered failing but a pending test often is not.
Fuzz Testing
fuzz :: (HasCallStack, Show a) => Fuzzer a -> Text -> (a -> Expectation) -> Test Source #
Take a function that produces a test, and calls it several (usually 100)
times, using a randomly-generated input from a Fuzzer
each time. This
allows you to test that a property that should always be true is indeed true
under a wide variety of conditions. The function also takes a string
describing the test.
These are called "fuzz tests" because of the randomness. You may find them elsewhere called property-based tests, generative tests, or QuickCheck-style tests.
fuzz2 :: (HasCallStack, Show a, Show b) => Fuzzer a -> Fuzzer b -> Text -> (a -> b -> Expectation) -> Test Source #
Run a fuzz test using two random inputs.
fuzz3 :: (HasCallStack, Show a, Show b, Show c) => Fuzzer a -> Fuzzer b -> Fuzzer c -> Text -> (a -> b -> c -> Expectation) -> Test Source #
Run a fuzz test using three random inputs.