1. Testando o difícil e o quase “impossível”
EDER NOGUEIRA
GEORGE FREIRE
IMD0028 - FERRAMENTAS PARA AUTOMAÇÃO DE TESTES
RESIDÊNCIA EM ENGENHARIA DE SOFTWARE
INSTITUTO METRÓPOLE DIGITAL/ UFRN
2. Agenda
Unit Testing: Fáceis x Difíceis
O que são os Mocks?
Cenário das Ferramentas Mock;
Porque o PowerMock;
Quando Usar x Quando Não Usar;
Metendo a mão na massa;
Conclusões;
Referências Bibliográficas;
3. Unit Testing: Fáceis x Difíceis
Testes unitários são fáceis quando:
◦ Seu código não depende de nada: Sem arquivos
de sistema, conexões com bancos de dados,
web services, sockets;
◦ Não possua dependências com outros
componentes, frameworks, etc;
◦ São automatizados para executá-los quantas
vezes for necessário;
◦ Precisam ser testados com a segurança
necessária;
◦ Resumindo:
CÓDIGO FÁCIL DE SER TESTADO É CÓDIGO
ISOLADO,SEGURO E AUTOMATIZADO.
4. Unit Testing: Fáceis x Difíceis
Easy Tests:
Hard Tests:
Class Under
Test
Test Class
Class Under
Test
Test Class
5. Unit Testing: Fáceis x Difíceis
Para testes difíceis, removemos as
dependências usando os objetos mock;
Class Under
Test
Test Class
m
o
c
k
m
o
c
k
m
o
c
km
o
c
k
6. O que são Mocks?
Segundo os especialistas:
◦ Martin Fowler: O termo “mock object” surgiu
dentro da comunidade XP e:
“...tornou-se popular para descrever um caso especial de
objetos que imitam objetos reais para teste”.
◦ Gerard Meszaro: Os mocks são:
“...objetos pré-programados com informações que formam
uma especificação das chamadas que esperam receber”.
Fazem parte de uma classe de objetos falsos usados para
propósito de testes, na qual ainda fazem parte os objetos
dummy, fake e stubs;
7. O que são Mocks?
Sendo mais claro, os objetos mock:
◦ Simulam objetos reais;
◦ Modularizam melhor os testes;
◦ Gravam e examinam as expectativas das
chamadas, verificando se foram atendidas;
◦ Usam as mesmas interfaces do objeto real;
◦ Realizam verificações de estado e de
comportamento;
8. O que são Mocks?
Situações reais: Se um objeto tem alguma das
características a seguir, é provável que um objeto
mock possa ser utilizado em seu lugar:
◦ Gera resultados não determinísticos (e.g. a hora ou
temperatura atual);
◦ Tem estados que são difíceis de criar ou reproduzir (e.g.
erro de comunicação da rede);
◦ É lento (e.g. um banco de dados completo que precisa ser
inicializado antes do teste);
◦ Ainda não existe ou pode ter comportamento alterado;
◦ Teriam que adicionar informações e métodos
exclusivamente para os testes (e não para sua função
real).
◦ Mapeamento Objeto-Relacional (ORM): Quando
trabalhamos com ORM, os mock-object nos auxiliam a
testar as operações de forma desconectada e validar se
as operações estão sendo chamadas a contento;
9. O que são Mocks?
Exemplo: Testar um sistema que envia
SMS
◦ Solução Tradicional:
◦ Criar um teste unitário que teste o envio utilizando o
próprio provedor de SMS;
◦ Problema da Solução: Para cada SMS enviado, terá que
ser pago as tarifas do SMS;
◦ Conclusão: QUANTO MAIOR O Nº DE TESTES, MAIOR O
CUSTO;
10. O que são Mocks?
Exemplo: Testar um sistema que envia
SMS
◦ Solução com objetos Mock:
Os objetos Mock simularão o comportamento dos
objetos “reais” da aplicação, de forma controlada
pelo desenvolvedor;
Este objeto será idêntico, ou seja, conterá os
mesmos métodos e parâmetros do original, que
não fará efetivamente o envio;
Logo, os testes poderão ser realizados sem custo e
ainda poderá ser simulado outras situações, como
a queda do serviço por parte da operadora;
13. Porque o PowerMock?
Open-Source;
Performance:
◦ Carregador de classes e de bytecode personalizado;
◦ Injeção de Dependência é muito custoso com chamadas a métodos
estáticos. PowerMock permite a simulação destes métodos;
Design:
◦ Possibilidade de simular métodos estáticos, privados, inicializadores
estáticos, final classes, que outras bibliotecas não possuem;
◦ Inclui muitas ferramentas que simplificam o uso de reflection,
especialmente úteis para testes e facilitam o acesso ao estado interno
do objeto testado.
3rd Party:
◦ O PowerMock oferece suporte a bibliotecas de mock existentes,
como EasyMock e Mockito, além das ferramentas de teste
TestNG e JUnit, possuindo a vantagem de se utilizar de um menor
número de métodos e anotações e oferecendo recursos extras;
◦ Integração com o Spring e Maven;
14. Quando Usar x Quando Não Usar
Quando Usar:
◦ Padrões Singleton ou Factory Method estático;
◦ Quando possuir um legado de testes escritos em EasyMock ou
Mockito: Devido a limitação destas ferramentas, deve-se usar as
extensões do PowerMock para um conjunto de funcionalidades mais
completo;
◦ Além dos testes unitários, pode ser utilizado em testes de
integração (e.g. @PowerMockIgnore ({“org.xml.*”,”javax.xml.*”} faz
com que o carregador de classes do PowerMock ignore estes pacotes)
Quando Não Usar:
◦ Quando não possuir o modelo preciso do comportamento/estado
do objeto que está querendo ser simulado;
◦ PowerMock foi desenvolvido por experts em teste unitário. Portanto, seu
uso não é indicado para desenvolvedores principiantes;
◦ Quando usa-se outras ferramentas de testes que não seja o JUnit
ou o TestNG.
15. Metendo a mão na massa
1. Configuração do Ambiente:
◦ Acesse a página:
https://code.google.com/p/powermock/downloa
ds/list e faça do download do arquivo que
contém o powermock-easymock-junit-X.X.X;
◦ No exemplo a seguir, usaremos a IDE Eclipse +
plugin do JUnit 4;
◦ Crie um Java Project e adicione os .jars do
arquivo baixado para dentro do projeto.
◦ Para usuários Maven, JUnit, TestNG ou Mockito,
há outras bibliotecas disponíveis para este tipo
de projeto;
16. Metendo a mão na massa
2. Conhecendo o projeto FinalMocking:
Neste exemplo, mostraremos como simular e
testar uma situação com classe e métodos com
marcação final:
Relembrando: Classes com atributos final não
poder ser herdadas; métodos com esta marcação
não podem ser reescritos; e variáveis com este
adjetivo geralmente representam valores
constantes;
Classes do Projeto: StateHolder.java,
StateFormatter.java e StateFormatterTest.java
17. Metendo a mão na massa
I. StateHolder.java:
Classe auxiliar da classe StateFormatter que
contém as marcações final;
II. StateFormatter.java
Simples classe que interage com seu
colaborador;
III. StateFormatterTest.java
O teste propriamente dito;
IV. Propósito:
Mostrar que o Powermock tem a capacidade
de criar um mock do colaborador, mesmo
que seja final, e esperar chamadas de
métodos, embora também seja final;
18. Metendo a mão na massa
public final class StateHolder {
/**
* @return The current state.
*/
public final String getState() {
// Imagine that we query a database for state
return null;
}
public final void setState(String state) {
// Imagine that we store the state in a database.
}
}
19. Metendo a mão na massa
public class StateFormatter {
private final StateHolder stateHolder;
public StateFormatter(StateHolder stateHolder) {
this.stateHolder = stateHolder;
}
public String getFormattedState() {
String safeState =
“Sem informação do estado do servidor.";
final String actualState = stateHolder.getState();
if (actualState != null) {
safeState = actualState;
}
return safeState;
}
}
20. Metendo a mão na massa
@RunWith(PowerMockRunner.class)
@PrepareForTest(StateHolder.class)
public class StateFormatterTest {
@Test
public void testGetFormattedState_actualStateExists() throws Exception {
final String expectedState = “servidor online";
StateHolder stateHolderMock = createMock(StateHolder.class);
StateFormatter tested = new StateFormatter(stateHolderMock);
expect(stateHolderMock.getState()).andReturn(expectedState);
replay(stateHolderMock);
final String actualState = tested.getFormattedState();
verify(stateHolderMock);
assertEquals(expectedState, actualState);
}
O PowerMock
cria um fake
“StateHolder”
O Powermock
ajuda a simular o
estado do
servidor;
Aqui, o PowerMock
prepara a classe
para teste por meior
de manipulação de
bytecode
21. Metendo a mão na massa
@Test
public void testGetFormattedState_noStateExists() throws Exception {
final String expectedState = "Sem informação do estado do servidor.";
StateHolder stateHolderMock = createMock(StateHolder.class);
StateFormatter tested = new StateFormatter(stateHolderMock);
expect(stateHolderMock.getState()).andReturn(null);
replay(stateHolderMock);
final String actualState = tested.getFormattedState();
verify(stateHolderMock);
assertEquals(expectedState, actualState);
}
}
22. Metendo a mão na massa
3. Copie o código das 3 classes para dentro
do seu projeto e execute o teste;
4. Todos os testes devem ocorrer sem falha:
23. Conclusões
O PowerMock contém um rico conjunto de
funcionalidades que bibliotecas
tradicionais de teste unitário não
possuem;
O PowerMock lhe ajudar a escrever o
melhor código, portanto, deve ser objeto
de estudo de qualquer desenvolvedor
Java;