O documento discute testes unitários, apresentando: 1) O que são testes unitários e seus benefícios; 2) Como escrever testes unitários usando JUnit e frameworks de mock como Mockito e PowerMock.
2. Testes Unitários
• O que são Testes Unitários?
• É um nível de teste de software no qual
componentes individuais são testados
(métodos)
• O propósito é validar se cada unidade do
software executa como esperado
11/06/2016 Testes Unitários 2
4. Testes Unitários
• Os testes unitários tem como benefício:
• Garantir que problemas serão descobertos
cedo.
• Facilitar a manutenção de código
• Servir como documentação
• Ajudam a melhorar o design do seu código
e torna-lo um melhor desenvolvedor
11/06/2016 Testes Unitários 4
13. Testes Unitários
11/06/2016 Testes Unitários
• Qualquer alteração na classe Conta, você terá mais
confiança de que o comportamento do método temSaldo
será mantido!!!
13
Os três testes
passaram
14. Testes Unitários
• Algumas observações:
• Para ter certeza de que o seu código não tem erro,
deve-se testar todas as possíveis entradas do método
• Para a variável saldo:
• 4.94065645841246544e-324d a 1.79769313486231570e+308d
• Geralmente, se testa alguns valores chaves que
representam todas as possíveis entradas:
• -1000, -1, 0, null, +1, +1000
• Tenha criatividade para imaginar as possiblidades de
testes!!!
11/06/2016 Testes Unitários 14
15. Testes Unitários
• Não teste métodos triviais, tipo get e set padrões, só se
esses métodos tiverem validações.
• Achou um bug? Não conserte sem antes escrever um
teste que o pegue
• Preocupe-se com a qualidade do código dos seus
testes, mantenha igual ao código das classes que estão
sendo testadas, pois você vai precisar mantê-los do
mesmo jeito.
11/06/2016 Testes Unitários 15
16. Testes Unitários
• Para esse simples exemplo:
• Classe Conta: 13 linhas de código
• Classe Conta Teste: 31 linhas de código
• O número de linhas de código para se testar um
sistema geralmente é maior que o número de linhas de
código do sistema
11/06/2016 Testes Unitários 16
17. JUnit
• Framework que facilita o desenvolvimento e
execução de testes unitários em código JAVA.
• Facilita a criação, execução automática de testes e a
apresentação dos resultados
11/06/2016 Testes Unitários
Junit
17
19. JUnit
• Criando um teste unitário com JUnit
11/06/2016 Testes Unitários 19
20. JUnit
• Criando um teste
unitário com Junit
• Defina o nome da classe
• E a classe que vai ser
testada
11/06/2016 Testes Unitários 20
21. JUnit
• Criando um teste unitário com JUnit
• Escolha os métodos a serem testados
11/06/2016 Testes Unitários 21
22. JUnit
• Criando um teste com JUnit
11/06/2016 Testes Unitários
A partir da Versão 4 do JUnit todo método com um @Test
é um teste unitário a ser executo
Substitui o método main()
22
23. JUnit
• Criando um teste com JUnit
11/06/2016 Testes Unitários
Junit possui vários métodos “assertions”
Substitui os testes feitos anteriormente “if ... else .. println()”
23
24. Main Assert Statements
11/06/2016 Testes Unitários
fail(String) Faz o método falhar
assertTrue(boolean, condition) Testa se a condição é verdadeira
assertFalse(boolean, condition) Testa se a condição é falsa
assetEquals(expected, actual) Teste se dois valores são iguais
assertEquals(expected, actual,
tolerance)
Para float ou double, a tolerância é o número
de casas decimais a ser verificado
assertNull(object) Verifica se o objeto é nulo
assertNotNull(object) Verifica se o objeto não é nulo
24
25. JUnit
• Criando um teste com Junit
• Existem vários métodos assertX, para validar os
resultados dos testes
11/06/2016 Testes Unitários 25
26. JUnit
• Criando um teste com Junit
• Executando os Teste pelo Eclipse
11/06/2016 Testes Unitários 26
28. JUnit
• Criando um teste com Junit
• TestSuite: Roda vários casos de testes ao mesmo
tempo
11/06/2016 Testes Unitários 28
29. JUnit
• Criando um teste com Junit
• TestSuite: Roda vários casos de testes ao mesmo
tempo
11/06/2016 Testes Unitários 29
30. JUnit
• Criando um teste com Junit
• TestSuite: Roda vários casos de testes ao mesmo
tempo
11/06/2016 Testes Unitários
Para adicionar novos testes ao TestSuite, basta apenas
adicionar novas classes à anotação @SuiteClasses
30
31. JUnit Annotations
11/06/2016 Testes Unitários
@Test Identifica um método de testes
@Test(expected= Exception.class) Falha se o método testado não retornar essa
exceção
@Test(timeout=100) Falha se o método demorar mais de
100milisegundos
@Before
public void method()
Executa antes de cada teste. Usado para
preparar o ambiente de teste
@After
public void method()
Executa depois de cada teste. Usado para
liberar recursos do teste
@BeforeClass
public static void method()
Executa 1 vez, antes de todos os testes.
Usado para preparar o ambiente de teste
O método anotado deve ser estátivo
@AfterClass
public static void method()
Executa 1 vez, depois de todos os testes.
Usado para liberar recursos do teste
O método anotado deve ser estático
@Ignore Ignora algum método de teste
31
36. Mock Objects
11/06/2016 Testes Unitários
• Testes unitários devem testar uma classe
isoladamente, isto é, sem que o efeito de outras
classes com que ela se relaciona, interfiram no teste.
• Isso é particularmente muito difícil porque a maioria
das classes em um sistema real possuem
relacionamento com outras classes
• Para resolver esse problema, normalmente se usa a
metodologia de se criar Mocks.
36
37. Mock Objects
11/06/2016 Testes Unitários
• Objetos Mocks são implementações simuladas de um
interface ou classe que define a saída das chamas dos
métodos que se relacionam com a classe.
• Isso ajuda a assegurar que você só teste a classe e
que seu teste não será afetado por efeitos colaterais
37
38. Mock Objects
11/06/2016 Testes Unitários
• No mundo real a classe Conta deveria atualizar o saldo
de forma persistente, não apenas em memória.
38
40. Mock Objects
11/06/2016 Testes Unitários
• Tentativa de Criar um Teste para nova classe Conta
passando um objeto DAO para atualizar o saldo:
40
41. Mock Objects
11/06/2016 Testes Unitários
• Como resolver esse problema?
• Isso é, como alterar o comportamento do objeto DAO
para o teste passar, sem alterar o objeto DAO real
porque ele precisa se comunicar com o banco quando
for executado em produção?
• R: Por meio da herança.
41
43. Mock Objects
11/06/2016 Testes Unitários
• No Teste Unitário que usa o objeto Mock criado:
• Objetivo não é testar se o dado é salvo, o objetivo
do teste é testar se a lógica do saque está correta
43
44. Mock Objects
11/06/2016 Testes Unitários
• O problema com Mock Objects é que eles são
trabalhosos de serem criados.
• Para isso surgiram vários Framework de geração de
Mock, esse é nosso próximo passo ....
44
45. Mockito
• É um Framework popular para construção
de Mocks que pode ser usado em conjunto
com o JUnit.
11/06/2016 Testes Unitários
Mockito
Junit
45
46. Mockito
• Em vez de você precisar criar os Mocks, você
apenas indica, que o Mockito criar o mock para
você.
11/06/2016 Testes Unitários 46
47. Mockito
• Por padrão um mock é uma subclasse com todos
os métodos vazios
• É possível definir valores a serem retornados ao
se chamar algum método do mock.
• Com os métodos
Mockito.when(...).thenReturn(...)
11/06/2016 Testes Unitários 47
48. Mockito
• Definindo o comportamento do método
buscaPorSaldoMaiorQue() do mock.
11/06/2016 Testes Unitários 48
49. Mockito
• É possível criar um Mock Parcial do objeto com
o método Spy().
• Mock Parcial é um mock cujo todos os métodos
possuem o comportamento real do objeto.
11/06/2016 Testes Unitários 49
50. Mockito
• E para que eu quero um Mock onde todos os
métodos possuem o comportamento real do
objeto um mock já não é para não realizar o
comportamento real?
• Porque as vezes, por exemplo, você precisa usar a classe testada
em algum método do Mockito, mas os métodos do mockito só
aceitando mocks, e você não deseja criar um mock da classe
testada, se não, você não vai ter código para ser executado na
classe testada. Nestes casos usa-se o mock parcial. Entendeu ?
Não! Espere mais 2 slides até eu explicar o que é o verify.
11/06/2016 Testes Unitários 50
51. Mockito
• Testar se um código foi executado.
11/06/2016 Testes Unitários 51
Útil para testar métodos voids. Você não tem o que testar porque o
método não retorna anda, mas pelo menos pode verificar se
determinado trecho de código foi executado. Se o teste chegou até
aquele trecho você sabe que ele executou sem problemas até ali.
52. Mockito
• Uso do mock parcial (continuando ...)
• Você quer usar o verify para verificar se algum método da sua classe
que está sendo testada foi chamado.
• Não é possível fazer
Mockito.verify(minhaClasse).doStuff(1);
• Porque minhaClasse não é um mock, é a classe que você está
testado. Não é desejado criar um mock dela. E o método verify só
aceita mocks como argumento. Para resolver essa situação é possível
fazer:
minhaClasse = Mockito.spy(minhaClasse); // cria um
mock mas mantém o comportamento dos métodos
Mockito.verify(minhaClasse).doStuff(1); // verificar
se o método doStuff da minha classe que está sendo
testada foi chamado recebendo o valor 1
Ps.: Todos os Métodos da minhaClasse serão executados normalmente
11/06/2016 Testes Unitários 52
53. Mockito
• Trabalhar com objetos que é difícil estipular um
valor específico no momento da execução.
Mockito.when(myClass.method(
Mockito.any(Date.class))).thenReturn(x);
• Para qualquer instancia da classe Date passada o método
myClass#method retorna o objeito X;
11/06/2016 Testes Unitários 53
54. Mockito
• Limitações do Mockito:
• Ele não consegue fazer mocks de:
• Classes Final
• Variáveis, Métodos e Objetos Estáticos
• Tipos primitivos
• Classes anônimas
• Métodos privados
• Por que?
• Porque o Mockito usa herança para criar mocks, ele herda da
classe real e cria uma subclasse com os método vazios os com
comportamento definidos por você para o teste.
11/06/2016 Testes Unitários 54
55. Mockito
• É comum vários sistemas possuírem dados
estáticos acessando banco de dados ou outros
recursos externos cujo mockito não consegue
isolar
11/06/2016 Testes Unitários 55
56. PowerMock
• Um Framework do Mock que estende o
Mockito para provê mocks mais poderosos.
• Principalmente de mockar objetos estáticos
11/06/2016 Testes Unitários
Mockito
Junit
PowerMock
56
57. PowerMock
• Um Framework do Mock que estende o Mockito
para provê mock mais poderosos.
• Ele consegue fazer isso porque ele vai no
bytecode da classe e altera o código para a
execução do teste.
11/06/2016 Testes Unitários 57
61. PowerMock
11/06/2016 Testes Unitários
Use the PowerMock Junit runner
Declara a classe que nós iremos testar
e que possui o método estático.
Será carregada em outro classloader
Diz ao Powermock para realizar
mock dos métodos estáticos
da classe
61
63. PowerMock
• “PowerMock é uma ferramenta poderosa, mas
devemos sempre nós lembrar: Se nós
encontramos uma situação onde só o
PowerMock pode resolver nosso problema.
Então nós falhamos. Isso significa que a classe
que está sendo testada está errada.”
Charles Roth
www.thedance.net/~roth/TECHBLOG/powerMock.
html
11/06/2016 Testes Unitários 63
64. PowerMock
• Se você encontrar uma situação que precisa
mockar um método estático, então
provavelmente esse método não deveria ser
estático.
• Algumas vezes esse método pertence a uma
classe de terceiros que não pode ser alterada,
para essas situações que o PowerMock foi
criado.
11/06/2016 Testes Unitários 64
65. PowerMock
11/06/2016 Testes Unitários
• Outras funcionalidades:
• Chamar uma método real de um mock
• PowerMockito.doCallRealMethod()
.when(UFRNUtils.class, “checkRole”,
usuarioLogado,
PapeisProtocolo.RECEBER_PROTOCOLO);
• Pular a execução de algum método que não deve ser chamado
• PowerMockito.suppress(PowerMockito.method
(ProcessadorAnaliseComissaoProgressao.class,
“criar”));
65
67. Teste na Integração Contínua
• “Integração Contínua é uma prática de
desenvolvimento de software onde os membros
de um time integram seu trabalho
frequentemente. Cada integração é verificada por
um build automatizado (incluindo testes) para
detectar erros de integração o mais rápido
possível.” [Martin Fowler]
11/06/2016 Testes Unitários 67
68. Teste na Integração Contínua
• Testes automatizados é uma parte
fundamental da integração contínua
• Ou você usa testes automatizados ou você
não estará realizando integração contínua
11/06/2016 Testes Unitários 68
69. Teste na Integração Contínua
• Chamando Test Suites a partir do Gradle.
11/06/2016 Testes Unitários 69
70. Teste na Integração Contínua
11/06/2016 Testes Unitários 70
• Rodando os testes do sistema periodicamente
• Para isso crie um job que rode constantemente (idealmente a cada
commit) e execute os testes unitários
71. Teste na Integração Contínua
11/06/2016 Testes Unitários 71
• Rodando os testes do sistema periodicamente
• Esse job invoca a task unitTest do Gradle que por sua vez executa
os Test Suites do sistema
72. Teste na Integração Contínua
11/06/2016 Testes Unitários 72
• Rodando os testes do sistema periodicamente
• O Gradle armazena os resultado dos testes por padrão do diretório
build/test-results do projeto, é possível mandar o jenkins publicar
esses resultados
73. Teste na Integração Contínua
11/06/2016 Testes Unitários 73
• Rodando os testes do sistema periodicamente
• Assim é possível ver na interface do jenkins a tendência dos testes
do sistema
• Caso algum teste falhe, a build quebra e imediatamente toda a
equipe é avisada