https://kwahome.medium.com/microservice-testing-a-new-dawn-aa614d31d7e9
Category Archives: Teste Automatizado
Cucumber – Exemplo prático de Calculadora
Introdução
Este post tem o objetivo de demonstrar, de forma prática, a metodologia do uso do Cucumber, usando Eclipe e Java.
Aprenda mais sobre o Cucumber aqui.
Criação do Projeto
Vamos criar um projeto Maven Java no Eclipse.
- Abra o Eclipse.
- Clique no menu File / New / Maven Project
- Deixe os valores padrão e clique em Next
- Utilize o archetype quickstart (padrão) e clique em Next
- Configure os parâmetros do projeto
- Group Id: com.maxidica.tdd
- Artifact Id: calculadora
- Deixe os demais campos padrão
- Clique no botão Finish
Ajustando pom.xml
Agora vamos incluir as dependências necessárias para o projeto.
- Abra o arquivo pom.xml
- Clique na aba Dependencies
- Remova o junit 3.8.1
- Adicione o junit 4 (4.1.2)
- Adicione as dependências do Cucumber
- cucumber-java
- cucumber-junit
- cucumber-picocontainer
- Configure as dependências com escopo test
Criando arquivo de estórias
Iremos criar o diretório de fonte, chamado resource.
- Clique com o botão direito no projeto
- Escolha New / Source Folder
- Digite src/test/resource
- Clique em Finish
Eliminando classes desnecessárias
Exclua todos os arquivos .java do projeto (App.java e AppTest.java).
Criando a classe CalcRunner
Essa classe é responsável pela execução do teste.
- Clique com o botão direito em src/test/java
- Escolha New / Class
- Digite CalcRunner
- Clique em Finish
package com.maxidica.tdd.calculadora;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
@RunWith(Cucumber.class)
@CucumberOptions(
plugin = {“html:target/cucumber-html-report”, “json:target/cucumber-json-report.json”},
features = “src/test/resource”
)
public class CalcRunner {
}
Criando arquivo feature
Esse arquivo é responsável pela execução dos testes.
- Clique com o botão direito em src/test/resource
- Escolha New / File
- Digite o nome Calc.feature
- Digite o conteúdo abaixo
#language: en Feature: Calc Como usuario entrar com 2 valores Com objetivo de obter um resultado Scenario: Somar Given que eu escolha somar When eu preencho o primeiro número com o valor '1' And eu preencho o segundo número com o valor '1' Then eu devo ver o resultado como '2'
Rodando o 1º teste
Esse teste criará a estrutura para definirmos a classe de execução.
- Clique com o botão direito na classe CalcRunner.java
- Escolha Run As / JUnit Test
- Na aba Console, aparecerá o resultado com os métodos a serem codificados
1 Scenarios (1 undefined) 4 Steps (4 undefined) 0m0,000s You can implement missing steps with the snippets below: @Given("^que eu escolha somar$") public void que_eu_escolha_somar() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @When("^eu preencho o primeiro número com o valor '(\\d+)'$") public void eu_preencho_o_primeiro_número_com_o_valor(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @When("^eu preencho o segundo número com o valor '(\\d+)'$") public void eu_preencho_o_segundo_número_com_o_valor(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^eu devo ver o resultado como '(\\d+)'$") public void eu_devo_ver_o_resultado_como(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); }
Criar classe com os passos do teste
Agora, iremos criar a classe responsável pela execução dos passos do teste.
- Clicar com o botão direito em src/test/java
- Escolher New / Class
- Defina o nome como CalcSteps
- Então, basta copiar os métodos (apresentados no Console) para dentro da classe
package com.maxidica.tdd.calculadora; import cucumber.api.PendingException; import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; public class CalcSteps { @Given("^que eu escolha somar$") public void que_eu_escolha_somar() throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @When("^eu preencho o primeiro número com o valor '(\\d+)'$") public void eu_preencho_o_primeiro_número_com_o_valor(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @When("^eu preencho o segundo número com o valor '(\\d+)'$") public void eu_preencho_o_segundo_número_com_o_valor(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } @Then("^eu devo ver o resultado como '(\\d+)'$") public void eu_devo_ver_o_resultado_como(int arg1) throws Throwable { // Write code here that turns the phrase above into concrete actions throw new PendingException(); } }
Criar a aplicação
Essa classe é que conterá as regras de negócio que queremos, neste caso, calcular a soma de números.
- Clique com o botão direito em src/main/java
- Escolha New / Class
- Defina o nome Calc
package com.maxidica.tdd.calculadora; public class Calc { public int somar( int a, int b ) { return a + b; } }
Codificando os métodos na classe CalcSteps
Agora, precisamos codificar os métodos.
package com.maxidica.tdd.calculadora; import static org.junit.Assert.assertEquals; import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; public class CalcSteps { Calc calc; int num1, num2; @Given("^que eu escolha somar$") public void que_eu_escolha_somar() { calc = new Calc(); } @When("^eu preencho o primeiro número com o valor '(\\d+)'$") public void eu_preencho_o_primeiro_número_com_o_valor(int arg1) { num1 = arg1; } @When("^eu preencho o segundo número com o valor '(\\d+)'$") public void eu_preencho_o_segundo_número_com_o_valor(int arg1) { num2 = arg1; } @Then("^eu devo ver o resultado como '(\\d+)'$") public void eu_devo_ver_o_resultado_como(int arg1) { assertEquals(arg1,calc.somar(num1,num2)); } }
Teste final
Então podemos executar o teste final na classe CalcRunner.
- Clique com o botão direito na classe CalcRunner.java
- Escolha Run As / JUnit Test
- Verifique o resultado no Console
1 Scenarios (1 passed) 4 Steps (4 passed) 0m0,146s
Provocando erro no teste
Para executar a falha, devemos alterar o arquivo feature.
- Edite o arquivo Calc.feature
- Altere o texto, eu devo ver o resultado como ‘3’
- Salve o arquivo
- Rode o teste na classe CalcRunner.java
- Perceba que no Console, apresentará erro de execução
1 Scenarios (1 failed) 4 Steps (1 failed, 3 passed) 0m0,163s java.lang.AssertionError: expected:<3> but was:<2> at org.junit.Assert.fail(Assert.java:88) at org.junit.Assert.failNotEquals(Assert.java:834) at org.junit.Assert.assertEquals(Assert.java:645) at org.junit.Assert.assertEquals(Assert.java:631) at com.maxidica.tdd.calculadora.CalcSteps.eu_devo_ver_o_resultado_como(CalcSteps.java:31) at ✽.Then eu devo ver o resultado como '3'(Calc.feature:10)
Essa é a parte interessante do teste. Alterando o arquivo feature, podemos validar se a aplicação está funcionando de forma correta.
Você pode baixar o projeto pronto no Github.
Cucumber – Linguagem Gherkin
Cucumber é uma ferramenta que suporta Behavior Driven Development (BDD), traduzindo ao pé da letra significa: “desenvolvimento orientado por comportamento”, simples assim,ou seja, BDD nada mais é do que descrever os COMPORTAMENTOS de um sistema utilizando linguagem Gherkin.
O que é Gherkin ?
Gherkin é uma linguagem natural que tanto o cucumber quanto todos os interessados(usuários, desenvolvedores, testadores, etc…) entendem, dessa forma, todas as necessidades reais do usuário e projeto são descritas, gerando uma documentação viva e valor pro negócio.
Não altere a estrutura padrão
Como já sabemos, o cucumber utiliza linguagem gherkin, que é uma linguagem natural e de fácil entendimento, porém possui algumas palavras “chaves” e são elas:
Dado (Given)
O “Dado” seria básicamente as pré-condições do cenário.
Quando (When)
O “Quando” serve descrever as ações chave que o usuário executa, resumidamente seria qualquer ação de interação do usuário com o sistema.
Então (Then)
O “Então” visa mostrar as saídas, os resultados das ações executadas, seriam basicamente os resultados esperados.
Exemplo:
Dado número A
Quando somar A+B
Então resultado deve ser C
Portanto mantenha sempre esse padrão: Dado, Quando, Então. NÃO altere isso e NÃO repita essas palavras no mesmo cenário, para não repetir essas palavras, caímos no segundo tópico das melhores práticas.
Faça uso do “E” e “Mas”
E (And)
O “E” visa complementar qualquer uma das palavras chaves citadas anteriormente, por exemplo:
Dado número A
E número B
Quando somar A+B
E dividir por C
Então resultado deve ser D
Mas (But)
O “Mas” seria a forma negativa do “Então”, basicamente, quando o resultado esperado for que o usuário NÃO DEVE receber.
Dado número A
E número B
Quando somar A+B
E dividir por C
Então resultado deve ser exibido
Mas não deve ser igual a D
Use “Contexto” e ganhe tempo
Uma regra básica que serve para a vida, se você está fazendo o mesmo trabalho duas vezes, de duas uma, ou você não fez direito, ou algo de errado não está certo.
No cucumber é para isso que existe o contexto(background), para remover aquilo que está sendo repetido em todos os cenários e centralizar em um único lugar, no caso o contexto. Vamos dar um exemplo para ficar bem mais fácil e compreensível.
Reparem que no exemplo acima, a seguinte linha está sendo repetida em todos os cenários:
Dado que eu esteja logado
Vamos ao “Contexto”
Viu como diminuímos o retrabalho? Mais fácil do que fazer regime!
O “Contexto” é bom quando usado para coisas simples, não é recomendável utilizar para cenários mais complexos complexas.
O “Contexto” é executado antes de cada um dos cenários, mas após qualquer um dos Hooks.
Use tags
#VemNeMimSextaFeira, é praticamente a mesma coisa, só que no lugar da hashtag, utiliza o @. Com isso você consegue filtrar e executar cenários específicos, por exemplo:
@validar_login @crítico @wip @cadastrar_cliente
Pode utilizar mais de uma tag por funcionalidade
Seja mais comportamental do que procedural
Não escreva todos os passo a passo de cada cenário, basta descrever o comportamento. exemplo:
Dado que o usuário esteja na tela de login
Quando preencher o campo usuário
E preencher o campo senha
E clicar no botão entrar
Então o sistema deve logar
e exibir dashboard
Pode isso Arnaldo ? Poder pode, mas não é recomendável, o mais correto seria:
Dado que o usuário esteja na tela de login
Quando informar os dados válidos
Então o sistema realizar o login
E o sistema exibir mensagem de “Bem Vindo”
Sempre descreva na terceira pessoa
Pare de utilizar “eu” nas descrições dos cenários, procure utilizar sempre na terceira pessoa. Reparem no cenário abaixo:
Dado que eu esteja…
Quando eu adiciono…
Não, não é assim! utilize na terceira pessoa.
Dado que o usuário ou o cliente esteja logado
Quando usuário ou cliente adicionar um produto no carrinho
Melhorou ?
Utilize Scenario Outline
Quando os cenários têm validações e resultados parecidos, podemos utilizar os Scenarios Outline, ou Esquemas de cenário. Vamos ao exemplo:
Cenário: mostrar o resultado quando executar uma operação de adição
Dado que o usuário esteja na calculadora
Quando pressionar o número 4
E pressionar o número 2
E escolher adição
Então o sistema devera mostrar o resultado igual à 6
Cenário: mostrar o resultado quando executar uma operação de subtração
Dado que o usuário esteja na calculadora
Quando pressionar o número 4
E pressionar o número 2
E escolher subtração
Então o sistema devera mostrar o resultado igual à 2
Cenário: mostrar o resultado quando executar uma operação de multiplicação
Dado que o usuário esteja na calculadora
Quando pressionar o número 4
E pressionar o número 2
E escolher multiplicação
Então o sistema devera mostrar o resultado igual à 8
Repare que são praticamente as mesmas validações, para facilitar tanto na implementação e na manutenção, existe no cucumber os scenarios outline. E ficaria da seguinte maneira:
Cenário: mostrar o resultado quando executar uma operação na calculadora Dado que o usuário esteja na calculadora Quando pressionar o <número1> E pressionar o <número2> E escolher a <operação> Então o sistema devera mostrar o <resultado>
Exemplo:
| numero1 | numbero2 | operação | resultado|
| 4 | 2 | soma | 6 |
| 4 | 2 | subtração | 2 |
| 4 | 2 | multiplicação | 8 |
| 4 | 2 | divisão | 2 |
A primeira linha da tabela representa as variáveis escritas assim <variável> nos cenários e as outras linhas são os exemplos para execução dos testes com seus respectivos resultados esperados.
Viu como fica mais fácil de escrever e manter os cenários? Além de serem mais legíveis também.
Organize Diretórios
Existem outras formas de organizar os diretórios dentro do projeto. Porém uma boa prática é criar uma pasta Features e dentro dela criar as seguintes subpastas: pages, onde vão ficar todos os objetos de cada pagina(não precisa se preocupar com isso agora), specifications, onde vão ficar todos os comportamentos do sistema escrito em cucumber, step_definitions, onde vão ficar todos os passo a passo gerados a partir das nossa especificações e support, onde vão ficar algumas configurações, conforme exemplo abaixo: