- Por que fazer testes?
- saber se o software está funcionando de maneira automatizada
- não elimina os testes exploratórios feito de forma manual
- manter custos de desenvolvimento em níveis saudáveis
- ajuda na qualidade interna do código (design e arquitetura do código)
- saber se o software está funcionando de maneira automatizada
- Como avaliar a qualidade dos testes (se estão bem feitos)?
- corretude - se o teste não está gerando um falso positivo
- adequação do tipo de teste - se o teste é o mais adequado para a situação
- clareza - se o teste é fácil de ler
- adequação do tipo de teste
- qual o tipo de teste escrever?
- aceitação - testa o requisito funcional (o que o usuario vê e o que está especificado nos requisitos funcionais)
- unitário - testa uma unidade do sistema (classe ou método)
- integração - testa um comportamento que dois ou mais objetos fazem juntos
- qual o tipo de teste escrever?
- O teste de aceitação testa a regra de negócio e não a interface (botão ou texto na tela)
- Recomenda-se escrever o código em termos do domínio do problema e não do domínio técnico
- A pirâmide de testes é um guia sobre quantos testes devem ser escritos proporcionalmente entre testes de aceitação, integração e unitário.
- Na pirâmide de testes quanto mais perto do topo, o teste é mais frágil, mais lento e possui mais garantia de qualidade externa. Ao passo que quanto mais perto da base, o teste é menos frágil, mais rápido e possui menos garantia de qualidade externa.
- Pode-se utilizar teste unitário para realizar testes de views para verificar se um botão está pressionado como padrão, por exemplo, ao invés de se utilizar testes de aceitação.
- clareza
- é importante para o desenvolvedor (facilitar a leitura)
- é importante consirando o teste como documentação (linha de pensamento de BDD)
- Um teste pode ser estruturado (assim como uma redação) segundo as 4 fases padrão do xUnit:
- Setup - coloca o sistema no estado necessário
- Exercise - interage com o objeto sob teste
- Verify - checar se o comportamento aconteceu
- Teardown - colocar o sistema no estado anterior ao teste
- Um teste é claro quando é fácil de entender a relação de causa e consequência entre as fases do xUnit.
- Para avaliar a clareza de um teste basta lê-lo de forma isolada.
- Ao extrair fragmentos de código exageradamente (aplicar o princípio DRY) dificulta a clareza do teste.
- Na prática, o uso excessivo de DRY prejudica a clareza do teste.
- Recomenda-se não aplicar DRY em testes da mesma forma que é aplicado em códigos de produção.
- Favoreça a clareza do teste sobre DRY.
- Ao escrever um teste, pense nele como um exemplo de utilização do seu código.
- Como se tivesse explicando para alguém como utilizar o seu código.
- Ao pensar dessa maneira, você será forçado a deixar o seu teste claro.
- Os mocks e stubs são ferramentas clássicas na realização de testes sendo usados quase que diariamente.
- Porém, muitas pessoas não sabem a diferença entre ambos e/ou não entendem como funcionam.
- Os mocks não são uma ferramenta somente de teste.
- O SUT é system under test ou o objeto que está sendo testado.
- O objeto que está sendo testado possui, normalmente, uma dependência que é passada através do construtor. Essa dependência é chamada de DOC ou depended-on-component ou collaborator.
- Um test double (um mock ou stub, por exemplo) é quando no seu teste se substitui a dependência real por um objeto simulado (DOC).
- Os test doubles mais conhecidos são stub, mock, spy, fake e dummy object.
- O livro xUnit Patterns explica melhor o funcionamento dos test doubles.
- Por que precisamos de mocks?
- O conceito de mocks foi introduzido para ajudar no fluxo de desenvolvimento utilizando TDD.
- O conceito foi introduzido por Steve Freeman através de um paper chamado Endo-Testing: Unit Testing with Mock Objects.
- Foi descoberto com a técnica de mocks que é possivel fazer software pensando de modo outside-in e ir definindo as APIs internas dos objetos do ponto de vista de quem vai consumi-las.
- Uma ferramenta para descobrir a API dos colaboradores ou dependências do ponto de vista de quem as consome dentro do processo de desenvolvimento orientado a testes são os mocks.
- Os mocks surgiram para ajudar a fazer design de modo outside-in.
- Houveram dificuldades no entendimento do funcionamento de mocks e foi então criado outro paper chamado Mock Roles, not Objects.
- Recomenda-se a leitura do paper chamado Mock Roles, not Objects.
- Persistindo as dificuldades, os autores decidiram escreveer um livro, o Growing Object-Oriented Software, Guided by Tests.
- A interface discovery é o processo de descoberta da API e responsabilidades de novos objetos do seu sistema a partir de quem precisa utilizá-los. Esse é o motivo pelo qual os mocks são criados.
- Ao invés de verificar a impressão na tela, por exemplo, verifica-se se a comunicação entre os objetos está correta, ou seja, se o método foi chamado.
- O teste com mocks testa a chamada do método ou envio da mensagem.
- No teste (1) cria-se o test double, (2) injeta-se o objeto como dependência, (3) cria-se o mock do test double e, por fim, (4) verifica-se se o mock irá receber a mensagem correta.
- A ordem dos passos do teste muda de (1) setup, (2) exercise e (3) verify para (1) setup, (2) verify e (3) exercise.
- Pode-se utilizar um spy caso queira-se manter a ordem.
- Os mocks são utilizados para a fase de verify de um teste e não para a fase de setup como é comumente visto.
- No teste tradicional verifica-se o estado final do objeto.
- No teste por comportamento (com mocks) verifica-se a troca de mensagens entre os objetos.
- A orientação a objetos é menos sobre os objetos e mais sobre a troca de mensagens entre si.
- Um mock é um teste double utilizado na fase de verify.
- Mockar um objeto é programá-lo para verificar se ele recebeu as mensagens corretas do SUT. E não programar um objeto para retornar um valor padrão, isso é um stub.
- O mock foi criado originalmente para ser usado com a técnica de interface discovery.
- O que é um stub?
- É um test double utilizado na fase de setup.
- O conceito de stubar um objeto é programá-lo para retornar um valor padrão.
- Ao fazer um teste de aceitação que tem como detalhe consumir dados de uma API deve-se stubar uma API e não mockar uma API como todo mundo costuma dizer.
- A especificação por exemplos é uma técnica ágil para o levantamento de requisitos.
- Recomenda-se a leitura do livro Specification by Example para o entendimento da técnica.
- O Cucumber é uma ferramenta de especificação e documentação e não uma ferramenta de testes.
- As pessoas costumam utilizar o Cucumber para testes de aceitação e testes end-to-end equivocadamente.
- As ferramentas de specification by example como o Cucumber conforme a metodologia são utilizadas para fazer specs ou documentações executáveis.
- A ideia é trazer o conceito de documentação tradicional para o mundo ágil.
- A documentação tradicional (casos de uso e documentos Word) fica desatualizada com o passar do tempo.
- A documentação executável se mantém atualizada com o passar do tempo.
- As documentações são importantes e uma forma de mantê-las atualizadas foi juntá-las com os testes automatizados em algo chamado de documentação executável.
- O processo de especificação por exemplos começa na (1) definição do escopo do software com user stories, (2) especificação e ilustração com exemplos, (3) automatização da especificação e (4) possuir uma documentação viva.
- A documentação se torna 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 documentá-lo com linguagem natural
- difícil de entender o propósito do código apenas através da leitura do 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ócios e outros stakeholders
- Para documentar um overview do comportamento do sistema
- exemplo da documentação do RSpec e VCR
- Quando o domínio do negócio for complexo
- A fonte autoritativa sobre o comportamento do sistema é o código.
- Como usar o Cucumber?
- use a linguagem do domínio do problema, não a de linguagem de interface com usuário
- escreva a 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
- O testing iceberg ou pirâmide caída diz que nem todos os business-readable tests precisam ser end-to-end.
- Nem todos os testes end-to-end precisam ser legíveis por pessoas de negócio, ou seja, em Cucumber.
- Conclusão
- prefira clareza ao invés de DRY nos testes
- organize sua suíte segundo a pirâmide de testes
- substitua "testes de aceitação" por testes de view ou testes unitários (a suíte vai ficar mais rápida)
- testes de aceitação são sobre regras de negócio e não sobre especificação de UI
- stubs são para a fase de setup e mocks para a fase de verify
- quando alguém fala mockar provavelmente quer falar stubar
- os mocks foram criados para fazer outside-in com interface discovery
- o Cucumber é uma ferramenta de documentação e 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 testes business-readable sem ser end-to-end
Forked from marcelgsantos/coisas-que-eu-nao-sabia-sobre-testes.md
Created
March 28, 2019 14:44
-
-
Save rondy/253be8404b3522d5439ac9ff08769ff7 to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment