Automated tests using Rest-assured with Kotlin lang

Overview

Badge ServeRest ktlint

Testes de API em Kotlin

Pré-requisitos

  1. Instalar o Kotlin

Ambiente

Para executar os testes localmente, estou utilizando o ServeRest

Logo do ServeRest

Link do Repo: https://github.com/ServeRest/ServeRest

ServeRest está disponível de forma online, no npm e no docker.

Instalando Dependências

Instalar via Gradle

Configuração do Projeto

Estrutura de Pastas

O projeto esta dividido da seguinte maneira:

[APITestsKotlin]
   [src] -> código fonte
        [core] -> setup do requestspecification do REST-assured
        [factory] -> Properties que retornam objetos criados através de uma sererialização
        [requests] -> Métodos que retornam o objeto Response do REST-assured
        [runner] -> Runner do JUnit
        [tests] -> Arquivos de teste do JUnit
        .env -> Arquivo com variáveis de ambiente abstraídas pelo dotenv

Detalhamento

core

A classe Setup é responsável por configurar o RequestSpecification do REST-assured antes de realizar as requisições, e para isso usamos a notação BeforeAll do JUnit para antes dos testes rodarem. Isso é possível graças a anotação @TestInstance que nesse caso estamos usando a LifeCycle.PER_CLASS que permite configurar o cliclo de teste do JUnit através desta classe.

E temos também um tearDown que aciona o reset do REST-assured.

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
open class Setup {

    val dotenv = dotenv()

    companion object {
        lateinit var requestSpecification: RequestSpecification
    }

    @BeforeAll
    fun setup() {
        val logConfig = LogConfig.logConfig()
            .enableLoggingOfRequestAndResponseIfValidationFails(LogDetail.ALL)
        val config = RestAssuredConfig.config().logConfig(logConfig)

        requestSpecification = RequestSpecBuilder()
            .setBaseUri(dotenv["PROD"])
            .setContentType(ContentType.JSON)
            .setRelaxedHTTPSValidation()
            .setConfig(config)
            .addFilter(RequestLoggingFilter(LogDetail.ALL))
            .addFilter(ResponseLoggingFilter(LogDetail.ALL))
            .addFilter(/* filter = */ AllureRestAssured())
            .build()
    }

    @AfterAll
    fun tearDown() {
        RestAssured.reset()
    }
}

Veja que foi utilizado o dotenv Kotlin para abstrair a urlBase do Serverest que esta no arquivo .env na raiz do projeto

factory

Aqui temos classes capazes de abstrair objetos que serão enviados para as requisições. Para isso foi utilizado o kotlinx.serialization.Serializable.

Essa biblioteca possui processos que são capazes de fazer uma serealização de um objeto para formatos de uso comum entre as aplicações como o JSON.

Então nessas classes foi utilizado Properties que retornam objetos definidos por uma data class no formato definido pela anotação @Serializable

class ProductFactory {
    var faker = Faker()
    val createProduct: Product
        get() {
            val productName = faker.commerce.productName()
            return Product(
                nome = productName,
                preco = faker.random.nextInt(10, 999),
                descricao = "Awesome $productName",
                quantidade = faker.random.nextInt(bound = 9999)
            )
        }
}

@Serializable
data class Product(
    @Required var nome: String,
    @Required var preco: Int,
    @Required var descricao: String,
    @Required var quantidade: Int
)

A ideia de usar essa estratégia é justamente delegar para a própria classe Factory construir os objetos a serem usados nas requisições.

A partir do momento em que você replica parte do código no seu teste, repetindo em outras partes do seu código, a manutenção do seu código irá sofrer muitos pontos de alteração, então use desse formato para trazer uma maior robustez para seus testes.

requests

Aqui estão as classes responsáveis por realizar as requisições dos testes, retornando o objeto Response do REST-assured onde será capaz de realizar uma desserialização do objeto e realizar as asserções dos testes.

Para isso acontecer no Kotlin, foi utilizado a dependência io.restassured.module.kotlin.extensions para usar os verbos Given, When, Then, Extract do REST-assured.

open class LoginRequests : Setup() {

