testes unitários
TRANSCRIPT
TESTES UNITÁRIOS
Jadson SantosSoftware Engineer
03/05/2023 Testes Unitários 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
03/05/2023 Testes Unitários 3
Testes Unitários
03/05/2023 Testes Unitários 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
03/05/2023 Testes Unitários 5
Testes Unitários
03/05/2023 Testes Unitários 6
Testes Unitários
• Como escrever um teste para essa classe???
03/05/2023 Testes Unitários 7
Testes Unitários• Criando método para testar conta com saldo
03/05/2023 Testes Unitários 8
Testes Unitários
•Pronto??? •A classe está testada ????
03/05/2023 Testes Unitários 9
Testes Unitários• Criando método para testar conta sem saldo
03/05/2023 Testes Unitários 10
Testes Unitários
•E agora??? •A classe está testada ????
03/05/2023 Testes Unitários 11
Testes Unitários• E se alguém criar uma conta passando nulo???
03/05/2023 Testes Unitários 12
Testes Unitários• Alterando a classe conta para passar no 3º teste
03/05/2023 Testes Unitários 13
Testes Unitários
• Qualquer alteração na classe Conta, você terá mais confiança de que o comportamento do método temSaldo será mantido!!!
Os três testes passaram
03/05/2023 Testes Unitários 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!!!
03/05/2023 Testes Unitários 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.
03/05/2023 Testes Unitários 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
03/05/2023 Testes Unitários 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
Junit
03/05/2023 Testes Unitários 18
Junit
•Vamos criar o mesmo teste da classe
Conta usado o JUnit
03/05/2023 Testes Unitários 19
JUnit• Criando um teste unitário com JUnit
03/05/2023 Testes Unitários 20
JUnit
• Criando um teste unitário com Junit• Defina o nome da classe• E a classe que vai ser
testada
03/05/2023 Testes Unitários 21
JUnit
• Criando um teste unitário com JUnit• Escolha os métodos a serem testados
03/05/2023 Testes Unitários 22
JUnit
• Criando um teste com JUnit
A partir da Versão 4 do JUnit todo método com um @Test é um teste unitário a ser executoSubstitui o método main()
03/05/2023 Testes Unitários 23
JUnit
• Criando um teste com JUnit
Junit possui vários métodos “assertions” Substitui os testes feitos anteriormente “if ... else .. println()”
03/05/2023 Testes Unitários 24
Main Assert Statementsfail(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
03/05/2023 Testes Unitários 25
JUnit• Criando um teste com Junit
• Existem vários métodos assertX, para validar os resultados dos testes
03/05/2023 Testes Unitários 26
JUnit
• Criando um teste com Junit• Executando os Teste pelo Eclipse
03/05/2023 Testes Unitários 27
JUnit• TestSuite: Permite executar um conjunto de testes de uma só vez.
03/05/2023 Testes Unitários 28
JUnit
• Criando um teste com Junit• TestSuite: Roda vários casos de testes ao mesmo
tempo
03/05/2023 Testes Unitários 29
JUnit
• Criando um teste com Junit• TestSuite: Roda vários casos de testes ao mesmo
tempo
03/05/2023 Testes Unitários 30
JUnit
• Criando um teste com Junit• TestSuite: Roda vários casos de testes ao mesmo
tempo
Para adicionar novos testes ao TestSuite, basta apenas adicionar novas classes à anotação @SuiteClasses
03/05/2023 Testes Unitários 31
JUnit Annotations@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
@Beforepublic void method()
Executa antes de cada teste. Usado para preparar o ambiente de teste
@Afterpublic void method()
Executa depois de cada teste. Usado para liberar recursos do teste
@BeforeClasspublic 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
@AfterClasspublic 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
03/05/2023 Testes Unitários 32
JUnit Annotations
03/05/2023 Testes Unitários 33
JUnit Rule• Pode-se criar objetos que podem ser usados nos seus métodos de teste
03/05/2023 Testes Unitários 34
JUnit Categories• Serve para agrupar tipos de testes
03/05/2023 Testes Unitários 35
JUnit Categories• Define em um TestSuite quais categorias serão executadas por ele.
03/05/2023 Testes Unitários 36
Mock Objects• 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.
03/05/2023 Testes Unitários 37
Mock Objects• 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
03/05/2023 Testes Unitários 38
Mock Objects
• No mundo real a classe Conta deveria atualizar o saldo de forma persistente, não apenas em memória.
03/05/2023 Testes Unitários 39
Mock Objects• Nova versão da classe Conta:
03/05/2023 Testes Unitários 40
Mock Objects• Tentativa de Criar um Teste para nova classe Conta
passando um objeto DAO para atualizar o saldo:
03/05/2023 Testes Unitários 41
Mock Objects
• 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.
03/05/2023 Testes Unitários 42
Mock Objects• Criação de uma subclasse que simula(Mock) ser um
banco de dados
03/05/2023 Testes Unitários 43
Mock Objects• 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
03/05/2023 Testes Unitários 44
Mock Objects• 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 ....
03/05/2023 Testes Unitários 45
Mockito• É um Framework popular para construção de Mocks que pode ser usado em conjunto com o JUnit.
Mockito
Junit
03/05/2023 Testes Unitários 46
Mockito• Em vez de você precisar criar os Mocks, você apenas indica, que o Mockito criar o mock para você.
03/05/2023 Testes Unitários 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(...)
03/05/2023 Testes Unitários 48
Mockito• Definindo o comportamento do método buscaPorSaldoMaiorQue() do mock.
03/05/2023 Testes Unitários 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.
03/05/2023 Testes Unitários 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.
03/05/2023 Testes Unitários 51
Mockito• Testar se um código foi executado.
Ú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.
03/05/2023 Testes Unitários 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étodosMockito.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
03/05/2023 Testes Unitários 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;
03/05/2023 Testes Unitários 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.
03/05/2023 Testes Unitários 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
03/05/2023 Testes Unitários 56
PowerMock• Um Framework do Mock que estende o Mockito para provê mocks mais poderosos.
• Principalmente de mockar objetos estáticos
Mockito
Junit
PowerMock
03/05/2023 Testes Unitários 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.
03/05/2023 Testes Unitários 58
PowerMock• Testar uma classe que usa o método estático getBundle()
03/05/2023 Testes Unitários 59
PowerMock• Apenas com o Mockito
03/05/2023 Testes Unitários 60
PowerMock• Apenas com o Mockito
03/05/2023 Testes Unitários 61
PowerMockUse 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
03/05/2023 Testes Unitários 62
PowerMock• Usando o PowerMock
03/05/2023 Testes Unitários 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 Rothwww.thedance.net/~roth/TECHBLOG/
powerMock.html
03/05/2023 Testes Unitários 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.
03/05/2023 Testes Unitários 65
PowerMock• 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”));
03/05/2023 Testes Unitários 66
Testes na Integração Contínua
03/05/2023 Testes Unitários 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]
03/05/2023 Testes Unitários 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
03/05/2023 Testes Unitários 69
Teste na Integração Contínua• Chamando Test Suites a partir do Gradle.
03/05/2023 Testes Unitários 70
Teste na Integração Contínua• Rodando os testes do sistema periodicamente
• Para isso crie um job que rode constantemente (idealmente a cada commit) e execute os testes unitários
03/05/2023 Testes Unitários 71
Teste na Integração Contínua• Rodando os testes do sistema periodicamente
• Esse job invoca a task unitTest do Gradle que por sua vez executa os Test Suites do sistema
03/05/2023 Testes Unitários 72
Teste na Integração Contínua• 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
03/05/2023 Testes Unitários 73
Teste na Integração Contínua• 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
03/05/2023 Testes Unitários 74