Write performance tests with Kotlin

João Paulo Gomes
WAES
Published in
5 min readMar 2, 2023

Are you a Kotlin developer working with microservices? In this article, you will learn the basics of writing performance tests with Kotlin.

Introduction

Performance tests are a type of test that helps to determine how your application will behave at a determined workload. This helps you to know your application better and learn some important things like:

  • how many simultaneous users it can handle;
  • how its responsiveness is at a certain load;
  • the maximum number of simultaneous users without impacting the responsiveness;
  • how much memory and CPU your application needs to run smoothly.

It also helps you to detect some issues and prevent problems in production, like bottlenecks and memory leaks.

Performance tests tools

The most commonly used tool to execute performance tests on an application is JMeter. It’s a powerful tool written in Java that allows the simulation of simultaneous users, offers a graphical user interface to write the tests, and saves the tests using the XML format.

Nowadays, using Agile methodologies, code review techniques, and everything as code, despite JMeter being a good tool, the XML format that is used to save the test scenarios doesn’t fit very well with the developers’ workflow.

We also have other tools, like k6, for example. This tool allows writing performance tests as code using JavaScript, but if you are a Kotlin developer used to the Java ecosystem, why not use the Kotlin programming language?

To write performance tests using the Kotlin programming language, you can use a tool called Gatling. Gatling uses Scala, Netty, and the Akka framework to simulate millions of simultaneous users. With support for Java, Kotlin, and Scala, Gatling offers a DSL to help you write your scenarios. Gatling also offers plugins for Gradle, Maven, and SBT build tools.

Writing performance tests with Gatling

After adding the Gatling plugin to your favorite build tool, it’s time to start writing your first performance test. In this article, we are going to test an API. You can also use Gatling to test other types of web applications.

package com.johnowl.simulations 

import io.gatling.javaapi.core.*
import io.gatling.javaapi.http.*
import io.gatling.javaapi.core.CoreDsl.*
import io.gatling.javaapi.http.HttpDsl.*

class BasicSimulation : Simulation() {

}

This is the skeleton of a performance test, just define your package name, then add all these imports (it’s strange to add a lot of imports, but believe me, it’s going to make your life easier by avoiding conflicts with other non-desired classes). Finally, create a new class inheriting from the Simulation class. A simulation is a load test describing how users interact with your application.

Next, you need to define the protocol that Gatling will use to connect with your application. In the protocol, you can define the base URL of your application, and you can also add some common headers that will be used in all the requests.

private val protocol = http
.baseUrl("http://localhost:8080")
.contentTypeHeader("application/json")

Now that we have set up the protocol, we can add the user's steps to the performance test. In Gatling, these steps are called a scenario.

private val scn = scenario("Do login")
.exec(http("Create token")
.post("/auth/v1/tokens")
.body(ElFileBody("bodies/credentials.json"))
.check(jsonPath("$.token").find().saveAs("token"))
)
.pause(Duration.ofMillis(50))
.exec(http("Validate token")
.post("/auth/v1/tokens/validate")
.body(ElFileBody("bodies/token.json"))
.check(status().`is`(200))
)
.pause(Duration.ofMillis(100))

There are a lot of things happening in this scenario. First, we start by defining the scenario’s name. After that, we define the first step to be executed, followed by a pause. Then we define the second step, also followed by a pause.

In our first step, called Create token, we do a POST to the path /auth/v1/tokens. For this step, we use an external file in the request body instead of defining the body in our code, this way you don’t need to mix JSON with Kotlin. After executing the POST, we check if the response has a JSON with a token field and save it to the current user session.

The user session is a nice feature that allows you to share information about a specific user with the next steps. Before defining the next step, we added a pause to simulate a real scenario. Until now, we have not been executing anything. We are just defining the steps.

The next step of this scenario is token validation. Again, we are doing a POST to a path, using a JSON file to define the request’s body, and expecting a 200 response code. But wait, where are we setting the token that is being validated by this API?

We are delegating this job to Gatling using template variables defined in the JSON file. See the content of the file:

{
"token": "${token}"
}

Finally, we must define how many users we want for this scenario. Before doing that, we need to understand two concepts:

  • Closed System
  • Open System

Closed systems are applications that allow only a certain amount of users simultaneously. Some examples of closed system applications are call centers or ticket-selling applications. Open systems are any other type of application in which the users can access the application until the server has enough resources to serve them.

You should use the correct model in your test. In your scenario, you can choose between the methods scn.injectOpen() and scn.injectClosed(). They define which type of system you will have. For the test in this article, we will use the open model.

init {
setUp(scn.injectOpen(
nothingFor(Duration.ofSeconds(5)),
rampUsers(3800).during(Duration.ofMinutes(15))
)).protocols(protocol)
}

The code above makes it easy to understand what it’s happening by reading the DSL. The test does nothing for 5 seconds. Then it ramps from 0 to 3800 simultaneous users in an interval of 15 minutes. Below you can see the complete class:

class BasicSimulation : Simulation() {

private val protocol = http
.baseUrl("http://localhost:8080")
.contentTypeHeader("application/json")

private val scn = scenario("Log in and validate generated token")
.exec(http("Create token with valid credentials")
.post("/auth/v1/tokens")
.body(ElFileBody("bodies/credentials.json"))
.check(jsonPath("$.token").find().saveAs("token"))
)
.pause(Duration.ofMillis(50))
.exec(http("Validate token")
.post("/auth/v1/tokens/validate")
.body(ElFileBody("bodies/token.json"))
.check(status().`is`(200))
)
.pause(Duration.ofMillis(100))

init {
setUp(scn.injectOpen(
nothingFor(Duration.ofSeconds(5)),
rampUsers(3800).during(Duration.ofMinutes(1))
)).protocols(protocol)
}
}

Conclusion

This is a sneak-peak of writing performance tests with Kotlin. You just need to run the Gatling plugin using your build tool to run your tests. At the end of the test, a nice report will be generated. It’s also possible to integrate Gatling with a time-series database to see real-time results.

Now that you know it’s possible, go deep into the documentation to learn more about this awesome tool.

Do you think you have what it takes to be one of us?

At WAES, we are always looking for the best developers and data engineers to help Dutch companies succeed. If you are interested in becoming a part of our team and moving to The Netherlands, look at our open positions here.

WAES publication

Our content creators constantly create new articles about software development, lifestyle, and WAES. So make sure to follow us on Medium to learn more.

Also, make sure to follow us on our social media:
LinkedInInstagramTwitterYouTube

--

--

João Paulo Gomes
WAES
Writer for

Hi! I’m JP! I work as a Kotlin and Java developer and in my spare time I like to cook. My github https://github.com/johnowl