testes de unidade com junit

58

Upload: cejug

Post on 06-Jun-2015

4.449 views

Category:

Technology


0 download

DESCRIPTION

Palestra ministrada por Fabricio Lemos no Cafe Com Tapioca do CEJUG com o tema "Testes de Unidade com Junit"

TRANSCRIPT

Page 1: Testes de Unidade com Junit
Page 2: Testes de Unidade com Junit

Palestra Café com Tapioca: Palestra Café com Tapioca: Testes de Unidade com JunitTestes de Unidade com Junit

Instrutor: Fabrício Lemos 15/12/2007

Page 3: Testes de Unidade com Junit

Agenda

● Conceito de Testes de Unidade● Junit● EasyMock● DbUnit● Desenvolvimento Guiado por Testes - TDD

Page 4: Testes de Unidade com Junit

Testes de Software

● É um tópico importante e vital no desenvolvimento de software

● Todo mundo sabe que testes precisam ser feitos● Existe uma quantidade enorme de aspectos que

precisam ser testados em um sistema

Page 5: Testes de Unidade com Junit

Testes de Software

● O sistema deve passar por diversos tipos de teste antes de entrar em produção– Unidade– Integração– Funcional– Stress e performance– Aceitação

Page 6: Testes de Unidade com Junit

Testes de Software● É praticamente impossível evitar que erros sejam

inseridos no código– Atividade complexa– Manipula uma grande quantidade de elementos

abstratos– Inclusões de novas funcionalidades podem influenciar

nas já existentes– Muitas vezes é difícil ter certeza que o código está

totalmente correto até que ele seja executado– Geralmente os desenvolvedores do projeto possuem

diferentes níveis de habilidades

Page 7: Testes de Unidade com Junit

Testes de Software

● Mesmo tendo reconhecida importância no desenvolvimento de software, os teste costumam ser vistos como uma atividade chata e repetitiva– Só costumam receber atenção quando os problemas

começam a ser tornar comuns● Geralmente só são iniciados quando o produto está todo

“pronto”

Page 8: Testes de Unidade com Junit

Testes de Software

● Muitos projetos assumem que o código desenvolvido está livre de erros e postergam os testes para as fases finais do desenvolvimento– Preferem remediar do que prevenir– “Está tudo pronto, só falta testar”

Page 9: Testes de Unidade com Junit

Testando o Código da Aplicação

● Como ter certeza de que o código escrito faz o que deveria fazer e não contém erros?

● Abordagens comumente usadas– Escreve-se um método main que chama o método

escrito e verifica-se o retorno– Espera-se que a funcionalidade esteja pronta e realiza-

se um teste funcional manual● Os testes são feitos de maneira pontual

– Não é possível a realização de testes de regressão

Page 10: Testes de Unidade com Junit

Testando o Código da Aplicação

● Testes não são automatizados– Não é possível utiliza-los na integração contínua

● Não são gerados relatórios sobre a execução dos testes

● Testes não são executados de maneira isolada– Maior dificuldade em encontrar a fonte de um erro

● Não há disciplina para a realização dos testes

Page 11: Testes de Unidade com Junit

Testes de Unidade

● Examinam o comportamento de uma “unidade de trabalho” distinta– Em java, geralmente representada por um único

método● Unidades de trabalho são testadas de maneira

isolada● Possuem natureza diferente dos testes de

integração e de aceitação– examinam como vários componentes interagem

Page 12: Testes de Unidade com Junit

Objetivos

● Verificar se um pedaço de código faz o que o desenvolvedor acha que ele faz

● Verificar se um pedaço de código SEMPRE faz o que o desenvolvedor acha que ele faz

● Identificar bugs prematuramente● Permitir que novas funcionalidades sejam

adicionadas sem comprometer as já existentes● Diminuir o impacto das refatorações de código

Page 13: Testes de Unidade com Junit

Vantagens dos Testes de Unidade

● Permite uma grande cobertura dos testes● Pode facilmente simular condições de erro● Melhora o trabalho em equipe

● Permite ao desenvolvedor entregar código de qualidade (testado) sem esperar que outras partes estejam prontas

● Dá-lhe a confiança que seu código funciona● “Alguém” assistindo a alteração/inclusão de novas

