testes unitários com junitlmialaret.orgfree.com/tutorial 2 - junit.pdf · as situações de uso de...

18
17/09/13 DevMedia - Leitor Digital www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 1/18 Gostei (0) [easy Java Magazine 16 - Índice] Testes Unitários com JUnit Verificando os métodos de sua classe De que se trata o artigo Neste artigo aprenderemos um pouco sobre Testes de Software, sobre o que é um Teste Unitário, veremos como utilizar o JUnit para criá-los e como implementá-los seguindo as recomendações da Engenharia de Software. Também entenderemos um pouco sobre Cobertura de Código para avaliarmos quão efetivos são os testes unitários criados. Em que situação o tema é útil O tema é útil para os desenvolvedores e times de desenvolvimento que procuram entregar softwares de qualidade. Com os testes de software é possível avaliar se o produto de software que se está entregando ao cliente está bem construído, se está confiável e é possível eliminar erros do mesmo. Resumo Devman Neste artigo fazemos uma breve introdução ao universo dos Testes de Software, mostrando alguns conceitos que devem acompanhar todos os envolvidos no desenvolvimento de um produto de software. Introduzimos quais são os níveis de teste e focamos nos Testes Unitários. Falamos um pouco sobre Cobertura de Código, métrica que nos ajuda a avaliar os testes unitários criados, e criamos uma aplicação de exemplo a partir da qual iniciamos criando os testes unitários utilizando o framework JUnit. Além disso, mostramos passo a passo como criar e aperfeiçoar os testes visando uma maior efetividade dos mesmos, com o objetivo final de entregar uma aplicação um pouco mais robusta, ou seja, que não quebra facilmente devido a erros de programação. O ser humano é suscetível a erros. Quando programamos, procuramos sempre desenvolver uma lógica que implemente o que é requisitado por alguém ou que está especificado em algum documento. Muitas vezes, sem perceber, cometemos pequenos deslizes ao programar, mas continuamos acreditando que nosso código está coerente e consistente. Para verificar, rodamos a nossa aplicação e observamos seu comportamento e suas respostas aos nossos cliques e dados que digitamos. Não ocorreu nenhum erro? Então está perfeito. Será mesmo? E se testarmos com outros dados? Ao inserirmos dados inválidos propositalmente, qual seria o resultado? O que aconteceria se um laço while fosse executado mais vezes do que o esperado? No caso de nosso método possuir um if/else, nosso dado de teste fez o if ser executado? O else foi testado em algum momento? Olhamos de novo, mais 10 vezes, e não conseguimos ver erro nenhum. Estamos certos de Seja bem vindo, Lineu Mialaret! Fale conosco Meus Serviços Tecnologias Revistas Cursos Pocket videos DevWare Fórum Serviços Publicar Comprar

Upload: duongxuyen

Post on 09-Dec-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 1/18

Gostei (0)

[easy Java Magazine 16 - Índice]

Testes Unitários com JUnit

Verificando os métodos de sua classe

De que se trata o artigo

Neste artigo aprenderemos um pouco sobre Testes de Software, sobre o que é um Teste

Unitário, veremos como utilizar o JUnit para criá-los e como implementá-los seguindo as

recomendações da Engenharia de Software. Também entenderemos um pouco sobre

Cobertura de Código para avaliarmos quão efetivos são os testes unitários criados.

Em que situação o tema é útil

O tema é útil para os desenvolvedores e times de desenvolvimento que procuram entregar

softwares de qualidade. Com os testes de software é possível avaliar se o produto de software

que se está entregando ao cliente está bem construído, se está confiável e é possível eliminar

erros do mesmo.

Resumo Devman

Neste artigo fazemos uma breve introdução ao universo dos Testes de Software, mostrando

alguns conceitos que devem acompanhar todos os envolvidos no desenvolvimento de um

produto de software. Introduzimos quais são os níveis de teste e focamos nos Testes Unitários.

Falamos um pouco sobre Cobertura de Código, métrica que nos ajuda a avaliar os testes

unitários criados, e criamos uma aplicação de exemplo a partir da qual iniciamos criando os

testes unitários utilizando o framework JUnit. Além disso, mostramos passo a passo como criar

e aperfeiçoar os testes visando uma maior efetividade dos mesmos, com o objetivo final de

entregar uma aplicação um pouco mais robusta, ou seja, que não quebra facilmente devido a

erros de programação.

O ser humano é suscetível a erros. Quando programamos, procuramos sempre desenvolver

uma lógica que implemente o que é requisitado por alguém ou que está especificado em algum

documento. Muitas vezes, sem perceber, cometemos pequenos deslizes ao programar, mas

continuamos acreditando que nosso código está coerente e consistente. Para verificar,

rodamos a nossa aplicação e observamos seu comportamento e suas respostas aos nossos

cliques e dados que digitamos. Não ocorreu nenhum erro? Então está perfeito. Será mesmo?

E se testarmos com outros dados? Ao inserirmos dados inválidos propositalmente, qual seria o

resultado? O que aconteceria se um laço while fosse executado mais vezes do que o

esperado? No caso de nosso método possuir um if/else, nosso dado de teste fez o if ser

executado? O else foi testado em algum momento?

