Unit Testing

Unit Testing

You are expected to write comprehensive unit tests along-side your source code. This means that you should be producing unit tests at each phase of your project, and you are expected to demonstrate working features with corresponding tests for each demo.

Setup

You should be using the Kotlin-native test framework. You can install this bny adding the following to your build.gradle.kts - either the module-level file, or at the root to apply to multiple modules.

dependencies {
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}

Creating Tests

Your tests should be created in a test folder that corresponds to your src folder; do not place tests alongside their source files. If you have multiple modules, then each module should have its own tests.

For example, here’s a folder structure for shared module (e.g., namespace is shared.common, shared.database and so on). Each folder contains multiple tests corresponding to a file under the source tree.

├── main
│   ├── kotlin
│   │   └── shared
│   │       ├── common
│   │       ├── database
│   │       ├── domain
│   │       ├── model
│   │       ├── service
│   │       └── settings
│   └── resources
│       └── local.properties
└── test
    ├── kotlin
    │   └── shared
    │       ├── database
    │       ├── domain
    │       ├── model
    │       ├── service
    │       └── settings
    └── resources
        └── local.properties

When creating tests, make sure to import the kotlin test namespace, and classes. Use the asserts provided by that framework.

// Create a class to test under src/main/kotlin.
class Sample() {
    fun sum(a: Int, b: Int): Int {
        return a + b
    }
}

// Create a test class under src/test/kotlin. Add functions as tests.
import kotlin.test.Test
import kotlin.test.assertEquals

@Test
internal class SampleTest {
    @Test
    fun testSum() {
        val testSample = Sample()
        assertEquals(42, testSample.sum(40, 2))
    }
}

What To Test

You should aim to have some level of testing for each class and function that you write.

Some guidelines:

  • Be pragmatic. Prioritize your tests, so that the most important and frequently used parts of your code have the more comprehensive test coverage.
  • You will not get to 100% coverage with anything (nor should you try to).
  • For “edges” of your architecture, use mocks. e.g., database, service layers.
  • For user interfaces, write unit tests that check state - see lecture notes.