funcionalidades

Page 14: Testes de Unidade com Junit

Vantagens

● Diminui o tempo gasto com depuração de código● Quando há algum erro, te diz o método que falhou e o

motivo da falha● Melhora a implementação

● Testes de unidade são os primeiros “clientes” do código

● Serve como uma documentação do código● Aprendizagem por exemplos

Page 15: Testes de Unidade com Junit

Vantagens

● São facilmente incorporados na Integração Contínua

● Relatórios sobre a corretude do código e a cobertura dos testes são gerados de maneira automática

Page 16: Testes de Unidade com Junit

Junit

● Framework de teste criado por Erich Gamma e Kent Beck

● Possui uma api bastante fácil e simples● Rapidamente se tornou o framework padrão para

testes em Java● Possui suporte para diversas ferramentas: Eclipse,

Maven, Ant, etc....

Page 17: Testes de Unidade com Junit

Junit

● Foram desenvolvidas diversas extensões para facilitar os testes de partes específicas de um projeto– EasyMock– DbUnit– StrutsTestCase– Cactus– Shale Test Framework– etc...

Page 18: Testes de Unidade com Junit

Escrevendo os Testes

public class Calculadora {public int somar(int op1, int op2) {return op1 + op2;

}}

Page 19: Testes de Unidade com Junit

Escrevendo os Testesimport static org.junit.Assert.*;import org.junit.Test;public class TestCalculadora {

@Testpublic void testSomar() {

Calculadora calc = new Calculadora();int resultado = calc.somar(2, 3);assertEquals(5, resultado);

}}

Page 20: Testes de Unidade com Junit
Page 21: Testes de Unidade com Junit

Se o método passar no teste...

Page 22: Testes de Unidade com Junit

Se o método não passar no teste...

Page 23: Testes de Unidade com Junit

Outros Assertsvoid assertEquals(Object expected, Object actual)void assertTrue(boolean condition)void assertFalse(boolean condition)void fail()void assertArrayEquals(Object[] expecteds, Object[] actuals)void assertNull(Object object)void assertNotNull(Object object)void assertEquals(String message, Object expected, Object

actual)

Page 24: Testes de Unidade com Junit

Boas Práticas

● Cada classe do sistema deve ter sua própria classe testadora

● Cada método do sistema deve ter seu próprio método testador

● O nome das classes testadoras devem seguir o padrão TestNomeClasseTestada– Não prejudica o code completion– Classes reconhecidas automaticamente pelo Maven

Page 25: Testes de Unidade com Junit

Boas Práticas

● Pacote da classe testadora deve ser o mesmo da classe testada– Permite o teste de métodos protected

● Classes testadoras devem ser armazenadas em pastas separadas– Facilita o empacotamento da aplicação– src/test/java

● Padrão do Maven

Page 26: Testes de Unidade com Junit

Classe Usuario

public class Usuario {private String nome;private Integer idade;//get e set...

}

Page 27: Testes de Unidade com Junit

Validação de um Usuário

public boolean validarUsuario(Usuario usr) {if (usr.getIdade() > 0 &&

usr.getNome().length() > 2) {return true;

}return false;

}

Page 28: Testes de Unidade com Junit

Testando a Validação

@Testpublic void testValidarUsuario() {

Usuario usuario = new Usuario();usuario.setIdade(18);usuario.setNome("Cejug");boolean resultado = new

UsuarioManager().validarUsuario(usuario);assertTrue(resultado);

}

Page 29: Testes de Unidade com Junit

Testando a Validação@Testpublic void testValidarInvalido() {

Usuario usuario = new Usuario();usuario.setIdade(18);usuario.setNome("");boolean resultado = new

UsuarioManager().validarUsuario(usuario);assertFalse(resultado);

}

Page 30: Testes de Unidade com Junit

Isolando os Métodos Testados

● A maioria dos métodos de um sistema possui dependências externas à classe

● Umas das principais características dos testes de unidade é o isolamento das unidades testadas– Permite facilmente identificar o local do erro

● Diminui o tempo de debug– As dependências não precisam estar prontas para que

o método seja testado● Para isolar os métodos testados, as dependências

devem ser substituídas por dependências “falsas”

Page 31: Testes de Unidade com Junit