    @Step("login request /login")
    open fun login(login: Login): Response {
        val response =
            Given {
                spec(requestSpecification)
                    .body(Json.encodeToString(login))
            } When {
                post("/login")
            } Then {
            } Extract {
                response()
            }
        return response
    }
}

Repare que extendemos a class Setup para essas classes de reqquisições, para ser capaz de user o requestSpecification que contem a preparação dos nossos testes.

Outro ponto interessante é que passamos por parâmetro exatamente o data class que define o modelo do objeto esperado.

runner

Essa classe serve para controlar quais são as classes ou pacotes que pertencem ao grupo de testes a serem executados. Esses grupos chamamos de @Suite pelo JUnit

@Suite
@SelectClasses(
    LoginTests::class,
    UserTests::class,
    ProductTests::class,
    CartTests::class
)
@SelectPackages("tests")
class AllIntegratedTests {
}

O exemplo esta redundante, mas foi para exemplificar que podemos fazer da seguinte forma:

  • @SelectClasses: onde defino quais classes de teste serão executadas por este runner
  • @SelectPackages: onde defino quais pacotes serão executados.

Podem ser criados outros runners dependendo do tipo de teste, como por exemplo testes de regressão e testes de uma feature específica.

Exemplo de execução com linha de comando do gradle

./gradlew clean test --tests "runner.AllIntegratedTests"

tests

E por ultimo, aqui estão as classes de teste do JUnit

@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
class LoginTests: Setup() {

    var request = LoginRequests()
    lateinit var response: Response
    var login = LoginFactory()

    @Test
    @Order(1)
    @DisplayName("Login bem sucedido")
    fun `login succeeded`() {
        response = request.login(login.loginSucceeded)
        assertEquals(HttpStatus.SC_OK, response.statusCode)
        assertEquals("Login realizado com sucesso", response.jsonPath().get("message"))
    }

    @Test
    @Order(2)
    @DisplayName("Login com falha")
    fun `login failed`() {
        response = request.login(login.loginFail)
        assertEquals(HttpStatus.SC_UNAUTHORIZED, response.statusCode)
        assertEquals("Email e/ou senha inválidos", response.jsonPath().get("message"))
    }
}

Para seguir uma sequencia de execução, o JUnit 5 possui uma anotação @TestMethodOrder que tem capacidade de decidir qual será a ordem de execução dos meus testes. No exemplo utilizei o OrderAnnotation::class que é representado pelo anotação @Order. Essa anotação espera um número inteiro na qual seguirá uma ordem crescente de execução.

OBS: Não utilize para criar uma dependência de um cenário para outro, mas sim organizar os reports, analisar os logs, etc.

Allure

Para gerar os reports basta rodar os commandos

./gradlew allureReport e ./gradlew allureServe

ktlint

Foi utilizado o processador de estilização de código ktlint, ele analisa se o código foi desenvolvido seguindo as boas práticas da linguagem Kotlin.

Para verificar se o código esta com algum code smell basta rodar o comando

gradle ktlint

Assim que encontrar os erros, basta rodar o comando abaixo para corrigir pos problemas

gradle ktlintFormat

GitHub Actions

Este projeto conta com a configuração do GitHub Actions e Configuração do GitHub Pages para saber mais pesquise e veja o arquivo de configuração no diretório /.github

You might also like...
Write Tests as Examples on the Method-under-test

Write Tests as Examples on the Method-under-test

A collection of tests and easy to reuse pieces of code for bdk-jvm and bdk-android

Readme This repo is a collection of tests and easy to reuse pieces of code for bdk-jvm and bdk-android. Note that they don't aim to provide a full cov

Easy Response Mocking for Retrofit using annotations

Response Mocking for Retrofit using annotations. Assume Provides safe and easy way to mock API responses for retrofit-okhttp3.

A program to calculate the distance traveled during the run the calories burned and the average speed Display data in more than one way using a graph
A program to calculate the distance traveled during the run the calories burned and the average speed Display data in more than one way using a graph

Running App Features: A program to calculate the distance traveled during the run the calories burned and the average speed Display data in more than

Kotlin wrapper for React Test Renderer, which can be used to unit test React components in a Kotlin/JS project.

