Testes de Unidade com Junit

5,008 views
4,808 views

Published on

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

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,008
On SlideShare
0
From Embeds
0
Number of Embeds
19
Actions
Shares
0
Downloads
134
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Testes de Unidade com Junit

  1. 1. Palestra Café com Tapioca: Testes de Unidade com Junit Instrutor: Fabrício Lemos 15/12/2007
  2. 2. Agenda ● Conceito de Testes de Unidade ● Junit ● EasyMock ● DbUnit ● Desenvolvimento Guiado por Testes - TDD
  3. 3. 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
  4. 4. 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
  5. 5. 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
  6. 6. 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”
  7. 7. 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”
  8. 8. 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
  9. 9. 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
  10. 10. 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
  11. 11. 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
  12. 12. 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
  13. 13. 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
  14. 14. 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
  15. 15. 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....
  16. 16. 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...
  17. 17. Escrevendo os Testes public class Calculadora { public int somar(int op1, int op2) { return op1 + op2; } }
  18. 18. Escrevendo os Testes import static org.junit.Assert.*; import org.junit.Test; public class TestCalculadora { @Test public void testSomar() { Calculadora calc = new Calculadora(); int resultado = calc.somar(2, 3); assertEquals(5, resultado); } }
  19. 19. Se o método passar no teste...
  20. 20. Se o método não passar no teste...
  21. 21. Outros Asserts void 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)
  22. 22. 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
  23. 23. 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
  24. 24. Classe Usuario public class Usuario { private String nome; private Integer idade; //get e set... }
  25. 25. Validação de um Usuário public boolean validarUsuario(Usuario usr) { if (usr.getIdade() > 0 && usr.getNome().length() > 2) { return true; } return false; }
  26. 26. Testando a Validação @Test public void testValidarUsuario() { Usuario usuario = new Usuario(); usuario.setIdade(18); usuario.setNome("Cejug"); boolean resultado = new UsuarioManager().validarUsuario(usuario); assertTrue(resultado); }
  27. 27. Testando a Validação @Test public void testValidarInvalido() { Usuario usuario = new Usuario(); usuario.setIdade(18); usuario.setNome(""); boolean resultado = new UsuarioManager().validarUsuario(usuario); assertFalse(resultado); }
  28. 28. 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”
  29. 29. Método com Dependência public void inserirUsuario(Usuario usuario) { usuario.setDataCadastro(new Date()); if(validarUsuario(usuario)){ usuarioDAO.inserirUsuario(usuario); } else { throw new IllegalArgumentException(); } }
  30. 30. 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
  31. 31. 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
  32. 32. 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
  33. 33. Utilizando Mocks 1.Criar o mock da interface a ser simulada 2.Configurar o comportamento do mock 3.Fazer com que a unidade testada utilize o objeto mock ao invés da dependência original 1.Injetar o Mock 4.Chamar a unidade a ser testada 5.Verificar o valor retornado 6.Verificar se a unidade testada colaborou corretamente com o mock
  34. 34. Utilizando Mocks // 1. criando o mock UsuarioDAO mock = EasyMock.createMock(UsuarioDAO.class);
  35. 35. Utilizando Mocks // 2. configurando o comportamento do // mock Usuario usuario = new Usuario(); usuario.setIdade(25); usuario.setNome("Café com Tapioca"); mock.inserirUsuario(usuario); EasyMock.replay(mock);
  36. 36. Utilizando Mocks // 3. Injetando o Mock UsuarioManager manager = new UsuarioManager(); manager.setUsuarioDAO(mock); // 4. chamando o método a ser // testado manager.inserirUsuario(usuario);
  37. 37. Utilizando Mocks // 5. Verificando o comportamento do // método assertNotNull(usuario.getDataCadastro()); // 6. Verificando se o método // usuarioDao.inserir() foi chamado com o // usuário passado EasyMock.verify(mock);
  38. 38. 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
  39. 39. 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
  40. 40. 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
  41. 41. 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
  42. 42. 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>
  43. 43. 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
  44. 44. Testando com o DbUnit protected IDatabaseConnection getConnection() throws ClassNotFoundException, SQLException { Class.forName("org.hsqldb.jdbcDriver"); Connection jdbcConnection = DriverManager.getConnection( "jdbc:hsqldb:sample", "sa", ""); return new DatabaseConnection(jdbcConnection); }
  45. 45. Testando com o DbUnit protected IDataSet getDataSet() throws DataSetException, IOException { FileInputStream fileIS = new FileInputStream("dataset.xml"); return new FlatXmlDataSet(fileIS); }
  46. 46. Testando a Seleção de Usuários public interface UsuarioDAO { List<Usuario> selecionarUsuarios( String nome); }
  47. 47. 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
  48. 48. @Test public 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); }
  49. 49. 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
  50. 50. 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
  51. 51. 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
  52. 52. 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
  53. 53. 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
  54. 54. 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
  55. 55. Duvidas??? ● Contato –fabricio.lemos@gmail.com – discussao@cejug.dev.java.net
  56. 56. 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

×