Olhamos de novo, mais 10 vezes, e não conseguimos ver erro nenhum. Estamos certos de

Seja bem vindo, Lineu Mialaret! Fale conosco Meus Serviços

Tecnologias Revistas Cursos Pocket videos DevWare Fórum Serviços Publicar Comprar

Page 2: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 2/18

que o código está correto. Pelo menos, pressupomos que esteja. Para ampliarmos nossa

certeza, vamos conhecer um pouco sobre Testes de Software e aprender algumas técnicas

que nos mostram que, apenas com concentração e boa intenção, não conseguimos enxergar

os problemas que estão presentes.

O que é Teste de Software? Durante o processo de desenvolvimento, há os momentos de verificar se o software que

estamos construindo está correto e se o que estamos desenvolvendo é o que o cliente ou o

usuário realmente quer. Estes momentos de verificação fazem parte de um processo chamado

Verificação e Validação, também referenciado como V & V, e devem ocorrer em várias fases

da construção do software. Validação é o processo que visa garantir que se está construindo

o programa que o cliente de fato deseja utilizar, com as funcionalidades que ele espera que

estejam disponíveis. Ou seja, conseguimos compreender o que o cliente quer e o entregamos

conforme acertado. Verificação é o processo de garantir que o produto de software está sendo

bem construído, executando corretamente, mostrando as mensagens corretas, sem ocorrer

falhas durante sua operação. Assim esperamos.

Teste de Software é parte integrante de V & V e corresponde ao processo que consiste de

todas as atividades do ciclo de vida referentes à avaliação do software, com o objetivo de se

determinar três coisas: (1) que o mesmo satisfaz aos requisitos especificados; (2) que o

mesmo está apto para ser liberado para o cliente; (3) e para encontrar defeitos, motivo que

todos pensam ser o único.

Portanto, testar um programa não é apenas procurar erros, é um processo bem mais amplo,

com seus papéis, atividades e artefatos resultantes.

Um Caso de Teste, que nós chamamos apenas de Teste, consiste de:

• Um conjunto de valores de entrada para o sistema;

• As ações a serem executadas pelo testador ou outro programa que interaja com o software

que está sendo testado;

• Os resultados esperados como consequências das ações executadas; e

• As pós-condições, que são o resultado final gerado como consequência do que foi executado

ao longo do teste.

Para conhecer os vários tipos de teste e entender em que momento eles se aplicam, veja a

Figura 1, conhecida como Modelo V, que mostra como as atividades de teste podem ser

integradas em cada fase do ciclo de vida de desenvolvimento. Quatro tipos diferentes são

mostrados, onde cada um deles é aplicado em um nível diferente dos artefatos da aplicação,

desde um simples método até o sistema inteiro. Por isso eles definem os Níveis de Teste.

Níveis de Teste - entendendo melhor

Vamos entender estes “níveis” melhor.

Após a codificação do sistema, criação das classes, definição de seus atributos e

implementação de seus métodos, iniciamos o desenvolvimento dos Testes Unitários, que

consiste em checar se os métodos de uma classe funcionam corretamente (este é o foco deste

artigo).

Depois que todos os métodos que interessam foram testados separadamente, inicia-se os

Testes de Integração, onde se procura verificar a comunicação entre as classes. Por exemplo,

procura-se verificar os resultados dos métodos de uma determinada classe quando chamados

por métodos de outras. Nesta fase, vai-se integrando do nível mais granulado, de classe em

classe, indo até componentes inteiros interagindo com outros, mas sempre observando as

estruturas internas que estão sendo testadas nos códigos, suas condições e seus laços. Estes

testes, os unitários e os de integração, são também chamados de “Testes de Caixa Branca”,

porque estamos olhando o que há dentro do código-fonte para poder testá-los.

Após a integração, se junta todos os componentes e demais recursos que compõem o

sistema e começam-se os Testes de Sistema. Neste nível não se checa mais o código, mas se

a aplicação está fazendo corretamente o que está especificado nos requisitos, testando-a

Page 3: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 3/18

através das interfaces gráficas, checando relatórios e demais artefatos gerados, simulando

mais ou menos o que um usuário faria ao usar o sistema.

Por último, os Testes de Aceitação são realizados, geralmente, pelos próprios clientes ou

usuários, onde se procura verificar se as necessidades deles foram adequadamente atendidas

e se o sistema oferece o que eles esperam.

Se estiver OK, o sistema é aceito e vai para produção. Tanto os testes de sistema quanto os

de aceitação, diferentemente dos dois primeiros, são chamados de “Testes de Caixa Preta”,

pois não se sabe como o código está estruturado, não se tem a visão de dentro da caixa.

Testa-se sem se preocupar com isso, pois o que interessa agora é a funcionalidade de alto

nível, na visão do usuário ou cliente.

NotaMuitas vezes ouvimos falar em versão beta de algum aplicativo. Isto nada mais é do que

uma versão disponibilizada para um Teste de Aceitação a ser realizado por uma grande

quantidade de usuários finais em um ambiente de uso real. As empresas procedem assim

porque, muitas vezes, é impossível ao time de desenvolvimento ou de testes prever todas

