Pirâmide de testes, escrevendo testes com qualidade @ RubyConf 2015
- parâmetros para avaliar a qualidade de um teste e de uma suite de testes
- pirâmide de testes
- mocks não são apenas para testes, são para design
- cucumber não é uma ferramenta de testes, mas sim de documentação
- testing iceberg
● Testes de view não são ruins ● Mock não é apenas uma ferramenta de teste ● Mockar => Stubar ● Cucumber não é uma ferramenta de teste Quebrar alguns dogmas e pré-conceitos
Hugo Baraúna - Co-fundador e sócio da Plataformatec - Engenheiro de computação pela Poli-USP - Autor do livro "Cucumber e RSpec" pela Casa do Código Quem sou eu?
Qualidade de testes Como posso avaliar se meu teste ou suíte está com qualidade? ● Corretude ○ "o teste está verificando o comportamento correto do código?" ● Adequação do tipo de teste ○ "o teste foi feito com o tipo mais adequado?" ● Clareza ○ "está fácil de entender sobre o que é o teste?"
● Aceitação ○ testa um requisito funcional, normalmente pela UI ● Unitário ○ testa o comportamento de 1 objeto ● Integração ○ teste entre aceitação e unitário, testando comportamento de 2 ou mais objetos juntos Tipos de teste Para cada comportamento a ser testado, deve ser avaliado o tipo de teste mais adequado
Na prática: testes de aceitação São sobre o domínio do problema (regras de negócio), não sobre o domínio de UI ou de Web domínio do problema domínio de web dev domínio de web UI domínio de web dev
Na prática: testes de aceitação São sobre o domínio do problema (regras de negócio), não sobre o domínio de UI ou de Web domínio do problema domínio do problema domínio do problema
● Aceitação: testa um requisito funcional, normalmente pela UI ● Unitário: testa o comportamento de 1 objeto ● Integração: teste entre aceitação e unitário, testando comportamento de 2 ou mais objetos juntos Adequação do tipo de teste Para cada comportamento a ser testado, deve ser avaliado o tipo de teste mais adequado
Quantos testes fazer em cada camada? Pirâmide de testes: guia para estratégia de testes, baseado na natureza do tipo de teste aceitação integração unitário
Quantos testes fazer em cada camada? Pirâmide de testes: guia para estratégia de testes, baseado na natureza do tipo de teste aceitação integração unitário (+) frágil (+) lento (+) garantia qualidade externa (-) frágil (+) rápido (-) garantia qualidade externa
Na prática: escolher um tipo de teste apropriado - Devemos fazer poucos testes de acceptance, e vários de unidade - Podemos usar teste unitário de view, pois teste de acceptance não é para especificação de tela e sim para spec de regras do domínio do negócio
4 fases do xUnit Um teste pode ser estruturado segundo as 4 fases padrão do xUnit: 1. Setup: coloca o sistema no estado necessário 2. Exercise: interage com o objeto sob teste 3. Verify: verifica o comportamento esperado 4. Teardown: coloca o sistema no estado antes do teste
Clareza = Causa e consequência Um teste é claro quando é fácil de entender a relação de causa e consequência entre as fases do xUnit dado o seguinte estado do meu sistema quando exercito tal ação nele então consigo verificar tal comportamento esperado setup exercise verify
Na prática: avaliar a clareza de um teste O teste está claro? - em que estado o objeto game precisa estar para ser setado como 100? - o que tem ser feito no objeto game para que ele sete o score para 100?
● Uso excessivo de DRY nos testes prejudica a clareza ● DRY não deve ser aplicado em código de teste do mesmo modo que em código de produção ● Favoreça clareza sobre DRY Na prática: clareza X DRY
Tipos de test doubles Existem vários tipos de test doubles, cada um com um propósito e uso específico. ● stub ● mock ● spy ● fake ● dummy object Mais detalhes em http://xunitpatterns.com/Test%20Double.html
Verificação: estado X comportamento objeto objeto objeto objeto objeto objeto tradicional: verificação pelo estado final do objeto com mocks: verificação pelo interação entre os objetos
O que é um mock? ● Mock é um test double usado na fase de verify ● Mockar um objeto é programá-lo para verificar se ele recebeu as mensagens corretas do SUT ● Criado originalmente para ser usado com a técnica de interface discovery
Na prática: usar a terminologia corretamente ● Ao fazer um teste de aceitação que tem como detalhe consumir dados de uma API, qual é o correto? ○ mockar API ○ stubar API
Na prática: usar a terminologia corretamente ● Ao fazer um teste de aceitação que tem como detalhe consumir dados de uma API, qual é o correto? ○ mockar API ○ stubar API
Living documentation Especificação tradicional X Especificação executável Documentação tradicional fica desatualizada com o passar do tempo Documentação executável se mantém atualizada com o passar do tempo
Processo de especificação por exemplos Escopo (user stories) Especificação (ilustrar com exemplos) Automatizar com testes (especificação executável) Documentação viva
Quando usar Cucumber ● Quando o domínio do negócio for complexo ○ o domínio do negócio tem muitos termos que não são de conhecimento público ● Para algum comportamento do sistema que for muito complexo e houver valor em documentá-lo com linguagem natural ○ difícil de entender o propósito do código apenas através da leitura código ● Quando houver pessoas que precisam saber o comportamento do sistema mas que não consigam ler o código-fonte ○ suporte, analistas de negócio e outros stakeholders ● Para documentar um overview do comportamento do sistema ○ exemplo da documentação do RSpec e VCR
Como usar Cucumber ● use a linguagem do domínio do problema, não a de interface com usuário ● escreva documentação, não apenas automação de testes ● não precisa usar para todos os testes end-to-end, só para os que envolvem a necessidade de documentação
Testing iceberg Nem todos os business-readable tests precisam ser end-to-end business facing acceptance tests End-to-end integration tests business facing end-to-end acceptance tests
Qualidade de testes ● Prefira clareza ao invés de DRY nos testes ● Organize sua suite segundo a pirâmide de testes ● Substitua "testes de aceitacão" por testes de view ou testes unitários de Javascript ● Testes de aceitação são sobre regras de negócio, não sobre especificação da UI Concluindo
Mocks e stubs ● Stubs são para fase de setup, mocks são para a de verify ● Quando alguém fala "mockar", provavelmente ele/ela quer dizer "stubar" ● Mocks foram feitos com o propósito de fazer design com a técnica de interface discovery Concluindo
Concluindo Cucumber ● Cucumber é uma ferramenta de documentação, não de testes (especificação por exemplos) ● Você não precisa usar Cucumber para todos os testes end-to-end da sua aplicação ● É possível fazer business-readable tests sem ser end-to-end
Outros materiais para estudar ● http://guidelines.plataformatec.com.br/rspec.html ● Vídeo da Plataformatec sobre pirâmide de testes: http://bit.ly/em-foco-testes ● Paper para entender origem de mocks: Mock roles, not Objects ● Livro sobre BDD com Cucumber e RSpec, do Hugo Baraúna ● Livro sobre testes avançado: Growing object-oriented software guided by tests ● Livro sobre a metodologia por trás do Cucumber: Specification by Example