Post on 07-Apr-2016
Luiz Carlos d´Oleronlcadb@cin.ufpe.br
SJCP
JUnit
Java Avançado
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
O que é JUnit?• Que tipo de aplicações
eu posso fazer com JUnit?
• Para que serve JUnit?
• Como usar o JUnit?
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
JUnit e testes
• JUnit é um framework para criação de testes
• Com JUnit não fazemos a aplicação em si, mas...
• Podemos criar código que irá testar código
• ...mas para quê?
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Para que testar?• E por que não testar?
• Você sempre testa suas sistemas
• Seja com um método main
• Seja usando o sistema depois de uma implementação
• Testes aumentam a confiança no código
• Testes diminuem o medo de alterar o código
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Por que testar?
• Para garantir que o código está funcionando
• Para validar requisitos
• Para validar modificações
• Para identificar erros
• Para simplificar o desenvolvimento
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Por que testar?
Mais cedo ou mais tarde seu código será testado, mesmo que seja quando o cliente
estiver usando o sistema!
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Por que JUnit?• Por que ele automatiza os testes
• Testes automatizados são essenciais no desenvolvimento atual
• Eles validam os requisitos do sistema
• Eles modelam os requisitos do sistema!
• Eles identificam os ERROS, mesmo quando você nem imagina que eles poderiam ocorrer!
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Desenvolvimento Orientado a Testes
“Quanto mais velho eu fico, mais agressivo me torno em relação a testes. Testes deveria ser um processo contínuo. Nenhum código deveria ser escrito até que você saiba como testá-lo. Uma vez que você escreva um código, escreva os testes para ele. Até que os testes funcionem, você não pode anunciar que terminou de escrever o código.”
Martin Fowler, UML Essencial, 2ª Edição, Bookman
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
O que é teste automatizado
• É uma aplicação que irá executar, a pedido do programador, ou de forma programada
• Normalmente quando o sistema está sendo desenvolvido
• Que irá testar o código do sistema
• Gerando uma resposta “sim” ou “não”
• Representando que o código passou ou não passou no teste
• É comum também um relatório descrevendo os erros ou falhas, quando elas ocorrem.
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
O que é um teste de unidade?
• É um teste que irá avaliar uma unidade
• Uma unidade é uma parte lógica do código– Pode ser um objeto inteiro– Um método– Uma transição– Um estado
• Avalia somente o comportamento do componente
• Não avalia as interações do componente com outras entidades
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
O que testar?• Situações de sucesso
– O método fornece o comportamento esperado quando recebe a entrada correta? Testes os cenários aonde tudo dá certo.
• Situações de falha– O método se comporta como esperado quando colocado sob condições
“hostis”? Testes os cenários aonde tudo dá errado.
• As pré-condições– Como o sistema deve estar antes da execução do método?
• As pós-condições– Como o sistema deve estar após a execução do método?
• Teste (principalmente) as regras de negócio– GUI´s e código de formatação pode ou não pode ser testado
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
JUnitJUnit é um framework para testes de
unidades automatizados para aplicações Java. Todo tipo de aplicação (web, desktop, mobile) poderá se beneficiar de JUnit.
Foi criado por Erich Gamma (escritor de Design Patterns) e Kent Beck (criador da metodologia XP).
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
JUnit
Existem plug-ins para praticamente todas as IDE´s sérias de desenvolvimento Java. Lembre-se que você poderá usar JUnit mesmo se não estiver usando nenhuma IDE, compilando e executando tudo pela linha de comando. Além disso, JUnit se integra perfeitamente com a tecnologia ANT.
Usar JUnit é muito simples. basicamente utilizamos:
• TestCases• Fixtures• Test Suites
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
JUnit
• TestCases– Um TestCase define uma fixture para ser avaliada perante um conjunto
de testes.– Cada classe deveria ter um TestCase associado– O normal é termos um TestCase que instancia um objeto e testa todos
os seus métodos
• Test Fixtures– Recursos necessários para a execução do teste– variáveis primitivas– Objetos
• Test Suite– Coleção de testCases correlacionados
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Criando um teste• Criaremos um novo projeto no
Eclipse, normalmente, como fizemos antes
• Em libraries, podemos usar add External Jars... para definir o local de junit.jar
• Podemos também usar Add Variable... para indicar que utilizaremos JUNIT_HOME
• Eclipse possui um Wizard para criação de TestCases, mas, para facilitar nosso entendimento, não usaremos ele
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Criando o TestCase• Criamos uma classe,
normalmente, chamando-a de TestHashMap
• Colocaremos ela no pacote testes
• Importante: Nossa classe deverá extender junit.framework.TestCase
• Marque a opção public static void main(String [] args)
• Clicamos em Finish
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Codificando o teste• Eclipse criou para nós o
esqueleto de uma classe que extende TestCase
• Adicionamos 5 variáveis ao nosso teste. Estas variáveis são os fixtures do teste
• Elas nos ajudarão a testar a classe HashMap
•Observe que utilizamos generics para definir uma Map que mapeia Strings em Strings
•Se você não tiver configurado o projeto para usar Java 5.0, Eclipse e o compilador javac irão reclamar!
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
setUp e tearDown
• Após adicionarmos nossos fixtures, vamos codificar os métodos protected void setUp() throws Exception e protected void tearDown() throws Exception
• Esses métodos são responsáveis por configurar os fixtures e liberar os recursos dos fixtures, respectivamente.
• Observe que setUp e tearDown são protected, eles já existem em TestCase, de forma que quando os codificamos, estamos realizando overriding
• No nosso exemplo, todos os recursos adquiridos por setUp serão coletados pelo Garbage Colector. Por isso, nosso método tearDown terá uma implementação vazia (não era necessário nem mesmo reescrevê-lo)
• Se setUp alocasse conexões de rede ou com banco de dados, era necessário que nós liberássemos esses recursos dentro de tearDown
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
setUp e tearDown
• O eclipse possui um recurso para Override (Menu Source >> Override/Implements Methods) que poderá facilar a escrita de setUp e tearDown
• Se esse recurso for utilizado, observe que eclipse incluirá a annotation @Override
• setUp e tearDown serão executados antes e depois, respectivamente, de cada teste
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Codificando os testes• JUnit utilza um padrão para a criação de testes
• Testes são métodos de subclasses de TestCase
• Todo teste deve possuir a assinatura:
public void testXXX()
• Aonde XXX pode ser trocado por outro identificador
• JUnit utilizará este padrão para encontrar os métodos que serão executados
• Normalmente, temos um teste para cada método do fixture
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Codificando os testes
• Nos testes é onde nós manipulamos as fixtures e fazemos asserções sobre o comportamento delas
• No nosso exemplo, nós testaremos apenas dois métodos de Map, o size e o put
• Utilizamos duas versões do método assertEquals da classe TestCase. Existem outros tipos de asserções, como assertNull e assertNotNull
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
TestRunner
Finalmente, escrevemos o corpo do método main, de forma que possamos chamar o TestRunner
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
TestRunner• JUnit vem com três tipos de TestRunner:
– junit.swingui.TestRunner– junit.textui.TestRunner– junit.awtui.TestRunner
• Cada tipo utiliza uma tecnologia para executar e apresentar os resultados do teste
• Ao executar a classe TestHashMap, o testRunner escolhido irá ser invocado
• Eclipse vem com o próprio TestRunner, que pode ser executado clicando-se Run >> Run as >> JUnitTest
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
junit.swingui.TestRunner
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Eclipse e New JUnitTest Wizard
• Eclipse possui uma ferramenta para criação automática de TestCases
• Basicamente, o New JUnitTest Case Wizard cria uma subclasse de TestCase
• Para cada método e contrutor, o New JUnitTest Case Wizard cria um método testXXX
• O corpo dos testes está inicialmente vazio, ficando a cargo do programador codificar os testes.
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Eclipse e New JUnitTest Wizard
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Test Suite
• As aplicações são compostas de dezenas, centenas ou milhares de classes
• É comum que em um projeto existam um número enorme de TestCases
• Test Suite é uma forma de agrupar Test Cases correlatos. Ao invés de executar os testes um por um, com Test Suite é possível executar todos os testes de uma vez.
• Mais uma vez, Eclipse possui um Wizard para criação de Test Suites
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Test Suite
• Para criar um Test Suite, clique com o botão direito no pacote aonde os testes estão. Em seguida, clique em new >> other
• Expanda a pasta java e em seguida expanda a pasta JUnit
• Selecione JUnit Test Suite e Clique em Next
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Test Suite• Se desejar, redefina o nome do
TestSuite
• Selecione os Test Cases e clique em Finish
• Se desejar, você poderá criar um método main que chamará um test runner específico
• Eclipse terá criado Test Suite para você
• Para executá-lo, clique em Run >> Run As>>JUnit Test
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Aonde colocar os testes?
• O ideal é colocá-los no mesmo pacote das classes testadas
• Assim, será possível acessar os métodos e variáveis com visibilidade default-protected
• Ant-Scripts podem dividir as classes do sistema das classes de testes para deploy
• Colocar em uma hierarquia paralela também é uma estratégia utilizada
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Limitações do JUnit
• Código testando código pode gerar problemas de “realimentação” (quem sabe se o código de testes está correto?)
• JUnit testa só características não privadas (só as acessíveis)
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
TDD
• É possível usar JUnit sem aplicar TDD
• Mas o maior ganho de usar JUnit ocorre quando você usa TDD
• TDD – Test Driven Development– Desenvolvimento orientado a testes– Associado à técnicas de desenvolvimento ágil
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
TDD
• Antes de codificar, crie um teste para o código
• O teste não irá compilar, muito menos executar
• Então, construa o “esqueleto” do código até que o teste compile
• Rode o teste, ele irá falhar
• Codifique até que o teste passe (sem mexer no teste)
• Não codifique mais, trabalho terminado!
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
TDD
• Garante que todo código irá ser testado
• Permite que o código que será construído seja o mais simples possível
• Quando o programador for construir o código, ele saberá exatamente qual deverá ser o comportamento do dele
• TDD é utilizado com metodologias de desenvolvimento ágil - www.agilealliance.com
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Refactoring• Uma técnica utilizada no desenvolvimento de software, em especial,
no desenvolvimento ágil de software, é o Refactoring.
“Refactoring is the process of rewriting a computer program or other material to improve its structure or readability, while explicitly keeping its meaning or behavior.”
http://wikipedia.org
• Como garantir que o comportamento do software será o mesmo após o refactoring?
• Como garantir que o refactoring não foi agressivo ao código, gerando erros?
• Para garantir Refactoring, é indispensável o uso de testes. O processo é realizado comparando as saídas dos testes realizados antes e depois do Refactoring.
• Sem testes, não existe Refactoring!
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Mitos de testes
• Criar testes atrasam o desenvolvimento– Errado. Encontrar bugs é o que atrasa desenvolvimento
• Testes só no final– E o que fazer se todos os testes falharem?
• Se todos os testes passam, o sistema está perfeitamente a prova de falhas– Todas as possibilidades foram testadas?
• Testes só para testar– Testes são uma ferramenta importante para a especificação de
requisitos
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Atividade prática• Criar a classe Autentica, que possui apenas o método:public boolean autenticar(String login, String senha)
• Este método deve verificar se o login e senha são válidos, retornando true. Se login e senha não conferirem, o método deve retornar false.
• Caso login ou senha sejam passados null ou igual à String vazia, autenticar deve lançar uma java.lang.IllegalArgumentException.
• Caso sejam efetuadas três tentativas inválidas seguidas, todas as tentativas seguidas devem falhar, indiferente do que for fornecido como login e senha
• Crie uma classe de testes para validar estes requisitos
• Você poderá criar tanto a classe primeiro ou o teste primeiro
• Escolha uma forma para que cada objeto da classe Autentica possa armazenar as combinações corretas de login e senha
Luiz Carlos d´Oleron – lcadb@cin.ufpe.br
Bibliografia• Java Tools for Extremme Programming, Richard
Hightower
• Desenvolvimento guiado por testes com JUnit, Helder da Rocha
• Jakarta-Struts Live, Richard Hightower
• UML Essencial, Martin Fowler
• www.junit.org