as situações de uso de uma ferramenta na prática.

[abrir imagem em janela]

Figura 1. Modelo V.

Aprofundando em Testes de Unidade ou Unitários Testes de Unidade são testes que verificam a menor unidade de projeto do software que, em

um sistema orientado a objetos, é o método. Sua meta é encontrar defeitos. Falando de forma

mais prática, testes unitários são nada mais do que outra classe Java que você cria para testar

seu código. Esta classe deve possuir métodos nos quais você instancia a classe que deseja

testar, chama seus métodos passando os parâmetros necessários, recupera seu resultado e o

avalia comparando com o que você esperava que fosse retornado. Veremos mais a frente

como implementá-los.

É importante criar testes que “exercitem” todos os métodos de uma classe e cada estrutura

que há dentro de cada um deles, ou seja, ifs, elses, for, forEach, entre outras. “Exercitar” é um

termo que significa executar um trecho de código com um teste. Portanto, é importante que

criemos testes que exercitem todas as partes do código.

Quando criamos testes unitários que atinjam a condição de exercitar muitas partes do código,

dizemos que atingimos uma boa “cobertura de código”.

“Cobertura” é uma indicação de quais linhas, e quais caminhos diferentes dentro dos métodos,

conseguimos verificar nos nossos testes.

Veja o tópico “Cobertura de Código” para entender melhor como se consegue uma boa

cobertura verificando linhas e caminhos.

Apenas para ilustrar, observe o código da Listagem 1. Vemos que há um método calcular()

que possui um while que, por sua vez, possui um if/else. É importante observar que, ao

criarmos testes unitários para este exemplo, devemos exercitar o laço while, o if e o else.

Quantos testes unitários seriam necessários para isso?

Page 4: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 4/18

Para exercitar o while, precisamos que qtd tenha um valor menor do que 50, caso contrário,

não ocorreria nenhuma iteração. Se o valor informado em qtd for igual a 10, exercitaríamos o

while e o if. Teríamos, assim, um teste passando 10 para qtd. Se criássemos outro teste onde

o valor passado fosse menor que 50, não sendo 10, teríamos exercitado o while e o else.

Concluindo, precisaríamos de dois testes unitários para atingir uma boa cobertura do código

da Listagem 1.

Usando TDD - Test Driven Developme

Notant ou Desenvolvimento Guiado Por Testes - o desenvolvedor, antes mesmo de começar a

programar, inicia com a criação de um teste unitário e, só depois, implementa o método.

Afinal, o teste é que guia o desenvolvimento. Se você vai iniciar um projeto ou alguma

nova funcionalidade, pesquise esta técnica.

Listagem 1. Exemplo de método a ser exercitado.

public void calcular (int qtd) {

while (qtd < 50) {

if (qtd == 10) {

// realiza alguma operacao.

} else {

// senão, realiza outra operacao.

}

}

}

Cobertura de Código Cobertura de Código é um método de análise que permite verificarquão efetivo foram os testes unitários. Com este método é possível

ter a noção de quais partes do software foram, ou não, executadas(ou cobertas) pela suite de testes. Lembrando que quando

executadas, dizemos que tais partes foram “exercitadas”.

Para avaliar a cobertura de código, criaram-se várias métricas querealizam diversas verificações no código testado. Dentre as mais

utilizadas estão: cobertura de comandos (statement coverage) e acobertura de desvios (branch coverage). Vamos entendê-las nos

parágrafos seguintes.

A Cobertura de Comandos (statement coverage), tambémconhecida como cobertura de linha, mede que linhas foram

exercitadas pelos testes unitários. Por exemplo, no código a seguir, é possível notar que se criarmos

um único teste unitário passando para o methodA() os valores 5 e

4, apenas a linha do if, que soma ‘a´ + ‘b´, e a linha que retorna ‘c´seriam exercitadas.

Neste caso, não conseguiríamos exercitar todos os comandos donosso método. Portanto, a cobertura de linhas do método não seria

de 100%.

public int methodA(int a, int b) {if(a > b) {

c = a + b;}

else {

c = a - b;}

return c;

Page 5: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 5/18

}

Neste caso, cobrimos apenas um desvio, o do if. Portanto,

também não temos 100% de cobertura de desvios. Paraconseguirmos cobrir 100% das linhas deste código e cobrir todos

os desvios, será necessário criar mais um teste unitário passandoqualquer valor onde ‘b´ é maior que ‘a´, podendo ser 5 e 4, por

exemplo. Com isso, conseguiríamos exercitar o else. Olhando a

cobertura dos dois testes separadamente, nenhum deles conseguealcançar os 100%. Mas uma suite de testes, que é um conjunto

destes, com os dois juntos atingem os objetivos, tanto o dacobertura de comandos, ou linhas, quanto o da cobertura de

desvios.

Assim, é fácil identificar que precisaríamos de dois

testes unitários, mas em uma situação mais complexa,

no dia a dia, não seria tão evidente. Por este motivo o

uso destas técnicas faz a diferença.

Criando nossa aplicação de

exemplo Para ilustrar o uso de testes unitários com o JUnit,

vamos criar uma aplicação de exemplo bem simples,

mas que contém os elementos que são importantes de

