elm-community/elm-test/2.1.0

NOTE: this package is not compatible with Elm 0.19.1

Test

A module containing functions for creating and managing tests.

type alias Test =
Test

A test which has yet to be evaluated. When evaluated, it produces one or more Expectations.

See test and fuzz for some ways to create a Test.

test : String -> (() -> Expectation) -> Test

Return a Test that evaluates a single Expectation.

import Test exposing (fuzz)
import Expect




test "the empty list has 0 length" <|
    \() ->
        List.length []
            |> Expect.toEqual 0

Organizing Tests

describe : String -> List Test -> Test

Apply a description to a list of tests.

import Test exposing (describe, test, fuzz)
import Fuzz expoing (int)
import Expect




describe "List"
    [ describe "reverse"
        [ test "has no effect on an empty list" <|
            \() ->
                List.reverse []
                    |> Expect.toEqual []
        , fuzz int "has no effect on a one-item list" <|
            \num ->
                 List.reverse [ num ]
                    |> Expect.toEqual [ num ]
        ]
    ]
concat : List Test -> Test

Run each of the given tests.

concat [ testDecoder, testSorting ]
filter : (String -> Bool) -> Test -> Test

Remove any test unless its description satisfies the given predicate function. Nested descriptions added with describe are not considered.

describe "String.reverse"
    [ test "has no effect on a palindrome" testGoesHere
    , test "reverses a known string" anotherTest
    , fuzz string "restores the original string if you run it again" oneMore
    ]
        |> Test.filter (String.contains "original")


-- only runs the final test

You can use this to focus on a specific test or two, silencing the failures of tests you don't want to work on yet, and then remove the call to Test.filter after you're done working on the tests.

Fuzz Testing

fuzz : Fuzzer a -> String -> (a -> Expectation) -> Test

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.

import Test exposing (fuzz)
import Fuzz exposing (list, int)
import Expect




fuzz (list int) "List.length should always be positive" <|
    -- This anonymous function will be run 100 times, each time with a
    -- randomly-generated fuzzList value.
    \fuzzList ->
        fuzzList
            |> List.length
            |> Expect.atLeast 0
fuzz2 : Fuzzer a -> Fuzzer b -> String -> (a -> b -> Expectation) -> Test

Run a fuzz test using two random inputs.

This is a convenicence function that lets you skip calling Fuzz.tuple.

See fuzzWith for an example of writing this in tuple style.

import Test exposing (fuzz2)
import Fuzz exposing (list, int)




fuzz2 (list int) int "List.reverse never influences List.member" <|
    \nums target ->
        List.member target (List.reverse nums)
            |> Expect.toEqual (List.member target nums)
Fuzzer a
-> Fuzzer b
-> Fuzzer c
-> String
-> (a -> b -> c -> Expectation)
-> Test

Run a fuzz test using three random inputs.

This is a convenicence function that lets you skip calling Fuzz.tuple3.

Fuzzer a
-> Fuzzer b
-> Fuzzer c
-> Fuzzer d
-> String
-> (a -> b -> c -> d -> Expectation)
-> Test

Run a fuzz test using four random inputs.

This is a convenicence function that lets you skip calling Fuzz.tuple4.

Fuzzer a
-> Fuzzer b
-> Fuzzer c
-> Fuzzer d
-> Fuzzer e
-> String
-> (a -> b -> c -> d -> e -> Expectation)
-> Test

Run a fuzz test using five random inputs.

This is a convenicence function that lets you skip calling Fuzz.tuple5.

fuzzWith : FuzzOptions -> Fuzzer a -> String -> (a -> Expectation) -> Test

Run a fuzz test with the given FuzzOptions.

Note that there is no fuzzWith2, but you can always pass more fuzz values in using Fuzz.tuple, Fuzz.tuple3, for example like this:

import Test exposing (fuzzWith)
import Fuzz exposing (tuple, list, int)
import Expect




fuzzWith { runs = 4200 }
    (tuple ( list int, int ))
    "List.reverse never influences List.member" <|
        \(nums, target) ->
            List.member target (List.reverse nums)
                |> Expect.toEqual (List.member target nums)
type alias FuzzOptions =
{ runs : Int }

Options fuzzWith accepts. Currently there is only one but this API is designed so that it can accept more in the future.

runs

The number of times to run each fuzz test. (Default is 100.)

import Test exposing (fuzzWith)
import Fuzz exposing (list, int)
import Expect




fuzzWith { runs = 350 } (list int) "List.length should always be positive" <|
    -- This anonymous function will be run 350 times, each time with a
    -- randomly-generated fuzzList value. (It will always be a list of ints
    -- because of (list int) above.)
    \fuzzList ->
        fuzzList
            |> List.length
            |> Expect.atLeast 0