Método com Dependência

public void inserirUsuario(Usuario usuario) {usuario.setDataCadastro(new Date());if(validarUsuario(usuario)){

usuarioDAO.inserirUsuario(usuario);} else {

throw new IllegalArgumentException();}

}

Page 32: Testes de Unidade com Junit

Objetos Mock

● Na realização dos testes (em tempo de execução), as dependências são substituídas por objetos Mock– Injeção de dependência

● Simulam as dependências dos métodos testados● São objetos “vazios”

– Não contém nenhuma lógica● Podem ser feitos pelo próprio desenvolvedor ou a

partir de alguma biblioteca

Page 33: Testes de Unidade com Junit

EasyMock

● Biblioteca para geração dinâmica de Mocks● Gera objetos mock que implementam qualquer

interface da aplicação– Possui uma extensão para geração de mocks para

classes

Page 34: Testes de Unidade com Junit

EasyMock

● Permite verificar se o método testado colaborou corretamente com a dependência– Permite a configuração dos objetos mock

● Quais os argumentos que o mock deve receber do método testado

● Qual deve ser o retorno do método chamado● Se a chamada deve lançar alguma exceção

● Facilidade para simular condições de erro

Page 35: Testes de Unidade com Junit

Utilizando Mocks

1.Criar o mock da interface a ser simulada2.Configurar o comportamento do mock3.Fazer com que a unidade testada utilize o objeto

mock ao invés da dependência original1.Injetar o Mock

4.Chamar a unidade a ser testada5.Verificar o valor retornado6.Verificar se a unidade testada colaborou

corretamente com o mock

Page 36: Testes de Unidade com Junit

Utilizando Mocks

// 1. criando o mockUsuarioDAO mock = EasyMock.createMock(UsuarioDAO.class);

Page 37: Testes de Unidade com Junit

Utilizando Mocks

// 2. configurando o comportamento do // mockUsuario usuario = new Usuario();usuario.setIdade(25);usuario.setNome("Café com Tapioca");mock.inserirUsuario(usuario);EasyMock.replay(mock);

Page 38: Testes de Unidade com Junit

Utilizando Mocks

// 3. Injetando o MockUsuarioManager manager =new UsuarioManager();

manager.setUsuarioDAO(mock);// 4. chamando o método a ser// testadomanager.inserirUsuario(usuario);

Page 39: Testes de Unidade com Junit

Utilizando Mocks

// 5. Verificando o comportamento do// métodoassertNotNull(usuario.getDataCadastro());// 6. Verificando se o método// usuarioDao.inserir() foi chamado com o // usuário passadoEasyMock.verify(mock);

Page 40: Testes de Unidade com Junit

Mocks – Boas Práticas

● Sempre utilize injeção de dependências em suas classes

● Acesse as dependências através de suas Interfaces e não através da implementação

● Tenha bem definido qual o comportamento de seus métodos nas interações com as dependências

Page 41: Testes de Unidade com Junit

Testando a Camada de Persistência

● Como ter certeza de que seu código de acesso a dados está lendo e escrevendo corretamente na base de dados?

● É necessária uma integração com o banco de dados na realização dos testes– Misto entre teste de unidade e teste de integração

● Quando feita de forma não automática, a verificação depende da inspeção visual do conteúdo da base de dados

Page 42: Testes de Unidade com Junit

Testando a Camada de Persistência

● Para automatizar os testes duas condições tem que ser satisfeitas– O conteúdo da base de dados tem ser conhecido no

início de cada teste– Deve ser possível verificar o conteúdo da base de

dados após cada teste● Os testes ainda devem ser realizados

independentemente– Testar a inserção independentemente da seleção

Page 43: Testes de Unidade com Junit

DbUnit

● Extensão do Junit especializada em testes integrados ao banco de dados

● Permite o controle do conteúdo armazenado na base de dados– Exporta dados para a base através de arquivos XML

● Possui métodos de verificação do estado da base de dados– Importa dados da base e compara com arquivos XML

Page 44: Testes de Unidade com Junit

Testando com o DbUnit

● O conteúdo da base de dados é configurado através de DataSet no formato XML

● Por default, antes de cada teste a base de dados é esvaziada e re-populada com o conteúdo do DataSet

