ITKarma picture

Stated in the title Kotlin is more associated with Android-development, but why not experiment? We used it to find a way to simplify the automation of testing the API of one of our services a bit, as well as to facilitate the work of testers who are new to programming and the nuances of the Java language.

What are we doing? We develop a service for sending brokerage forms for settlement and obtaining a decision on them. And despite the fact that this is a banking solution, the development is carried out by a small scrum-team, in which 1-2 specialists are engaged in testing, depending on the load and the situation on the project.

Under the cut, we’ll tell you about the results of our experiments, which we gladly transferred to production.

Without a face

Our service was developed for integration with the partners interface and does not have its own UI. Therefore, in this case, testing the API directly is the only option available. Although there are a number of advantages to API tests with an interface:

  • allow you to start testing already at the stage of developing services,
  • simplify error localization,
  • generally reduce testing time.

Our service includes a set of APIs for transferring customer profile data for calculation and for obtaining a decision on a car loan. The following checks can be identified as the main high-level testing tasks:

  • format of fields and parameters,
  • correct status codes and error messages,
  • required fields and service logic.

ITKarma picture

Tipping point

The team prepared the MVP service in a very short time, and automated tests were originally written by the product developer. Autotests were faster and more convenient to include in the project, so initially they were closely connected with the code and were based on the Java stack, REST-assured, with the TestNG test framework.

With the development of the project, the involvement of testers in the automation process grew. At the moment, the tasks of supporting and updating autotests lie entirely in the testing department. In this regard, there was a need to adjust the approach to automation - to simplify the tests as much as possible and make them independent of the main code. And thereby solve the difficulties that arise:

  1. Linking with the code makes the tests more vulnerable to any design changes, it requires a lot of work to maintain performance.
  2. Sophisticated relationships increase the time it takes to find information and investigate errors.
  3. It’s difficult to connect new employees of the testing department to work with Java code, it requires training for testers and considerable time to enter the project.

Therefore, we decided to change the approach to testing and formulated the following requirements for new tools:

  1. Full compatibility with Java, allowing you to rewrite checks in stages, while continuing to work with old tests.
  2. Simple, intuitive code.
  3. Free and stable language.
  4. Separation of autotests in a separate project.

And here Kotlin

Kotlin meets our needs as much as possible.

ITKarma picture

In addition to full Java compatibility at Kotlin, we were interested in the following features:

  1. Laconicism of the language makes the code clear and easy to read.
  2. Syntactic sugar.
  3. Intuitive code and easy entry of specialists into the project.
  4. The ability to translate self-tests from Java to Kotlin is gradual and painless, partially if necessary.

Cons, of course, also exist, especially in comparison with Java. First, a relatively small community: finding help and answers to Java questions is much easier than with Kotlin. Secondly, in general, Java is a more universal language with great features and a large number of developments and libraries.

But, frankly, for testing purposes, we do not need such wide opportunities that only Java can provide. Therefore, we preferred the simplicity and conciseness of Kotlin.

From words to action

As a result of a partial transition to a new language, we received a noticeable gain in the labor costs of specialists, a significant simplification of the code and a reduction in its volume. This is clearly seen in specific examples from the tests of our service for processing brokerage profiles.

In Kotlin, you can initialize a query object with a single line of code. For example, the ApplicationDTO class (for sending a questionnaire for a solution) and ErrorDTO (errors coming from the service) look like this:

ITKarma picture

Kotlin allows you to set field values ​​during initialization. This saves a lot of time writing tests: when creating an object, the fields are already filled with valid data, we only change the values ​​that apply to the current scan.

JsonIgnoreProperties annotation allows you to omit all the fields in the class if they are not needed for tests and need not be checked. If a field arrives that is not specified in the description, the test will not fail with an error.

A question mark for a variable type indicates that at some point it can be null. But when using a variable, you will need to remember to take this into account and process it. Finally, unlike Java tests, you can gracefully avoid a NullPointerException here.

We illustrate with a simple example error checking with an incorrect login:

class ApplicationTests { val DEFAULT_LOGIN="consLogin" val ERROR_CODE="3" val BASE_URI="" companion object{ private var spec: RequestSpecification?=null @JvmStatic @BeforeClass fun initSpec() { spec=RequestSpecBuilder() .setContentType(ContentType.JSON) .setBaseUri(BASE_URI) .addFilter(ResponseLoggingFilter()) .addFilter(RequestLoggingFilter()) .build() } } @Test fun incorrectLogin() { val incorrectLogin=DEFAULT_LOGIN + "INCORRECT"; val res=given() .spec(spec) .body(ApplicationDTO) .`when`() .post(endpointApplication(incorrectLogin) .then() .statusCode(400) .extract().`as`( assertThat(res.error_message).containsIgnoringCase("Указан неверный логин или пароль") assertThat(res.error_code).isEqualToIgnoringCase(ERROR_CODE) } } 

We are creating a specification for queries in BeforeClass, which we will reuse in all tests of this class. Jacson serializes and deserializes json objects, which simplifies things: you don’t need to work with them like strings, which significantly reduces the number of errors.

ITKarma picture

With Kotlin, we significantly reduce the amount of code, which means we make life easier for both “writers” and its “readers.” The ApplicationDTO class already contains a constructor and some other methods (hashCode (), copy (), etc.) - we don’t need to “overload” the code with them and novice developers of autotests are not distracted by them. They do not need to be updated with any changes, which reduces the time for making changes to the tests.

It is also very convenient that Kotlin supports named arguments - the code is pretty easy to read, and there is no need to setters themselves for json object classes.

Try new - for free

I would like to note the openness and free of charge of Kotlin and all the libraries we use, which greatly simplifies the work and expands the possibilities for experiments and the introduction of new approaches. Agree, it’s always easier to try new things for free, and in case of failure, return to the old ones.

In the future, we plan to develop a new approach and scale it to other projects, transfer the remaining API and user interface tests to Kotlin.

P.S.: Despite the fact that Kotlin is primarily associated with Android development, the scope of its use, as you understand, is not limited to this at all. Reducing the time to write code, its simplicity and conciseness will help reduce labor costs in solving many problems. If we have new cases with Kotlin, we will definitely tell about them here .