Test.Runner.Effectful

A test runner that supports running Tasks.

Running Tests

run : Environment -> Test -> Task (Cmd a)

Run your effectful test suite.

The result of this function should be passed to Node.defineSimpleProgram as part of your main function:

main =
    Node.defineSimpleProgram <|
        run <|
            await (Task.succeed "hi") "my task" <| \val ->
                test "says hi" <| \_ ->
                    Expect.equal "hi" val
runWithOptions : Environment -> Options -> Test -> Task (Cmd a)

Customize a test run with Options.

type alias Options = { runs : Int, seed : Seed }

Options to customize your test run.

  • runs: how many times a fuzz test is run with different inputs.
  • seed: used to generate random input in fuzz tests. A test suite run with the same seed will generate the same fuzz values.
type alias Program a = SimpleProgram a

Type alias for a program that runs your effectful test suite.

Awaiting Tasks

await : Task error a -> String -> (a -> Test) -> Test

Wait for a task to resolve before running a test.

await Time.now "Current time" <| \now ->
    test "is not Jan 1, 1970" <| \_ ->
        Expect.notEqual (Time.millisToPosix 0) now

If the task fails, the inner test won't run and the test suite will fail. If you want to test the error condition of a task, use awaitError.

You can nest as many awaits as you want:

await (Task.succeed "a") "task a" <| \a ->
await (Task.succeed "b") "task b" <| \b ->
    test "are not equal" <| \_ ->
        Expect.notEqual a b
awaitError : Task error a -> String -> (error -> Test) -> Test

Test the error state of a task.

awaitError (Task.fail "oopsy") "An expected failure" <| \error ->
    test "is an oopsy" \_ ->
        Expect.equal "oopsy" error

If the task does not fail, the inner test won't run and the test suite will fail.

These can be nested just like (and alongside) await calls.

Defining Tests

type alias Test = Task Never (InternalTest {})

A test in an effectful test suite.

They can be created with test, fuzz, or several other functions in this module:

import Expect
import Test.Runner.Effectful exposing (test)

test "my test" <| \_ ->
    Expect.equal True True

The semantics are the same as a test from the core test package, except they can wrapped in one or more await or awaitError calls to verify the outcome a Task:

import Expect
import Test.Runner.Effectful exposing (await, test)
import Time

await Time.now "The current time" <| \now ->
    test "is not Jan 1, 1970" <| \_ ->
        Expect.notEqual (Time.millisToPosix 0) now
test : String -> ({} -> Expectation) -> Test

Create a Test.

Test Organization

concat : Array Test -> Test

Group an array of Tests into one.

concat
    [ test "true is true" <| \_ ->
        Expect.equal True True
    , test "false is false" <| \_ ->
        Expect.equal False False
    ]
describe : String -> Array Test -> Test

Group an array of Tests with a description.

describe "Truisms"
    [ test "true is true" <| \_ ->
        Expect.equal True True
    , test "false is false" <| \_ ->
        Expect.equal False False
    ]
todo : String -> Test

Create a Test that is a "TODO" (not yet implemented).

The behavior and API mirrors todo from the core test package.

only : Test -> Test

Create a Test that causes other tests to be skipped, and only runs the given one.

The behavior and API mirrors only from the core test package.

Fuzz Testing

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

Create a "fuzz test".

The behavior and API mirrors fuzz from the core test package.

fuzz2 :
Fuzzer a
-> Fuzzer b
-> String
-> (a -> b -> Expectation)
-> Test

Create a "fuzz test" using two random inputs.

The behavior and API mirrors fuzz2 from the core test package.

fuzz3 :
Fuzzer a
-> Fuzzer b
-> Fuzzer c
-> String
-> (a -> b -> c -> Expectation)
-> Test

Create a "fuzz test" using three random inputs.

The behavior and API mirrors fuzz3 from the core test package.