destacar na hora de testar as unidades de um sistema.

Para isso, utilizaremos a IDE Eclipse Indigo.

A nossa aplicação é responsável por fazer um

controle de empréstimo de livros. Para isso,

precisamos de uma entidade Livro para poder iniciar

os trabalhos. A Listagem 2 mostra como seria a nossa

classe. A mesma tem os atributos autor, titulo,

emprestado e reservado. Estes dois últimos guardam o

status em relação a sua disponibilidade, está

emprestado (true) ou não (false) e reservado (true) ou

não (false). Também possui um atributo chamado

historico que é do tipo lista de Emprestimos, cuja

classe pode ser vista na Listagem 3.

Cada empréstimo da lista contém informações como

quem foi o Usuario (Listagem 4) que pegou o livro

emprestado, qual foi a data do empréstimo

(dataEmprestimo), e qual foi a data da devolução

(dataDevolucao), ambos do tipo Date, e a lista de livros

locados pelo usuário.

Livro possui o método emprestar(), que simplesmente

verifica se o atributo emprestado está como false,

antes de emprestá-lo setando true. Ao fazê-lo, também

imprime uma mensagem no console do

Eclipse/NetBeans informando que o livro foi

emprestado com sucesso. Esta classe também possui

o método consultarEmprestimosPorUsuario(), para o

qual é passada uma instância da classe Usuario, na

Listagem 4. Esta nossa aplicação de brinquedo tem o

objetivo apenas de criar elementos com as estruturas

necessárias para exemplificar o uso de testes unitários

com o JUnit.

Listagem 2. Classe Livro da nossa aplicação fictícia

Page 6: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 6/18

de controle de empréstimos.

public class Livro {

private String autor;

private String titulo;

private boolean emprestado;

private boolean reservado;

private List<Emprestimo> historico;

public boolean emprestar(){

if(!this.isEmprestado()){

this.setEmprestado(true);

System.out.println("Livro emprestado com sucesso.");

}

return this.isEmprestado();

}

public List<Emprestimo> consultarEmprestimosPorUsuario(Usuario usuario)

{

List<Emprestimo> emprestimosPorUsuario = new ArrayList<Emprestimo>

();

for (Emprestimo emprestimoUsuario : emprestimosPorUsuario) {

if(emprestimoUsuario.getUsuario().equals(usuario))

{

emprestimosPorUsuario.add(emprestimoUsuario);

}

}

return emprestimosPorUsuario;

}

}

Listagem 3. Classe Emprestimo da nossa aplicação

fictícia de controle de empréstimos.

public class Emprestimo {

private Usuario usuario;

private Date dataEmprestimo;

private Date dataDevolucao;

private List<Livro> livros;

}

Listagem 4. Classe Usuario com método equals().

public class Usuario {

private String nome;

private String matricula;

private boolean emDebito;

public Usuario(String nome, boolean emDebito) {

super();

this.nome = nome;

this.emDebito = emDebito;

}

@Override

public boolean equals(Object obj){

if(obj instanceof Usuario){

Usuario outro = (Usuario) obj;

return outro.getNome().equals(getNome());

} else {

return false;

}

}

}

No método consultarEmprestimosPorUsuario() é

necessário fazer uma comparação para saber se o

Page 7: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 7/18

usuário passado como parâmetro tem o mesmo nome

do usuário que fez o empréstimo, portanto a classe

Usuario sobrescreve o método equals(). Para

comparações utilizando este método, é necessário

sobrescrevê-lo, o implementando da forma que for

desejada; no caso, comparando pelo atributo nome. Se

fizéssemos a mesma comparação sem sobrescrevê-lo,

duas instâncias de Usuario só seriam iguais se

referenciassem exatamente o mesmo objeto, pois Java

compararia a identidade do objeto, que é diferente

para cada instância presente na JVM.

Exposta a estrutura da nossa aplicação, que contém

alguns erros que passaram despercebidos, vamos

instalar o JUnit para que possamos verificar nossos

métodos.

Instalando o JUnit O JUnit é um framework de testes unitários

desenvolvido em Java por iniciativa de Kent Beck e

Erich Gamma. Ele já vem integrado nas IDEs mais

atuais. No momento de criar seu projeto, basta

adicioná-lo ao Java Build Path clicando no seu projeto

e selecionando o menu File | Properties > Java Build

Path, selecionando a aba Libraries e pressionando o

botão Add Library, como mostra a Figura 2.

Na tela Add Library, selecione a opção JUnit e

pressione o botão Next. Então, mude a opção JUnit

library version para JUnit 4, como mostra a Figura 3, e

clique em Finish. A versão que vem pré-instalada no

Eclipse Indigo é a versão 4.8.2.

Outra opção seria acessar o site do JUnit e baixar a

última versão (no momento da escrita deste artigo é a

4.10). Baixe o arquivo junit-<versao>.jar, crie uma

pasta lib na raiz do seu projeto, se já não houver.

Adicione seu arquivo jar nesta pasta. Faça um refresh

do seu projeto para visualizar a pasta e o arquivo.

Clique com o botão direito do mouse sobre o arquivo e

selecione a opção Build Path > Add to Build Path. Ao