<dataset><Usuario codigo="-1" nome="josefino" idade="20" /><Usuario codigo="-2" nome="maria" idade="40" /><Usuario codigo="-3" nome="jose" idade="40" />

</dataset>

Page 45: Testes de Unidade com Junit

Testando com o DbUnit

● Classe de teste deve herdar de DatabaseTestCase● Implementar os métodos

– IDatabaseConnection getConnection()● Retorna uma conexão com a base de dados

– IDataSet getDataSet()● Retorna o DataSet para o povoamento da base de dados

Page 46: Testes de Unidade com Junit

Testando com o DbUnitprotected IDatabaseConnection getConnection()

throws ClassNotFoundException, SQLException {

Class.forName("org.hsqldb.jdbcDriver");Connection jdbcConnection =

DriverManager.getConnection("jdbc:hsqldb:sample", "sa", "");

return new DatabaseConnection(jdbcConnection);

}

Page 47: Testes de Unidade com Junit

Testando com o DbUnit

protected IDataSet getDataSet() throws DataSetException, IOException {FileInputStream fileIS = new

FileInputStream("dataset.xml");return new FlatXmlDataSet(fileIS);

}

Page 48: Testes de Unidade com Junit

Testando a Seleção de Usuários

public interface UsuarioDAO {List<Usuario> selecionarUsuarios(String nome);

}

Page 49: Testes de Unidade com Junit

Realizando o Teste

● Montar o(s) parâmetro(s) para a busca● Criar o retorno esperado de acordo com o

DataSet de povoamento da base de dados● Realizar a busca● Verificar se o resultado da busca é igual ao

resultado esperado

Page 50: Testes de Unidade com Junit

@Testpublic void testSelecionarUsuarios() {

String parametroBusca = "jose";List<Usuario> esperado = new

ArrayList<Usuario>();esperado.add(new Usuario(-3L));esperado.add(new Usuario(-1L));List<Usuario> retorno usuarioDAO.

selecionarUsuarios(parametroBusca);assertEquals(esperado, retorno);

}

Page 51: Testes de Unidade com Junit

Desenvolvimento Guiado por Testes (TDD)

● A escrita de testes ajuda na melhoria do design do código

● Ao se perceber os benefícios dos testes, a tendência é escreve-los o quanto antes

● Com o alcance da maturidade, durante a implementação de um método o desenvolvedor já imagina como irá testa-lo

Page 52: Testes de Unidade com Junit

TDD

● Quanto mais cedo os testes são implementados, maiores são os benefícios– Evita que bugs se espalhem pela aplicação e os

tornam mais fáceis de ser corrigidos● Os adeptos do TDD levam essa prática ao

estremo– Os testes são escritos antes do código a ser testado

Page 53: Testes de Unidade com Junit

TDD

● A regra básica do TDD é somente escrever código se existir algum teste falhando– Regra válida para implementação de novas

funcionalidades ou para correção de bugs● Somente o código estritamente necessário para

fazer o teste passar deve ser escrito– Refatorações são permitidas

Page 54: Testes de Unidade com Junit

Codificando com TDD

● Escreva o teste para a funcionalidade desejada– O teste irá falhar

● Escreva o código necessário e suficiente para o teste passar

● Refatore o código– Elimine possíveis duplicações de código

● Repita os passos quantas vezes necessário● Entregue o código

Page 55: Testes de Unidade com Junit

Vantagens do TDD

● Antes mesmo de começar a implementar o método, o desenvolvedor já tem definido qual será seu comportamento

● O código já nasce sem vícios de design● Evita que bugs sejam adicionados ao código

Page 56: Testes de Unidade com Junit

Vantagens do TDD

● Mantém o desenvolvedor focado no problema a ser resolvido– Código é o mais simples que funciona

● Não procura antecipar mudanças– Manutenção é garantida pela não duplicidade e pela

simplicidade do código

Page 58: Testes de Unidade com Junit

Referências● http://www.junit.org/● http://www.easymock.org/● http://dbunit.sourceforge.net/● JUnit in Action

– Vincent Massol● JUnit Recipes: Practical Methods for Programmer

Testing– J. B. Rainsberger

● Extreme Programming– Vinicius Manhaes Teles