Aqua 2024.3 Help

Tutorial: Test-driven development with Kotlin

Whether you like to write your tests before writing production code, or like to create the tests afterwards, Aqua makes it easy to create and run unit tests. In this tutorial we’re going to show how to use Aqua to write tests first (Test Driven Development or TDD).

Create new project

  1. Launch Aqua.

    If the Welcome screen opens, click New Project. Otherwise, go to File | New | Project in the main menu.

  2. From the list on the left, select Kotlin. Name the new project TDD-in-Kotlin and change its location if necessary.

  3. Select Gradle as a build tool and Kotlin as a DSL.

  4. From the JDK list, select the JDK that you want to use in your project.

    If the JDK is installed on your computer, but not defined in the IDE, select Add JDK and specify the path to the JDK home directory.

    If you don't have the necessary JDK on your computer, select Download JDK.

  5. Click Create.

Aqua creates a project with pre-configured structure and essential libraries.

Create a new package

  1. Right-click the main | kotlin folder in the Project tool window and select New | Package.

  2. Name the new package com.example.demo and press Enter.

Write the test body

Create your first test

Given that we’re writing our tests first without necessarily having the code we’re testing available to us yet, we’ll create our first test via the project panel.

  1. Right-click the test root folder and select New | Kotlin Class/File.

    In the popup that opens, name the new package and test class: com.example.demo.CalculatorTest.

    Test class created
  2. Place the caret inside the curly braces in the class, press Alt+Insert.

  3. Select Test Function from the menu to create a test function from the default template. Select JUnit 5 as the test framework.

    Name the function testMultiplyBy2, press Enter, and the caret will end up in the function body.

    Creating your first test

    You can alter the default test function template - for example, if you wish to change the start of the function name from test to should.

Write the test body

It may seem counter-intuitive to write test code for classes and functions that don’t exist, but Aqua makes this straightforward while keeping the compiler happy. Aqua can create classes and functions for you if they don’t already exist.

Write your tests describing what you want to achieve, pressing Alt+Enter on any classes that do not exist and selecting Create class. This will give you a minimum implementation that keeps the compiler happy.

  1. Type val calculator = Calculator(), press Alt+Enter, and select Create class 'Calculator'.

    Creating a new class
  2. From the Choose class container, select Extract to separate file. In the dialog that opens, select the com.example.demo package in main that we have created earlier.

  3. Continue writing the test body, including names of functions that you need that do not exist.

    Type val result = calculator.parse("2 * 2") and press Alt+Enter. Select Create member function to have Aqua create a bare skeleton function.

    Creating a function
  4. Implement the tested function so that it returns the required type and compiles without issues. The correctness of the result is not important now.

    Implementing the function in the tested class
  5. Add an assertion to the test function. This statement will compare the actual return of the function with the expected one and thus determine the outcome of the test. Type assertEquals(4, result)

    If the function has not been imported automatically, place the caret at assertEquals, press Alt+Enter, select Import function, and then select org.jetbrains.kotlin:kotlin-test.

    assertEquals() checks if the parameters are equal and fails the test if they are not

Run the tests

When following a TDD approach, typically you go through a cycle of Red-Green-Refactor. You’ll run a test, see it fail (go red), implement the simplest code to make the test pass (go green), and then refactor the code so your test stays green and your code is sufficiently clean.

The first step in this cycle is to run the test and see it fail.

Given that we’ve used Aqua features to create the simplest empty implementation of the method we’re testing, we do not expect our test to pass.

  • From inside the test, press Ctrl+Shift+F10 to run this individual test.

    The results will be shown in the run dialog. The test name will have an icon next to it — either red for an exception, or yellow for an assertion that fails. For either type of failure, a message stating what went wrong is also shown.

    Running the test

Implement the code

The next step is to make the tests pass, which means implementing the simplest thing that works.

  1. You can navigate to the code being tested using the usual functions - clicking through on the function name, pressing Ctrl+Alt+B while the caret is on the function name, or pressing Ctrl+Shift+T to switch between the test and the production code.

  2. Make a change to the function to make the test pass. Often with TDD, the simplest thing that works might be hard-coding your expected value. We will see later how iterating over this process will lead to more realistic production code.

    Fixing the code of the method to satisfy test conditions
  3. Use Shift+F10 to re-run the last test.

  4. Wait until the icon next to the test function goes green to make sure the test passes. If the icon does not go green, keep changing the code until the test passes.

    Rerunning tests

Iterate

Developing code is an iterative process. When following the TDD-style approach, this is even more true. To drive out more complex behaviour, we add tests for other cases.

  1. In your test class, use Alt+Insert again to create a new test function.

  2. Pick a second test case that specifies more requirements of the function you’re testing. Remember that you can use Aqua’s features to create classes and functions to keep the compiler happy.

    Creating a new test
  3. Run this second test case to show how it fails for the correct reason.

  4. Change the code in the function being tested to make this test pass.

    Improving the code so that the second test passes
  5. Re-run both tests by pressing Ctrl+Shift+F10 inside the test class, not inside a single function, and see that both tests now pass. If either test fails, make the changes needed to the code to ensure the tests pass.

    The second test passes

Summary

Writing your first test in a test-first style takes a small amount of setup – creating the test class, creating the test functions, and then creating empty implementations of the code that will eventually become production code. Aqua automates a lot of this initial setup.

As you iterate through the process, creating tests and then making the changes required to get those tests to pass, you build up a comprehensive suite of tests for your required functionality, and the simplest solution that will meet these requirements.

Last modified: 10 June 2024