concluir estes passos, seu projeto já estará apto para

utilizar os recursos disponibilizados pelo JUnit para

criação de testes unitários.

[abrir imagem em janela]

Page 8: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 8/18

Figura 2. Adicionando o JUnit ao build path.

[abrir imagem em janela]

Figura 3. Alterando a versão do JUnit.

Criando os testes unitários de

nossa aplicação O nosso objetivo no momento é conseguir aplicar a

teoria que vimos até então no software de exemplo que

criamos no tópico anterior. Ao utilizar as técnicas

apresentadas, conseguiremos criar bons testes

unitários e, por consequência, obteremos uma boa

“cobertura” com os mesmos.

Antes de qualquer coisa, é uma prática criar os testes

unitários em um pacote à parte, geralmente chamada

test, dentro da pasta src.

Procure criar os pacotes de teste com caminhos

similares aos das classes testadas. Por exemplo, para

as classes do pacote biblioteca.entidade, crie classes

de teste em um pacote biblioteca.entidade.test. No final

das contas, a estrutura de pastas de nosso projeto

ficaria como indicado na Figura 4.

[abrir imagem em janela]

Page 9: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 9/18

Figura 4. Estrutura de pastas do projeto.

Geralmente, cria-se uma classe de teste para cada

classe a ser testada do projeto. Para criar testes

unitários para a nossa aplicação com o JUnit, é

necessário selecionar uma classe.

Assim, vamos utilizar Livro. Pressione o botão direito

do mouse em cima dela. Ao abrir o menu, selecione

New > JUnit Test Case. Uma tela como a da Figura 5 é

exibida. Informe o nome que desejar para a classe de

teste. O default é: <o nome da classe a ser

testada>+“Test”, no nosso caso, LivroTest.

[abrir imagem em janela]

Figura 5. Tela de caso de teste.

Na Figura 5, onde vemos o campo Package, indique o

pacote de testes. No campo Name, você pode indicar o

nome que quiser, possuindo ou não o sufixo “Test”. O

mais interessante de observar é o conjunto de caixas

de checagem que tem mais abaixo na Figura 5. Dentre

elas, setUp() já vem marcada. Deixe assim - veremos

mais adiante do que se trata, e clique em Next >.

A próxima tela pode ser observada na Figura 6. Nela

é possível ver a classe selecionada e os seus

métodos. Ao selecioná-los, uma classe de teste será

criada com testes apenas para os métodos que foram

selecionados. Não é necessário criar testes para os

Page 10: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 10/18

gets e sets, a não ser que eles contenham alguma

regra de negócio. Deste modo, marque os métodos

emprestar() e consultarEmprestimosPorUsuario() e

clique em Finish.

[abrir imagem em janela]

Figura 6. Selecionando os métodos a se testar.

O resultado é o mostrado na Listagem 5. Observe

que há três métodos: setUp(), testEmprestar() e

testConsultarEmprestimosPorUsuario(). O primeiro foi

criado automaticamente porque a caixa de checagem

de mesmo nome, exibida na Figura 5, estava marcada.

Este método está anotado com @Before, o que

determina que será executado antes de qualquer

método de teste desta classe. Nele, é possível criar

qualquer configuração inicial que será utilizada pelos

demais testes da classe, como instanciar e atribuir

elementos a uma coleção, instanciar demais objetos

necessários, conectar com algum recurso, entre outras

coisas. Os dois métodos seguintes são os da classe

Livro que selecionamos para teste, como indica a

Figura 6, acrescidos da palavra “test” como prefixo,

que não é obrigatório. Eles são anotados com @Test,

o que determina para o JUnit quem são os métodos de

teste.

Listagem 5. Código da classe LivroTest.

public class LivroTest {

@Before

public void setUp() throws Exception {}

@Test

public final void testEmprestar() {

fail("Not yet implemented"); // TODO

}

@Test

public final void testConsultarEmprestimosPorUsuario() {

fail("Not yet implemented"); // TODO

}

}

Page 11: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 11/18

Para executar esta classe de teste recém-criada,

basta clicar com o botão direito em cima da mesma, no

Project Explorer, e selecionar Run As > JUnit Test.

O JUnit abrirá uma view como a mostrada na Figura 7,

onde é possível ver o tempo gasto na execução dos

testes, quantos foram rodados do total (Runs: 2/2),

quantos erros ocorreram (Errors: 0) e quantas falhas

(Failures: 2). Um erro indica que ocorreu algum

problema e o teste não foi concluído. Uma falha indica

que o teste foi concluído e o resultado esperado não

foi o desejado, portanto, há algum defeito na classe

sendo testada.

Ao clicarmos no método testEmprestar() na view do

JUnit, por exemplo, é possível ver qual a razão do

mesmo ter falhado observando a Failure Trace. Neste

ponto, criamos uma classe de testes unitários e os

executamos. O que nos falta agora é colocar a lógica

de teste nestes métodos, instanciando as classes de

nossa aplicação dentro deles, chamando seus

métodos e verificando os resultados.

[abrir imagem em janela]

Figura 7. Resultado da execução inicial da classe

LivroTest.

Implementando nosso teste

Após termos aprendido como criar e executar um

