Por que os testes E2E são seu melhor amigo (e como se tornar amigo deles em Kotlin)
\n\nImagine: você escreveu um serviço incrível em Kotlin, tudo compilou, os testes unitários estão verdes, o code review passou. Você faz o deploy para produção e... os usuários reclamam que o botão "Comprar" não funciona, embora os testes unitários o verificassem. Familiar? Bem-vindo ao mundo onde testes E2E de aplicações Kotlin não são um luxo, mas uma necessidade.
\n\nO teste de ponta a ponta (end-to-end) é a verificação de todo o caminho do usuário: desde o clique no botão até a gravação no banco de dados e vice-versa. Neste artigo, não vamos apenas falar sobre teoria. Vamos escrever testes reais para uma aplicação Kotlin, analisar as ferramentas e mostrar como não enlouquecer ao configurar a infraestrutura. Aperte os cintos, terá código e café.
\n\nO que são testes E2E e como eles diferem de outros tipos
\n\nVamos esclarecer isso de uma vez. Os testes E2E (ou de ponta a ponta) verificam o sistema como um todo, da forma como o usuário o vê. Ao contrário de:
\n\n- \n
- Testes unitários — verificam um método/classe isoladamente. \n
- Testes de integração — verificam a interação de dois ou três componentes (por exemplo, controlador + serviço). \n
- Testes de UI — muitas vezes são confundidos com E2E, mas um teste de UI pode não verificar o backend, apenas a renderização da interface. \n
Os testes E2E de aplicações Kotlin são o ciclo completo: interface do usuário (se houver), API, lógica de negócios, banco de dados, serviços externos. Tudo deve funcionar em conjunto como um relógio.
\n\nFerramentas para testes E2E em Kotlin
\n\nA escolha da ferramenta depende do que você está testando: uma aplicação Android, um serviço web em Ktor ou uma aplicação desktop. Aqui estão as melhores para um desenvolvedor Kotlin:
\n\n- \n
- Selenide + Kotlin — para interfaces web. Um wrapper sobre o Selenium, mas com sintaxe concisa, ideal para Kotlin. \n
- Ktor Client + TestContainers — para backend. Você sobe a infraestrutura de teste (BD, cache) no Docker e faz requisições HTTP. \n
- Espresso + Compose Test — para Android. Ferramentas nativas que acompanham o Android SDK. \n
- Cucumber + Kotlin — se precisar de cenários BDD em uma linguagem compreensível para o cliente. \n
Vamos nos concentrar nos dois primeiros cenários, pois são os mais versáteis.
\n\nEscrevendo um teste E2E para uma aplicação web em Kotlin (Selenide)
\n\nSuponha que temos uma loja online simples em Spring Boot + Kotlin. Precisamos verificar o cenário: o usuário acessa o site, adiciona um produto ao carrinho e finaliza a compra.
\n\nPrimeiro, adicionamos as dependências no build.gradle.kts:
dependencies {\n testImplementation("com.codeborne:selenide:6.19.1")\n testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")\n testImplementation("io.github.bonigarcia:webdrivermanager:5.6.2")\n}\n\nAgora escrevemos o teste propriamente dito. Observe que usamos funções de extensão do Kotlin para tornar o código legível:
\n\nimport com.codeborne.selenide.Condition.visible\nimport com.codeborne.selenide.Selenide.`$`\nimport com.codeborne.selenide.Selenide.open\nimport org.junit.jupiter.api.BeforeEach\nimport org.junit.jupiter.api.Test\n\nclass ShopE2ETest {\n\n @BeforeEach\n fun setUp() {\n // Abre o navegador antes de cada teste\n open("https://test-shop.example.com")\n }\n\n @Test\n fun `user can add product to cart and checkout`() {\n // Passo 1: Encontrar o produto e adicionar ao carrinho\n `$`("[data-testid='product-1']").shouldBe(visible).click()\n `$`("[data-testid='add-to-cart']").click()\n\n // Passo 2: Verificar se o carrinho não está vazio\n `$`("[data-testid='cart-badge']").shouldHave(text("1"))\n\n // Passo 3: Ir para o checkout\n `$`("[data-testid='checkout-btn']").click()\n\n // Passo 4: Preencher o formulário\n `$`("[