Concrete Logo
Hamburger button

Como aplicar duas abordagens de testes unitários

  • Blog
  • 31 de Outubro de 2018

Este post foi escrito a partir de uma talk quer fiz aqui na Concrete, porque nos preocupamos muito com a qualidade do software e com os testes unitários. Melhores técnicas para escrever testes são sempre temas de talks e conversas entre nós, devs.

Além disso, tivemos problemas recentes em um projeto ao testar componentes do Angular e que, aparentemente, é um problema que transborda para outros frameworks, já que os conceitos não são muito claros.

Para quem não conhece testes unitários, uma unidade é a porção de código que você escolhe testar e durante esse teste você não pode ter dependências de outros trechos de código, componentes, serviços, rede etc. Para simular algumas dependências, você deve usar spy, stubs e mocks.

Ter um componente como unidade, envolve escrever testes unitários das entradas, saídas e comportamentos desse componente. Boa parte dos frameworks e bibliotecas atuais fornecem formas de criar testes unitários para eles.

Para esses testes temos dois tipos de abordagem que vamos tratar nesse artigo. Elas são conhecidas como shallow rendering unit tests e isolated unit tests (testes unitários de renderização superficial e testes unitários isolado).

Isolated Unit Tests

O que são os isolated unit tests? De forma simples, em testes unitários isolados você importa sua classe e chama os métodos dela, sem olhar para o seu template e o comportamento do mesmo.

Você escreve seus it e expects para métodos da classe, informa os parâmetros e observa a saída ou modificação de comportamento das propriedades ao chamar esses métodos.

Então se tivermos o seguinte componente (o exemplo foi tirado o site oficial do Angular.io)…

… o nosso teste seria escrito da seguinte forma:

Agora vamos ver um exemplo de teste de renderização superficial ou shallow test.

Shallow rendering test

São testes unitários que renderizam parte do seu template, sem precisar ou depender de outros componentes e com isso fazer as suposições. Esse tipo de teste requer algumas coisas além do teste isolado, mas vamos aos exemplos antes de falar mais sobre isso.

Imagina que temos o seguinte template como parte do nosso HeroComponent já mencionado na parte dos testes isolados:

Como testar se houve uma modificação do nome do herói em nosso componente, já que isso acontece no template e não em nossa classe? Para isso, faremos o seguinte teste:

Esse é um exemplo simples de como acontece o shallow unit test, ele “renderiza” parte do seu template criando elementos do DOM e observando eles ao longo do teste.

Problemas com shallow unit test

Ao comparar os testes, notamos como a estratégia de shallow é maior e mais verboso do que a forma isolada, além disso ele também traz alguns outros problemas e dificuldades para testar.

Alguns problemas que temos é que demora um pouco mais para executar os testes, porque algumas interações e comportamentos dos componentes ao serem testados exigem uma declaração ainda maior. Quando se trata de eventos que acontecem no DOM depedendo da experiência da pessoa ou do time com testes, pode ser algo que tira a velocidade de desenvolvimento e em alguns momentos parece que escrevemos testes integrados, já que existe a dependência de outras interações do browser.

Resolvendo o problema de eventos ao usar shallow unit test

Para um ponto especificamente quero deixar uma solução, já que foi algo pelo qual tive certos problemas com eventos disparados com clicks e eventos subsquentes que trazem verdadeiros problemas nos testes shallow.

Por exemplo, quando clicamos em alguns elementos do browser outros eventos são disparados, mas, quando isso acontece através de um script, não temos o disparo desses eventos, então o que fazer para testar?

Temos que criar um dispatchEvent especifico para vermos o resultado e chamadas da função que emitem. Como podemos ver no exemplo abaixo:

Com isso conseguimos chamar algumas funções dentro da classe do nosso componente. Para essa solução fica o agradecimento ao Marcus Ortense.

Qual das duas abordagens escolher?

Demonstrar essas duas abordagens de testes é importante, especificamente na documentação do Angular, só temos a abordagem por meio de shallow rendering e podemos usar outras formas e padrões para ter uma boa cobertura de teste e não depender das ações do template.

Agradecimentos

Obrigado pela ajuda do Emerson de Faria Batista na revisão e também do Marcus Ortense, já mencionado.

Referências
angular.io
Unit and Integration tests for Angular components. Part 2 out of 3

Ficou com alguma dúvida? Pergunte aí nos comentários.

A Concrete é uma empresa da Accenture especializada no desenvolvimento ágil de produtos digitais. No capítulo de JavaScript nós trabalhamos com metas possíveis, porém desafiadoras. Fazemos parte de um time multidisciplinar, autogerenciado e auto-organizado e focamos no aprendizado contínuo, seguindo sempre práticas ágeis e lean de desenvolvimento. Nosso objetivo é transformar ideias em resultados concretos, com excelência! Quer fazer parte? Envie seu currículo para trabalheconosco@concrete.com.br.