Kotlin API for React Test Renderer Kotlin wrapper for React Test Renderer, which can be used to unit test React components in a Kotlin/JS project. How

A multiplatform assertion library for Kotlin

Atrium is an open-source multiplatform assertion library for Kotlin with support for JVM, JS and Android. It is designed to support multiple APIs, dif

Portable validations for Kotlin

Portable validations for Kotlin ✅ Type-safe DSL 🔗 Multi-platform support (JVM, JS) 🐥 Zero dependencies Installation For multiplatform projects: kotl

Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing
Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing

Kotest is a flexible and comprehensive testing tool for Kotlin with multiplatform support. To learn more about Kotest, visit kotest.io or see our quic

mocking library for Kotlin
mocking library for Kotlin

Kotlin Academy articles Check the series of articles "Mocking is not rocket science" at Kt. Academy describing MockK from the very basics of mocking u

Comments
  • Foram realizados N ajustes.

    Foram realizados N ajustes.

    • adicionado git actions (workflow);
    • removido as classes factory, somente data class (poderia colocar em um arquivo somente);
    • corrigido alguns bugs, como criar usuário, id do get all users não quer dizer q vai ser o primeiro, tem que pegar o mesmo quando cria o usuário;
    • adicionado o gson no setup para ser reutilizado pelas classes;
    • adicionado variáveis como privadas, isso impedi um conflito entre elas;
    • adicionado paralelismo no gradlew, como os testes eles estão muito dependentes do outro, n vai ser visível essa melhoria, precisaria deixar os testes dependentes e tirar a ordem;
    opened by reinaldorossetti 0
Owner
Rafael Berçam
QA Engineer Specialist / Tech Lead
Rafael Berçam
A library that makes it easier to write high quality automated acceptance tests

Getting started with Serenity and Cucumber Serenity BDD is a library that makes it easier to write high quality automated acceptance tests, with power

ricardo larrahondo 1 Oct 20, 2021
Android library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests.

Green Coffee Green Coffee is a library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests using the

Mauricio Togneri 227 Nov 21, 2022
Using grpc-wiremock to mock responses in integrated tests of gRPC services

Utilizando grpc-wiremock para mockar respostas em testes integrados de serviços gRPC Este repositório possui um exemplo prático de como configurar e r

Tony A. Luz 2 Oct 28, 2021
3 types of Tests in Android (Unit - instrumentation - UI)

UnitTestingPractice 3 types of Tests in Android Unit instrumentation (Integration) UI Unit Testing benefits confirm code work like a charm simulate Ap

Ahmed Tawfiq 8 Mar 23, 2022
Raccoon is a lightweight response mocking framework that can be easily integrated into the Android UI tests.

Raccoon Medium Articles Checkout these article to get more insights about this library: How to integrate this in your Android Test Why Raccoon? There

Joseph James 52 Aug 15, 2022
Easily scale your Android Instrumentation Tests across Firebase Test Lab with Flank.

Easily scale your Android Instrumentation Tests across Firebase Test Lab with Flank.

Nelson Osacky 220 Nov 29, 2022
Most popular Mocking framework for unit tests written in Java

Most popular mocking framework for Java Current version is 3.x Still on Mockito 1.x? See what's new in Mockito 2! Mockito 3 does not introduce any bre

mockito 13.6k Jan 4, 2023
A simple project to help developers in writing their unit tests in Android Platform.

AndroidUnitTesting A simple project to help developers in writing their unit tests in Android Platform. This is not a multi-module project, but has th

Bruno Gabriel dos Santos 4 Nov 10, 2021
A JUnit5 Platform TestEngine integrated with the official FHIR Validator to run profile and Questionnaire validation as tests.

?? FHIR Validator JUnit Engine A JUnit5 TestEngine to integrate the FHIR Validator into the JUnit5 ecosystem. Supports writing expected validation out

NAV IT 2 Feb 2, 2022
Espresso - Use Espresso to write concise, beautiful, and reliable Android UI tests

Espresso Use Espresso to write concise, beautiful, and reliable Android UI tests

Android For All 1 Jan 26, 2022