Começar e manter uma suíte de testes

Sabrina Jucá Neri
Tech@Grupo ZAP
Published in
4 min readSep 27, 2016

Aqui no VivaReal os desenvolvedores são os responsáveis por escrever os testes das aplicações, desde os testes unitários até os end to end.

Por que o espanto? Somos nós os responsáveis por garantir a qualidade do que desenvolvemos.

Quando entrei para o time, fui trabalhar no projeto do site do VivaReal. Era um sistema legado que tinha testes de unidade de back-end e de front-end, alguns testes de integração, e eles já faziam parte do build da aplicação, mas a cobertura de testes era bem pequena, pela quantidade de código, regras e integrações.

O time tinha adotado a estratégia de escrever os testes end to end (testes que simulam a utilização do usuário final), que não foi uma escolha baseada em TDD ou BDD, e sim da necessidade de nos sentirmos mais confortáveis ao fazer mudanças. Lembrando que era um sistema que não tínhamos total domínio e que já estava em produção.

Os testes foram feitos utilizando o WebdriverIO e a ferramenta circleci para executá-los em vários dispositivos e browsers.

Para melhorar o tempo gasto com manutenção, e facilitar a confecção de novos testes, adotamos o pattern page objects. A proposta desse pattern é criar um objeto para cada página e encapsular em cada classe os atributos (elementos) e métodos (ações das páginas). Se mudarmos o html da página, por exemplo, teremos um ponto só de alteração.

Segue um exemplo da página de detalhes de um imóvel, seguindo o pattern, com seus elementos e métodos:

Com a utilização desse objeto, o teste fica mais legível e muito mais fácil de ser escrito. Segue um exemplo:

Os testes escritos de forma clara, como mostramos anteriormente, podem servir também como documentação das funcionalidades do sistema. Chamamos também de documentação executável.

Nem tudo são flores

Os testes end to end são executados a cada pull request ou merge na master, assim conseguimos identificar possíveis bugs, mas temos alguns problemas com isso:

  • Nossos testes demoram muito para rodar, mesmo utilizando a execução em paralelo;
  • Demoram para dar feedback sobre o sistema;
  • Muitos testes falham devido a falsos positivos;
  • São difíceis de serem debuggados e corrigidos.

Pensando nisso e com a experiência que eu tive ao trabalhar em outros projetos, sei que não devemos aumentar muito a quantidade de testes end to end e que precisamos cobrir outros pontos.

Um conceito que gosto muito é o da pirâmide de testes, que foi desenvolvido por Mike Cohn no livro Succeeding with Agile. Segundo Cohn, uma estratégia eficiente de testes deve ter três níveis: os testes de unidade, os de integração e os de UI (os nossos end to end), e quanto mais alto o nível mais custoso e demorado eles são.

Os testes de unidade são fáceis de manter, são muito efetivos para testarmos partes isoladas do sistema, e baratos de serem desenvolvidos, por isso devem ser a base da estratégia de testes. Os de integração identificam erros entre os módulos do sistema. Além de darem um feedback mais rápido, esses dois testes, também facilitam em encontrar os problemas, uma vez que tais testes exercitam um escopo menor da aplicação quando comparados com os testes end to end.

Visto isso, não devemos apostar apenas em um único tipo de teste, pois um complementa o outro. Enquanto os testes de unidade permitem um feedback em segundos quando problemas são encontrados, os testes end to end reduzem a necessidade de testes manuais.

Mantendo a suíte de testes

Não é hora de relaxar! Manter uma suíte de testes não é tarefa fácil, mas o importante é ter testes que a equipe confie e que ajude no desenvolvimento do sistema.

Por isso, gostaria de deixar algumas dicas que me ajudaram muito na manutenção de suítes de testes de sistemas que eu já trabalhei:

  • Escreva uma descrição que dê significado para o teste, evite descrições como "returns empty", pois caso uma grande modificação no sistema seja feito, não saberemos porque o teste deveria retornar vazio. Escreva algo como: "returns empty when property not found", assim teremos mais contexto;
  • Se um teste quebrou e gastamos muito tempo analisando, esse teste é um grande candidato a ser revisto ou até mesmo apagado;
  • Encontrou um bug na aplicação? Então crie um teste, assim você terá certeza que esse bug não acontecerá mais;
  • Teste somente o necessário, evitando testar componentes que você não tem controle, como por exemplo, testar se dados foram preenchidos sendo que a aplicação está utilizando o Bean Validation do Java;
  • Nos testes end to end, identifique elementos pelo id sempre que possível, isso garante que os testes estão interagindo com o elemento certo;
  • Utilize ferramentas que auxiliem na criação dos cenários de testes, como Fixture-Factory (Java) ou o Factory Girl (Ruby), que criam instâncias de objetos através de templates;
  • Use Page Objects;
  • Testes unitários difíceis de serem feitos indicam problema no design da aplicação;
  • E por ultimo, identifique qual a melhor estratégia para testar uma funcionalidade, às vezes um teste de unidade já é o suficiente.

Até mais!!!

--

--