Skip to content

…from kotlin.test

Keep your assertions🔗

You can keep your assertion library (most assertion libraries work out of the box, for Kotest Assertions there is a TestBalloon integration for it). Code inside tests can remain unchanged.

What needs to change🔗

Test Classes and Methods🔗

Top-level test classes become top-level suite properties. Test methods become test function invocations:

class KotlinTestBasics {
    @Test
    fun expected_to_pass() {
        assertEquals(4, 2 + 2)
    }

    @Test
    fun expected_to_fail() {
        assertEquals(5, 2 + 2)
    }
}
val FromKotlinTestBasics by testSuite {
    test("expected to pass") {
        assertEquals(4, 2 + 2)
    }

    test("expected to fail") {
        assertEquals(5, 2 + 2)
    }
}

Class properties, setup and teardown🔗

Keep your code inside tests, and

  1. wrap kotlin.test class properties into a fixture, omitting var and lateinit,
  2. omit runTest,
  3. co-locate setup code with initialization,
  4. use the optional closeWith lambda for tear-down code,
  5. make it a test-level fixture, providing a fresh value to each test:
class KotlinTestFixture {
    private lateinit var service: WeatherService

    @BeforeTest
    fun setup() = runTest {
        service = FakeWeatherService()
        service.connect(token = "TestToken")
    }

    @AfterTest
    fun teardown() = runTest {
        service.disconnect()
    }

    @Test
    fun `Temperature in Hamburg is 21_5 °C`() = runTest {
        assertEquals(21.5, service.location("Hamburg").temperature)
    }

    // more tests...
}
val FromKotlinTestFixture by testSuite {
    testFixture {
        FakeWeatherService().apply {
            connect(token = "TestToken") // (1)!
        }
    } closeWith {
        disconnect() // (2)!
    } asParameterForEach { // (3)!

        test("Temperature in Hamburg is 21.5 °C") { service ->
            assertEquals(21.5, service.location("Hamburg").temperature)
        }

        // more tests...
    }
}
  1. As the testFixture lambda is suspending, you can co-locate any setup code here.
  2. A suspending tear-down function.
  3. Making it a test-level fixture provides a fresh, isolated value as a parameter for each test.

Tip

For a fixture with multiple properties, use an object expression and provide it via asContextForEach to each test.

Other🔗

To @Ignore a test or suite, pass testConfig = TestConfig.disable() as a parameter to the test or testSuite function.

To migrate @BeforeClass and @AfterClass (which kotlin.test provides on Native), see the corresponding JUnit section on sharing state across tests.