teste unitário, vamos implementar a nossa classe de

teste, LivroTest. Para começar, crie um membro Livro

nela. Vamos instanciá-lo no método setUp(). Configure

seus atributos da seguinte forma: o autor será “Jorge

Amado”, o titulo será “Capitães da Areia” e

determinaremos que o atributo reservado, passado no

construtor, será false. Além disso, crie três instâncias

de Emprestimo, determine o Usuario de cada uma

delas, como mostrado na Listagem 6, e os adicione ao

atributo historico, do objeto livro. Observe que o

usuário “José” se repete, pois seria seu segundo

empréstimo deste livro. Desta forma temos um livro de

Jorge Amado que foi locado três vezes, duas das quais

por José. O segundo parâmetro do construtor de

Usuario é o status que indica se o mesmo está em

débito ou não. Na terceira locação, representado pelo

Page 12: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 12/18

objeto emprestimo3, José estava com débitos na

biblioteca. Este é o contexto no qual estamos

configurando nosso teste da classe Livro.

Listagem 6. Método setup() da classe LivroTest.

public class LivroTest {

Livro livro;

@Before

public void setUp() {

livro = new Livro("Jorge Amado", "Capitães da Areia", false);

Emprestimo emprestimo1 = new Emprestimo();

emprestimo1.setUsuario(new Usuario("Jose", false));

Emprestimo emprestimo2 = new Emprestimo();

emprestimo2.setUsuario(new Usuario("João", false));

Emprestimo emprestimo3 = new Emprestimo();

emprestimo3.setUsuario(new Usuario("Jose", true));

livro.getHistorico().add(emprestimo1);

livro.getHistorico().add(emprestimo2);

livro.getHistorico().add(emprestimo3);

}

// demais métodos omitidos.

}

Para cada “objeto de teste”, no caso cada método da

classe Livro, é interessante realizar um “teste positivo”,

no qual testamos uma situação de sucesso, e um

“teste negativo”, no qual verificamos se nossa

aplicação trata corretamente uma situação incorreta. A

partir de agora, incrementaremos um pouco mais o

nosso teste. Observando a classe Livro, na Listagem

2, o método emprestar() apenas verifica se o livro não

está emprestado para que ele possa atribuir true ao

atributo emprestado, ou seja, emprestá-lo. Caso esteja

emprestado, não faz nada e retorna a situação atual

do livro. Portanto, precisamos fazer dois testes: um

positivo, no qual o livro não está emprestado e

chamamos o método emprestar(); e outro negativo, no

qual o livro já está emprestado e chamamos o método

emprestar() mesmo assim.

Observando os objetivos de cobertura que vimos

antes, neste método temos uma estrutura if, portanto é

importante criar duas situações: uma onde a condição

lógica seja verdadeira, para entrar no mesmo; e outra

onde a condição seja falsa, para não entrar e não

realizar qualquer operação, para assim podermos

avaliar o comportamento completo do método.

É importante verificar as duas situações de uma

condição lógica para podermos avaliar o que acontece

com os objetos e variáveis manipulados pelo método

caso as operações que deveriam ser realizadas dentro

do if não se realizem.

Alguns erros podem estar contidos aí. Com este fim,

renomeamos o método da classe de teste

testEmprestar() para

testEmprestarLivroNaoReservado() e criamos o

testEmprestarLivroReservado() que corresponde ao

“teste negativo” de empréstimo de um livro. Estes dois

Page 13: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 13/18

métodos ficariam como na Listagem 7.

Com o JUnit, a forma de verificarmos se o resultado

da classe a ser testada é o esperado ou não é

utilizando um conjunto de assertivas: assertTrue(),

assertFalse(), assertEquals(), assertNull(),

assertNotNull(), só para citar algumas. Portanto, se

esperamos um valor lógico true como resultado de um

método, utilizamos o assertTrue() passando como

parâmetro o retorno do método. Se desejamos verificar

que dois objetos são iguais, um retornado por um

método e outro que você criou no corpo do método de

teste unitário, utilizamos um assertEquals() passando

os dois objetos como primeiro e segundo parâmetros.

Listagem 7. Métodos da classe LivroTest.

public class LivroTest {

Livro livro;

@Before

public void setUp() {

livro = new Livro("Jorge Amado", "Capitães da Areia", false);

Emprestimo emprestimo1 = new Emprestimo();

emprestimo1.setUsuario(new Usuario("Jose", false));

Emprestimo emprestimo2 = new Emprestimo();

emprestimo2.setUsuario(new Usuario("João", false));

Emprestimo emprestimo3 = new Emprestimo();

emprestimo3.setUsuario(new Usuario("Jose", true));

livro.getHistorico().add(emprestimo1);

livro.getHistorico().add(emprestimo2);

livro.getHistorico().add(emprestimo3);

}

@Test

public void testEmprestarLivroNaoReservado(){

assertTrue(livro.emprestar());

}

@Test

public void testEmprestarLivroReservado(){

livro.setReservado(true);

assertFalse(livro.emprestar());

}

// demais métodos omitidos.

}

Com a classe de teste mais completa, podemos

executá-la novamente.

Ao executar, é possível verificar que o teste

