Suite
Declare coroutine-aware tests programmatically with time control and lazy values.
This module defines the constructs of the Prepared test framework, namely ways to declare tests, control the time, and declare test dependencies.
Prepared is only about the way tests are declared and structured: you can continue using your favorite assertion library. We also provide compatibility modules for popular test runners, so you can benefit from Prepared without rewriting your existing tests.
Declare tests
Tests are declared in hierarchical suites:
suite("Feature name") {
suite("Feature use-case") {
test("Test case 1") {
// test code…
}
test("Test case 2") {
// test code…
}
}
}
This has two main consequences:
To learn more, see SuiteDsl and TestDsl.
Coroutine-aware
Prepared tests are coroutine-aware, which provides a few interesting features:
Prepared values
Most testing frameworks define ways to declare “code that needs to be executed before the test happens”. This may be anything from connecting to a database, to setting up test fixtures. However, doing this:
Instead, we declare Prepared values: lazy operations that are explicitly invoked in tests. Their values are only computed in the context of a test, and each test gets its own execution:
suite("Feature name") {
val prepareDatabase by prepared { FakeDatabase.connect() }
test("Test case 1") {
val database = prepareDatabase()
database.foo()
}
test("Test case 2") {
val database = prepareDatabase()
database.bar()
}
test("Test case 3") {
somethingElse()
}
}
In the above example, the first and second test both get their own fake database. The third test doesn't refer to the database, so it is not instantiated.
Prepared values have a few other properties:
To learn more, see prepared.
Control the time
We often write algorithms that depend on the current time. Sometimes, we discover bugs that only happen at rare times, for example during daylight savings transitions, when the year changes, or in leap years.
To avoid these issues, it is recommended to inject some kind of clock into all algorithms that depend on the current time, or that need to measure how time passes.
Inside Prepared tests, the time accessor exposes methods to control how time passes:
To learn more, see time. Compatibility with other time management libraries (e.g. KotlinX.Datetime) are provided as optional dependencies.
Control random values
Randomness is useful to generate test data, but it makes reproducing test failures harder.
Prepared exposes utilities to generate reproducible random tests:
To learn more, see random.