- Histórico do JUnit
- Planejando seus testes…
- Execução de um arquivo de teste JUnit
- Explicando o arquivo de teste…
- Alterando o arquivo de teste para gerar uma AssertionError
- Alterando o arquivo de teste para gerar uma Exception
- Rodando um package de testes
- Explicação sobre a View JUnit
- Identificação de Erros
- finally{
Olá Pessoal, tudo bom? Neste artigo de hoje vamos verificar como funciona a execução de um teste JUnit. Para configurar um projeto com JUnit favor observar o seguinte artigo.
Histórico do JUnit
JUnit é uma ferramenta de automatização de testes unitários e de testes de regressão para projetos Java. Foi criada por:
A API do JUnit é dividida em duas partes, uma parte que possui métodos e annotations para a construção de classes de teste e outra parte que realiza a execução das classes de teste criadas pela primeira parte.
A execução dos testes é realizada de forma automática e sem intervenção humana. A apresentação dos resultados dos testes é realizada através de um “semáforo”. Uma cor verde no teste significa que este executou conforme estava descrito no arquivo de testes. Uma execução com cor azul, significa que o teste possui algum erro de Assertion, ou seja, que alguma validação do JUnit não foi realizada corretamente. Uma execução com cor vermelha, significa que houve algum tipo de exception no código Java como NullPointerException ou IndexOutOfBoundsException.
Planejando seus testes…
Algo muito importante que deve ser realizado é o planejamento para a execução dos testes. Existem algumas coisas tarefas relacionadas ao planejamento que iremos descrever abaixo:
- Defina um pacote próprio para armazenar todas as classes de testes
- Cada classe de teste deve ser responsável por testar uma classe do sistema
- Use o paradigma do Dividir para Conquistar
- Crie vários métodos de teste que realizam pequenos testes cada um
- A cobertura de testes será muito maior
- Caso ocorram erros, a identificação é mais simples
Vamos que você possui um projeto que seja no formato MVC-DAO, dessa forma teoricamente você teria 3 camadas que não possuem iteração direta com o usuário do software, Model, Business Controller e DAO. Uma boa forma de planejar testes unitários é realizar um produto cartesiano entre as classes da camada Model x 3 camadas que não possuem iteração direta com o usuário (Model, BC e DAO). Vamos imaginar que existem 4 classes na camada Model, dessa forma teremos 12 testes no total, onde seria 4 testes por camada do software.
Talvez nesse cálculo não será possível testar todos os aspectos de todas as classes, mas uma grande cobertura de testes existirá dentro do seu sistema.
Execução de um arquivo de teste JUnit
Um arquivo de teste JUnit é aquele que possui ao menos um método com a annotation @Test, do pacote org.junit. Assim suponha o código de teste abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import static org.junit.Assert.assertTrue; import java.util.Collection; import org.junit.Test; public class JunitTest{ private Collection collection; @Test public void testEmptyCollection(){ assertTrue(collection == null); System.out.println("@Test –Collection nula"); } } |
Vamos agora executar diretamente o código. Depois iremos retornar e falar sobre alguns trechos deste código. Clique sobre a classe de teste e vá na opção Run As > JUnit Test, conforme Figura 03.
O resultado da execução da classe de teste acima pode ser conferido na Figura 04. Repare que a parte esquerda da Figura possui uma linha verde indicando que o teste foi executado com sucesso!
Explicando o arquivo de teste…
Vamos observar com maior detalhes o código executado acima. Repare que esse código possui algumas linhas diferentes do tradicional ao programar classes Java. A linha 08 possui uma annotation @Test. Essa anotation é o que caracteriza um método ser um teste dentro do JUnit. Caso essa anotação não existisse no método o JUnit ignoraria o método. Caso não existe nenhum método com essa anotação ocorreria a seguinte mensagem de erro ao executar o teste JUnit:
A linha 10 possui a invocação de um método static da classe org.junit.Assert, conforme pode ser conferido pelo import static realizado na linha 1. O método da linha 10 está exemplificado abaixo:
1 |
assertTrue(collection == null) |
Ele indica que a operação deverá ser verdadeira, ou seja, o atributo collection deve ser nulo. Caso o que se encontra como parâmetro do método assertTrue não seja True, ocorerrá uma AssertionError e o seu teste será encerrrado. Essa exceção é própria do JUnit e serve para realizar verificações de como está indo o teste e em caso de não estar caminhando de acordo com o que você deseja ocorra a exceção.
As outras linhas da classes não representam nenhuma linha nova para quem já possui alguma experiencia com programação Java.
Alterando o arquivo de teste para gerar uma AssertionError
Vamos alterar o arquivo de teste para gerar um AssertionError, a fim de demonstrar como é o comportamento do JUnit. O código abaixo apresenta a alteração realizada nas linhas marcadas:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import static org.junit.Assert.assertTrue; import java.util.Collection; import org.junit.Test; public class JunitTest{ private Collection collection; @Test public void testEmptyCollection(){ assertTrue(collection != null); System.out.println("@Test –Collection nula"); } } |
Vamos realizar a execução desta classe de teste e o resultado será a Figura 06:
A linha 10 foi modificada para que ao invés de o atributo collection seja igual a null, este seja diferente de null. Como em nenhum momento foi realizada a instanciação dessa Collection, logo o atributo será null, o que irá gerar o erro de assertion. Repare que a linha ficou vermelha, mas a execução errada foi marcada em uma parte da tela indicada por Failures, onde ficou marcado o número 1. Sempre que ocorrer um erro que fique azul o ícone do X ao lado da classe de teste, isso indica que houve um AssertionError. Alguma característica que deveria estar em um determinado estado, mas encontra-se em outro.
Alterando o arquivo de teste para gerar uma Exception
Vamos alterar o arquivo de teste para gerar um Exception, a fim de demonstrar como é o comportamento do JUnit. O código abaixo apresenta a alteração realizada nas linhas marcadas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import static org.junit.Assert.assertTrue; import java.util.Collection; import org.junit.Test; public class JunitTest{ private Collection collection; @Test public void testEmptyCollection(){ collection.clear(); assertTrue(collection == null); System.out.println("@Test –Collection nula"); } } |
Vamos realizar a execução desta classe de teste e o resultado será a Figura 07:
A linha 10 foi modificada para chamar o método clear() do atributo collection. Mas o problema é que o atributo nunca foi inicializado, logo ao chamar o método clear() irá estourar uma NullPointerException, caracterízando um erro no JUnit por exception. Repare que a linha ficou vermelha, e a execução errada foi marcada em uma parte da tela indicada por Errors, onde ficou marcado o número 1. Sempre que ocorrer um erro que deixe o ícone X ao lado da classe de teste na cor vermelha, isso indica que houve um Exception. Normalmente é um erro Java, NullPointerException, IndexOutOfBoundsException entre outras exceptions Java.
Rodando um package de testes
É possível utilizando o comando Run As > JUnit Test rodar um package de testes. Basta clicar sobre um pacote de testes e realizar o comando. O resultado será algo parecido com a Figura 08:
É possível perceber pela Figura 08, que ao rodar esse pacote, cada classe de teste foi exibida na View JUnit e ao expandir uma das classes é possível identificar o que ocorreu para cada teste. Isso facilita na hora de testar vários arquivos de teste com um só comando, otimizando assim o tempo para realizar os comandos de execução dos testes. Da mesma forma que a execução de um único arquivo de teste, o JUnit irá exibir testes de sucesso, AssertionErros e Exceptions.
Explicação sobre a View JUnit
A Figura 09 abaixo mostra a View do JUnit que é aberta ao iniciar a execução de um teste. Vamos explicar abaixo cada um dos pontos, a fim de facilitar o entendimento desta View.
Cada número representa um item dentro da view do JUnit na IDE Eclipse, vamos então explicar cada um deles:
- Botão Next Failed Test – Apresenta o próximo teste que falhou na Test’s List
- Botão Previous Failed Test – Apresenta o teste anterior que falhou na Test’s List
- Botão Show Failures Only – Mostra somente os testes que falharam na Test’s List
- Botão Scroll Lock – Durante a execução dos testes impede de a Test’s List ir deslocando para baixo a cada execução de teste
- Botão Rerun Test – Realiza novamente a execução de todos os testes
- Botão Rerun Test – Failures First – Realiza novamente a execução de todos os testes, mas com os que falharam por primeiro
- Botão Stop JUnit Test Run – Para a execução dos testes
- Botão Test Run History… – Verifica o histórico dos testes executados
- Text Runs – Mostra a quantidade de testes já rodados / quantidade de testes existentes
- Text Errors – Mostra a quantidade de testes que geraram exceções Java
- Text Failures – Mostra a quantidade de testes que geraram AssertionsErrors
- Test’s List – Lista de testes que estão sendo/foram executados
- Failure Trace – Stack trace de onde ocorreu o erro ou falha
Ao lado do item 8, Botão Test Run History… existe um triangulo, o qual há um menu, o qual é mostrado pela Figura 10. A opção mais importante deste menu é a opção Export… onde você poderá exportar um XML com os resultados de todos os testes realizados nessa execução. Dessa forma se você executou o teste de um pacote inteiro, será apresentado cada arquivo de teste e os resultados deste.
Por fim é possível clicar em um teste com erro e realizar a execução somente deste, como mostra a Figura 11.
Aqui você pode rodar o teste novamente com a opção Run, ou até mesmo Debugar o teste com a opção Debug (Não sabe debugar? Sem problemas a partir do dia 06/04/2015 teremos um tutorial nesse link). As outras opção não são importantes nesse momento.
Identificação de Erros
Existe dentro da view JUnit, uma parte chamada Failure Trace. Essa parte possui uma stack trace para identificar a linha que ocorreu o erro na execução do teste. Os testes apresentados até aqui são simples e estão contido em apenas um arquivo, conforme mostra a Figura 07, ao clicar na linha at JunitTest.testEmptyCollection(JunitTest.java:14), o Eclipse irá mostrar selecionada a linha 14, indicando que o erro ocorreu naquela linha. Caso você esteja observando a Figura 08, ao selecionar um teste cujo resultado foi uma Exception, é possível perceber que houve um erro Java, indicando que ele não possui a definição da classe Pessoa.
Quando temos arquivos de testes que necessitam de outras classes para que possam ser realizados (por exemplo, os testes dos branches model, business entre outros dos meus projetos públicos no Bitbucket), essa stack trace é de sumária importância, já que pode identificar qual linha das outras classes ocorreu o erro.
A stack que se encontra dentro da Failure Trace é apenas mais uma ajuda das stack traces impressas no console do Eclipse, quando o erro JUnit for uma Exception Java. Mas pode ser que seja a única a ser impressa, sendo que no console não há nada indicando o erro. Esse comportamento é comum de ocorrer em AssertionErrors.
finally{
Este é apenas o primeiro post sobre JUnit explicando um pouco mais a fundo essa ferramenta muito importante. Não perca nas próximas semanas posts mais profundos sobre essa ferramenta a fim de melhorar o entendimento e ajudar a você a desenvolver a habilidade de criar testes próprios.
Duvidas ou sugestões? Deixe seu feedback! Isso ajuda a saber a sua opinião sobre os artigos e melhorá-los para o futuro! Isso é muito importante!
Até um próximo post!
Juliano says
Bom dia Everson, gostaria de saber se tem como executar meu package de testes por linha de comando.
Estou usando IntelliJ + JUnit e Rest Assured + Maven.
Obrigado.
Mauda says
Olá Juliano, tudo bom?
Desculpe a demora em responder.
Nunca tentei fazer por linha de comando. E também não trabalho com o IntelliJ, mas tente ver esse post:
http://benjamintan.io/blog/2014/10/14/running-junit-test-from-the-command-line/
Obrigado.