testEmprestarLivroReservado() falha. Por que será?

Se você observar, o nosso teste está correto, pois não

podemos emprestar um livro que está reservado. Esta

falha nos mostra um erro de lógica na nossa aplicação.

Se um estudante, ou usuário da biblioteca, pegar um

exemplar na estante e levar até a bibliotecária para

pegá-lo emprestado, ela não precisa checar se o livro

está emprestado ou não, visto que o mesmo estava

disponível no acervo. Para os operadores do nosso

sistema, isto não faz sentido: ou o livro está disponível

Page 14: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 14/18

nas dependências da biblioteca, ou já está emprestado

para outro usuário. A implementação mais adequada

do método emprestar(), da nossa classe Livro, seria

como o mostrado na Listagem 8. Quanto à reserva,

devemos verificar se o livro está ou não reservado e,

por algum motivo, não estava separado dos demais, no

setor de reservas. Caso esteja reservado, não se pode

emprestá-lo. Caso contrário, o usuário poderá ter uma

boa leitura no conforto do seu lar. O nosso teste nos

mostrou uma falha negocial ao refletirmos sobre a

lógica do método a ser testado. Ao executarmos os

testes novamente, podemos verificar que agora ele

passou. O ícone ao lado do nome do teste, na view do

JUnit, se torna uma checagem verde ( ).

Listagem 8. Nova implementação do método

emprestar() da classe Livro.

public boolean emprestar(){

if(this.isReservado()){

this.setEmprestado(false);

System.out.println("Livro está reservado.");

} else {

this.setEmprestado(true);

System.out.println("Livro emprestado com sucesso.");

}

return this.isEmprestado();

}

Vamos agora implementar os testes do método

consultarEmprestimosPorUsuario(). Este método

possui uma lista dos empréstimos do livro e itera sobre

ela buscando se o usuário é o mesmo que o passado

por parâmetro, como mostrado na Listagem 2. Quando

há laços, uma recomendação mais rigorosa nos exige

criar pelo menos três testes: um teste onde

executamos o laço pelo menos uma vez; outro onde

não executamos nenhuma; e outro quando executamos

mais de duas vezes. Porque não executar nenhuma?

Às vezes, nós contamos que sempre ocorrerá várias

iterações de um laço e implementamos o método

contando com isso, definindo um conjunto de

operações dentro do mesmo. Quando o laço não é

executado nenhuma vez, e não contávamos com isso,

alguma operação óbvia deixou de ser executada,

comprometendo assim toda a função do método e,

consequentemente, prejudicando quem aguardava o

retorno do mesmo. A nossa classe de teste ficaria

como mostra a Listagem 9.

Listagem 9. Código da classe LivroTest.

public class LivroTest {

Livro livro;

@Before

public void setUp() {

livro = new Livro("Jorge Amado", "Capitães da Areia", false);

Emprestimo emprestimo1 = new Emprestimo();

emprestimo1.setUsuario(new Usuario("Jose", false));

Page 15: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 15/18

Emprestimo emprestimo2 = new Emprestimo();

emprestimo2.setUsuario(new Usuario("João", false));

Emprestimo emprestimo3 = new Emprestimo();

emprestimo3.setUsuario(new Usuario("Jose", true));

livro.getHistorico().add(emprestimo1);

livro.getHistorico().add(emprestimo2);

livro.getHistorico().add(emprestimo3);

}

@Test

public void testEmprestarLivroNaoReservado(){

assertTrue(livro.emprestar());

}

@Test

public void testEmprestarLivroReservado(){

livro.setReservado(true);

assertFalse(livro.emprestar());

}

@Test

public void testNenhumEmprestimoPorUsuario(){

Usuario novoUsuario = new Usuario("Judas", false);

List<Emprestimo> historico = livro.consultarEmprestimosPorUsuario(novoUsuario);

int resultadoReal = historico.size();

assertEquals(0, resultadoReal);

}

@Test

public void testUmEmprestimoPorUsuario(){

Usuario novoUsuario = new Usuario("João", false);

List<Emprestimo> historico = livro.consultarEmprestimosPorUsuario(novoUsuario);

int resultadoReal = historico.size();

assertEquals(1, resultadoReal);

}

@Test

public void testDoisEmprestimosPorUsuario(){

Usuario novoUsuario = new Usuario("Jose", false);

List<Emprestimo> historico = livro.consultarEmprestimosPorUsuario(novoUsuario);

int resultadoReal = historico.size();

assertEquals(2, resultadoReal);

}

}

Ao executarmos nossos testes agora, vemos que

quase todos passaram, com exceção de

testUmEmprestimoPorUsuario() e

testDoisEmprestimosPorUsuario(). Quando analisamos

o método consultarEmprestimosPorUsuario() da classe

Livro, verificamos que há um erro muito elementar:

esquecemos que o método itera por uma coleção que

foi criada dentro dele mesmo. Como poderia ter

alguma coisa se acabamos de criá-la? A correção

deste problema consiste apenas em alterar a instrução

for para que itere na coleção historico, membro da

classe Livro, e não na coleção emprestimosPorUsuario,

que é interna ao método e é, na verdade, seu objeto

de retorno. Após esta correção, todos os testes

