Kotest is split into several subprojects which can be used independently. One of these subprojects is the comprehensive assertion / matchers support. These can be used with the Kotest test framework, or with another test framework like JUnit or Spock.
The core functionality of the assertion modules are functions that test state. Kotest calls these types of state assertion functions matchers. There are core matchers and matchers for third party libraries.
There are also many other utilities for writing tests, such as testing for exceptions, functions to help test non-determistic code, inspectors for collections, and soft assertions to group assertions.
For example, to assert that a variable has an expected value, we can use the
There are general purpose matchers, such as
shouldBe as well as matchers for many other specific scenarios,
str.shouldHaveLength(10) for testing the length of a string, and
file.shouldBeDirectory() which test
that a particular file points to a directory. They come in both infix and regular variants.
Assertions can generally be chained, for example:
There are over 350 matchers spread across multiple modules. Read about all the matchers here.
Sometimes a failed assertion does not contain enough information to know exactly what went wrong.
If this failed, you would simply get:
Which isn't particularly helpful. We can add extra context to failure messages through the use of clues.
Inspectors allow us to test elements in a collection, and assert the quantity of elements that should be expected to pass (all, none, exactly k and so on). For example
Read about inspectors here
It is easy to add your own matchers. Simply extend the
Matcher<T> interface, where T is the type you wish to match against.
The Matcher interface specifies one method,
test, which you must implement returning an instance of Result.
The Result contains a boolean to indicate if the test passed or failed, and two messages.
Matcher is contravariant so a matcher for Number can be used to test an Int, for example.
The first message should always be in the positive, ie, indicate what "should" happen, and the second message is used when the matcher is used with not.
For example to create a matcher that checks that a string contains the substring "foo", we can do the following:
This matcher could then be used as follows:
And we should then create an extension function version, like this: