Java + Gherkin + Cucumber: Como Escrever Testes de Aceitação


 

Testes de Aceitação com Cucumber e Gherkin: Do Cenário ao Código

Introdução

Os testes de aceitação são essenciais para garantir que o software atenda aos requisitos do usuário. O Cucumber é uma ferramenta popular para implementar BDD (Behavior Driven Development), permitindo que cenários de teste sejam escritos em linguagem natural com Gherkin. Este artigo explora como o Cucumber e o Gherkin funcionam juntos para criar testes automatizados claros e eficientes.

 

O que é o Cucumber?

O Cucumber é uma ferramenta para desenvolvimento orientado a comportamento (BDD). No entanto, vale destacar que não é obrigatório usá-lo para implementar BDD.

Seu funcionamento segue o ciclo Red - Green - Refactor, um processo que garante a construção de código testável e bem estruturado:

  • Red: O teste falha porque a funcionalidade ainda não existe.
  • Green: O código é implementado e o teste passa.
  • Refactor: O código é aprimorado para maior clareza e eficiência.

Seguir esse fluxo torna o desenvolvimento mais intuitivo e estruturado, garantindo não apenas testes eficientes, mas também um código mais limpo e legível. O Cucumber se encaixa perfeitamente nesse modelo, reforçando boas práticas de qualidade e organização.


O que é Gherkin?

O Gherkin define a estrutura dos testes de aceitação no Cucumber. Ele usa uma sintaxe simples para descrever os testes em formato legível por humanos:

  • Given (Dado): Define o contexto inicial antes da ação principal.

  • When (Quando): Representa a ação do usuário ou evento que está sendo testado.

  • Then (Então): Descreve o resultado esperado após a ação.

A divisão dos testes com Gherkin deve ser clara e explícita para garantir a compreensão do comportamento esperado. 

Para entender melhor como é o contexto do Gherkin vou colocar um exemplo abaixo:

Aqui vemos como ele seria implementado, existem outros formatos alem do given, when, then iremos explorar eles mais a frente.

Como o Cucumber funciona?

O Cucumber interpreta arquivos .feature, onde cada funcionalidade é descrita em cenários utilizando a linguagem Gherkin. Abaixo estão alguns dos principais componentes do Cucumber e suas funções:

  • Feature (Funcionalidade): Define o objetivo do teste, ou seja, qual funcionalidade será validada.
  • Scenario (Cenário): Representa um caso específico de teste, detalhando uma situação a ser verificada.
  • Step Definitions (Definições de Passos): Cada etapa descrita no cenário é mapeada para um método em Java, que implementa a lógica do teste.
  • Runner (Executador de Testes): Responsável por rodar os testes utilizando JUnit. Para isso, ele deve ser configurado corretamente, garantindo que os arquivos .feature e suas definições de passos estejam bem mapeados. O Cucumber é bastante sensível à sintaxe, então qualquer erro pode impedir a execução dos testes. 
  • Idioma: É possível definir o idioma dos arquivos .feature com # language: pt, permitindo que os testes sejam escritos em português ou outro idioma compatível.
Aqui irei colocar um exemplo de como ficaria um arquivo .feature configurado
 
 
Nesta imagem, vemos um cenário montado com *. Quando definimos um arquivo .feature utilizando * nos passos, o Cucumber interpreta automaticamente, sem afetar a execução dos testes. O mais importante é garantir que o teste funcione corretamente, independentemente dessa notação.

Configurações do Cucumber (@CucumberOptions)

A anotação @CucumberOptions permite configurar a execução dos testes. Ela é colocada em um arquivo .class do Java, que, como explicado acima, executa o arquivo .feature, iniciando a primeira etapa do ciclo Red - Green - Refactor. Nesta execução inicial, o Cucumber irá retornar os métodos já montados, permitindo que tenhamos uma visão de como o teste irá se comportar. Veja abaixo um exemplo de como a configuração do Runner pode ser feita:

 

 Como podemos configurar o Runner para isso primeiramente vamos entender oque cada anotação faz:

  • features: Define o caminho para os arquivos .feature.
  • glue: Define o pacote das step definitions.
  • plugin: Permite configurar relatórios e saída no terminal.
  • monochrome: Melhora a legibilidade da saída no terminal.
  • snippets: Define o formato dos passos gerados (por exemplo, CamelCase).
  • dryRun: Executa uma simulação para verificar se os passos estão corretamente mapeados.
  • strict: Garante que todos os passos descritos no arquivo .feature tenham uma implementação correspondente.
  • tags: Filtra a execução de testes com base nas tags definidas nos arquivos .feature (por exemplo, @notignore).
Agora que entendemos oque cada anotação faz vamos ver como ficaria:

 
 

Integração com JUnit

O Cucumber pode ser executado com JUnit através da anotação @RunWith(Cucumber.class). Isso facilita a integração com pipelines de CI/CD e execução automatizada dos testes. No exemplo acima ele esta sendo executado com o JUnit como podem ver com a anotação.

O Poder da Regex no Cucumber

Antigamente, o Cucumber usava expressões regulares para capturar valores dinâmicos. Nas versões acima da 4.X, ele passou a permitir o uso de placeholders como {int}, {string} e {float}, o que simplifica a leitura dos testes. Isso elimina a necessidade de usar String, tornando os testes mais legíveis. Para que o Cucumber entenda corretamente o tipo de dado, é necessário identificar diferentes tipos de parâmetros no texto. Caso o Cucumber não consiga identificar o tipo automaticamente, é preciso delimitar a string com aspas ("") para indicar que se trata de um parâmetro de tipo string

Tags no Cucumber

As tags permitem categorizar e executar testes específicos. Exemplo:

  • @Fast e @Slow: Para diferenciar testes rápidos e demorados.

  • @Sprint1: Para marcar testes relacionados a uma sprint específica.

A execução pode ser filtrada no Runner usando tags = "not @ignore" para ignorar testes marcados com @ignore.

Um exemplo seria este caso eu quiser executar os testes rapidos posso colocar na tags o meu @Flash executando apenas os cenarios que estão marcados com esta anotação

 

Testes Data-Driven

Esquema de Cenário

O Esquema de Cenário no Cucumber permite a execução do mesmo teste com diferentes conjuntos de entradas, utilizando uma tabela de dados. Esse modelo de teste é ideal para situações em que você precisa validar o comportamento de uma aplicação para diversos valores de entrada sem precisar duplicar o código do cenário.

Esquema do Cenário: Deve calcular o total correto
  Dado que o preço do produto é R$ <preco>
  Quando adiciono <quantidade> unidades ao carrinho
  Então o total deve ser R$ <total>

  Exemplos:
  | preco |  quantidade  | total |
  | 10      |         2           | 20    |
  | 15      |         3           | 45    |
Neste exemplo, o Cucumber entende que os parâmetros <preco>, <quantidade> e <total> são substituídos pelos valores definidos na tabela de Exemplos. Isso permite testar o mesmo fluxo com diferentes dados de maneira concisa e sem redundância.

Data Table

O Data Table é utilizado quando é necessário passar dados mais estruturados ou complexos para o teste, especialmente quando você tem múltiplos parâmetros ou combinações de dados a serem validados em um único cenário. Ele é comumente usado em situações em que os dados precisam ser apresentados em formato de tabela para garantir a clareza e facilitar o entendimento.

Exemplo de Data Table:

Cenário: Cadastro de usuário
  Dado um usuário com as seguintes informações:
    | nome |         email           |      senha      |
    | João  | joao@email.com |     123456     |
  Quando ele se cadastra
  Então o cadastro deve ser concluído com sucesso
 
Neste caso, o Cucumber irá entender que o nome, email e senha são parâmetros a serem passados para o teste. O Data Table proporciona uma forma clara e estruturada de fornecer múltiplos dados, permitindo que o cenário seja executado de forma mais eficiente, principalmente quando se trata de dados como registros de usuários, produtos, entre outros
 

Contexto no Cucumber

O Contexto evita repetições nos cenários, deixando os testes mais limpos:

Contexto:
  Dado que estou logado como "admin"

Cenário: Criar uma nova conta
  Quando crio uma conta chamada "Conta Teste"
  Então a conta deve ser salva com sucesso

Cenário: Criar uma conta sem nome
  Quando tento criar uma conta sem nome
  Então sou notificado sobre o erro
 

Cenários Imperativos vs. Declarativos

  • Imperativos: Descrevem cada passo detalhadamente.

  • Declarativos: São mais simples e focam no resultado esperado.

Exemplo Imperativo:

Quando acesso a página de login
E digito "usuario" no campo de usuário
E digito "senha123" no campo de senha
E clico em entrar
 Ele é melhor pensando em uma equipe com uma rotatividade alta, ele serve como um facilitador 

Exemplo Declarativo:

Quando realizo login como "usuario"

Os testes declarativos são mais legíveis e fáceis de manter

Conclusão

O Cucumber e o Gherkin são ferramentas poderosas para escrita de testes de aceitação. Usando boas práticas como Contexto, Data Tables e Esquema de Cenário, é possível criar testes claros, reutilizáveis e fáceis de manter.

Se você deseja melhorar a qualidade do seu software, comece a escrever testes com Cucumber e Gherkin!



Comments

Popular posts from this blog

Spring VS Micronaut VS Quarkus

Spring + Redis: Como melhorar sua aplicação com caching

Java + Kafka, Como essa parceria fucniona ?