passam com sucesso, como mostra a Figura 8.

[abrir imagem em janela]

Page 16: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 16/18

Figura 8. Resultado dos testes com sucesso.

Parece óbvio, mas qual o benefício mesmo?

Realmente parece óbvio, pois quando estamos

criando testes unitários, estamos criando métodos para

testar outros métodos. E ao fazer isto, também

estamos corrigindo nossa aplicação. Ao criá-los,

devemos fazê-lo buscando verificar cada estrutura de

cada método, para a maior quantidade de métodos

possível de nossa aplicação.

Tendo esta coleção de testes em mãos, toda vez que

for necessário fazer alguma alteração nas regras de

negócio ou corrigir algum erro encontrado por um

usuário ou até mesmo uma melhoria, altere

tranquilamente. Após fazer o que é necessário, basta

reexecutar o seu arsenal de testes já pronto para

verificar se o que você alterou, corrigiu ou melhorou,

não danificou alguma parte do sistema que já estava

funcionando.

A consequência negativa que pequenas alterações

podem acarretar ao sistema também é conhecida por

“efeito gelatina”; como se sua aplicação fosse uma

gelatina num pires sendo arrastado sobre uma mesa

que, ao mexer, tudo treme. Analogamente ao

desenvolvimento de sistemas, se você fizer uma

pequena alteração, esta poderia causar algum tremor

no seu sistema, pois, sem querer, poderia ter

consequências em outras partes que se relacionam

com a parte alterada.

Os testes unitários evitam este efeito porque antes de

liberar um build do sistema, você reexecutaria os testes

unitários. Desta forma você se sentirá bem mais

seguro ao mexer em um código que já existe e/ou que

foi criado por outro programador.

Conclusões Neste artigo, aprendemos sobre o que é Teste de

Software, qual o seu papel no processo de

desenvolvimento de software e quais os Níveis de

Teste que são definidos nesta área específica da

Engenharia de Software. Aprofundamos no nível

específico dos Testes de Unidade (ou unitários), sua

definição e seu papel dentro dos testes em geral.

Page 17: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 17/18

eduardo vinicius ferreira deoliveira

31/3/2012 14:20 Boa tarde, estou tentando fazer os testes com o JUnit seguindo os passos do artigo mas

estou com o seguinte erro:

Could not connect to: : 49382

java.net.ConnectException: Connection refused: connect

at java.net.DualStackPlainSocketImpl.connect0(Native Method)

at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)

at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:337)

at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:198)

at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)

at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)

at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)

at java.net.Socket.connect(Socket.java:579)

at java.net.Socket.connect(Socket.java:528)

at java.net.Socket.(Socket.java:425)

at java.net.Socket.(Socket.java:208)

at

org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.connect(RemoteTestRunner.java:570)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:381)

at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Aprendemos também a criar testes unitários utilizando

um framework bastante conhecido, o JUnit, que,

enquanto este artigo estava sendo escrito, sua versão

mais recente era a 4.10. Ao longo do artigo, criamos

uma aplicação de brinquedo apenas para ilustrar

situações corriqueiras e importantes nas quais os

testes de unidade podem ajudar bastante no processo

de codificação de um sistema.

Falamos superficialmente sobre um método de análise

que nos permite avaliar quão efetivo estão os nossos

testes unitários, método este que nos auxilia na

necessidade de identificar se precisamos criar mais

testes ou não, que são as métricas de cobertura de

código.

Assim, esperamos ter demonstrado de forma clara e

didática para quê servem os testes unitários, como

criá-los da melhor forma e qual a sua grande utilidade

ao longo do desenvolvimento e manutenção de um

sistema.

João dos Prazeres Farias

Mestre em Ciência da Computação com ênfase em automação de

testes pela UFPE, bacharel em Ciência da Computação pela UNICAP.

Professor do Instituto Superior Fátima, em Brasília, ministrando as

disciplinas de Lógica de Programação e Projeto I e II. É desenvolvedor

desde 1999 e trabalha com Java desde 2006.

Page 18: Testes Unitários com JUnitlmialaret.orgfree.com/Tutorial 2 - JUnit.pdf · as situações de uso de uma ferramenta na prática. [abrir imagem em janela] Figura 1. Modelo V. ... do

17/09/13 DevMedia - Leitor Digital

www.devmedia.com.br/websys.5/webreader.asp?cat=61&artigo=4419&revista=easyjavamag_16#a-4419 18/18

O que devo fazer ?

desde ja agradeço

Responder

WESLEY YAMAZACK4/2/2012 10:14:47 PM

Olá Eduardo, solicitei um dos nossos consultores a te ajudar, peço que aguarde um

pouco.

Obrigado e um abraço Responder

DYEGO SOUZA DO CARMO4/3/2012 8:44:36 AM

Chegou a carregar o Bacno de DAdos/Servidor de Aplicação ?

Este erro quer dizer que o servidor/banco estão baixados. Responder

DevMedia | Anuncie | Fale conosco

Hospedagem web por Porta 80 Web Hosting

2013 - Todos os Direitos Reservados a web-03

DevMedia

Curtir

13.551 pessoas curtiram DevMedia.

Plug-in social do Facebook