PARTE 2 - Tudo que um desenvolvedor precisa saber sobre testes
Tags: testing, architecture
Published: 2023-05-18 03:35:44

## Lições de design voltado para testabilidade

É fundamental escrever sistemas que sejam fáceis de serem testados. Se for muito difícil automatizar os casos de teste, você não verá os benefícios de tê-los escrito. Portanto, é importante que seja fácil e barato escrever testes. Para tornar isso possível, é preciso prestar atenção em algumas lições de design.

1. Desacoplamento:
    - Separe a infraestrutura da sua regra de negócio. Sua regra de negócio não precisa ter uma complexidade tão grande. Por exemplo, não é necessário ter uma implementação direta do Firebase no meio do seu código.
    - A arquitetura hexagonal pode ajudar nisso. Ela sugere que você desacople sua regra de negócio e seu domínio da infraestrutura (serviços externos). Você também pode utilizar o padrão chamado "adapter". O seu adapter vai ter todo o código necessário para se comunicar com a infraestrutura, tornando-os facilmente mockáveis. Portanto, avalie como você pode desenhar o seu sistema dessa maneira.
2. Controlabilidade:
    - Com a controlabilidade, você quer que seja muito fácil testar o seu componente. O seu componente deve ser fácil de ser controlado. Você deve ser capaz de definir um estado inicial X e, em um momento de teste posterior, verificar se ele retorna uma determinada condição.
    - Por exemplo, se for difícil controlar o componente para fazer com que ele retorne uma exceção quando necessário, então você não conseguirá testar esse caso adequadamente. Quando você tem a controlabilidade do componente, é possível escrever testes a partir de diversos pontos de vista.
3. Observabilidade:
    - Deve ser fácil observar como o componente se comportou. Você quer fazer uma asserção para garantir que o componente funcionou da maneira esperada. Portanto, é importante que seja muito fácil realizar um assert nesse componente.
    - Além disso, deve ser fácil fazer perguntas ao seu componente durante os testes.
4. Classes pequenas e responsabilidade única:
    - Classes grandes não são boas. Suas classes devem ter uma única responsabilidade. O seu sistema deve ser composto por várias classes que colaboram entre si para entregar o resultado.
    - Classes pequenas permitem uma compreensão maior. É muito mais fácil ler 20 linhas de código do que 500.
    - Se você tiver uma classe que carrega outras classes menores, será mais fácil realizar testes unitários. Por outro lado, se você tiver uma classe que faz tudo, não terá a opção de realizar um teste unitário e terá que ir direto para um teste de integração.

## Qualidade dos seus testes

O código de teste também é código, e precisamos realizar sua manutenção. Portanto, tornar o código de teste fácil de ser mantido é uma responsabilidade do desenvolvedor.

O código de teste deve ser fácil de escrever, manter, evoluir e depurar.

Assim como o código de produção pode se tornar complexo, o código de teste também pode ser. Seus testes devem ser coesos, ou seja, testar uma única funcionalidade em vez de tentar abranger 30 funcionalidades diferentes. Testes longos e difíceis de entender são problemáticos.

Os testes devem ter uma razão clara para existir. Eles não devem ser criados apenas para aumentar a cobertura de código. Uma boa razão para um teste é simular um bug que ocorreu. Tente escrever testes úteis que tenham a chance de identificar um bug real.

Os testes devem ser repetíveis, ou seja, podem ser executados várias vezes e sempre devem produzir o mesmo resultado. Se um teste às vezes passa e às vezes falha, é considerado um teste instável. Por que os testes instáveis são ruins? Eles levam os desenvolvedores a perderem a confiança neles, pois não é possível determinar se uma falha é um bug real ou apenas instabilidade do teste. Evite ao máximo os testes instáveis.

Os testes devem quebrar quando o sistema é alterado. Se você modificou seu código de negócio e o teste não falhou, algo está errado. Em sistemas complexos, é fácil escrever testes que não testam nada.

Os testes devem ter uma razão clara para falhar. Você quer que o teste o ajude na depuração. Quando um teste falha, você quer que ele forneça uma mensagem de erro clara e informativa.

Os testes devem ser fáceis de ler. Se um teste está falhando, ele deve ser compreensível. As mesmas questões de legibilidade de código se aplicam ao código de teste. Refatorar o código de teste também é essencial.

O código de teste deve ser fácil de evoluir. Se o código de produção está evoluindo, o código de teste também deve acompanhar. Você não quer ter que lidar com 30 testes falhando porque modificou uma única parte do código de produção.