PARTE 3 - Tudo que um desenvolvedor precisa saber sobre testes
Tags: testing, architecture
Published: 2023-05-18 03:37:08

## Teste e refatoração

Testes automatizados e a prática de refatoração desempenham papéis fundamentais no desenvolvimento de software. Eles trabalham em conjunto para garantir a qualidade e a evolução contínua do código. No entanto, é importante considerar alguns aspectos específicos em relação a eles.

Testes automatizados podem apresentar desafios durante o processo de refatoração. Quanto mais detalhados e acoplados a implementações específicas eles forem, mais difícil será refatorar o código subjacente. Ao analisar o código de teste, é necessário refletir sobre as mudanças no código de produção e avaliar se essas mudanças resultarão em muitas falhas nos testes. Em alguns casos, pode ser necessário extrair partes do código de produção para uma área separada, como uma dependência de classe, a fim de facilitar a manutenção dos testes.

O uso de mocks também pode impactar a refatoração. Embora os mocks possam ser úteis em certos cenários, eles também podem complicar as modificações no código. Se as dependências externas estiverem fortemente acopladas ao código de produção e forem mockadas nos testes, as alterações na interação entre o código e essas dependências exigirão modificações nos mocks e, por consequência, nos testes. É importante considerar se o uso de mocks é realmente necessário ou se existem abordagens mais simples para a realização dos testes.

A abordagem de "testes estúpidos" pode ser benéfica. Esses testes são simples, diretos e aceitam várias entradas e saídas esperadas. Eles são mais flexíveis e menos propensos a quebrar durante a refatoração, em comparação com testes que se concentram em detalhes de implementação. Os testes estúpidos são fáceis de entender, manter e oferecem uma cobertura mais ampla das funcionalidades do código.

Manter os testes atualizados é fundamental. Assim como o código de produção, os testes precisam de manutenção contínua. É importante revisar e atualizar os testes à medida que o código evolui. Caso uma alteração no código de produção resulte em muitas falhas nos testes, isso pode ser um indicativo de que os testes precisam ser ajustados para refletir as mudanças.

O ciclo de refatoração e teste é iterativo. À medida que refatoramos o código, é necessário executar os testes para garantir que eles continuem passando. Por sua vez, os testes também podem auxiliar na identificação de áreas do código que precisam ser refatoradas para melhorar a legibilidade, manutenibilidade ou desempenho.

Lembre-se de que teste e refatoração são práticas complementares e contínuas. Eles visam melhorar a qualidade do código, sua manutenção e sua capacidade de evolução. Ao realizar refatorações, é essencial ter um conjunto robusto de testes automatizados para garantir que as modificações não introduzam regressões ou comportamentos indesejados no software.

## Testes Flaky

Testes flaky são prejudiciais ao sistema, pois geram mais ruído do que sinal claro. É comum encontrar esse tipo de teste em empresas de grande porte. Existem algumas causas principais para a flakiness, como concorrência, uso de async/await e dependências externas. Outra possível causa é a ordem de execução dos testes, mas geralmente isso pode ser resolvido facilmente utilizando recursos fornecidos pelas bibliotecas de teste, como o uso de BeforeAll para configuração inicial e AfterAll para limpar recursos ao final dos testes.

Problemas relacionados a async/await são bastante comuns. Por exemplo, quando se espera um retorno assíncrono, mas a resposta não é recebida dentro do tempo esperado, resultando em um teste flaky. Isso ocorre frequentemente em testes end-to-end (e2e), nos quais uma chamada a um serviço externo pode demorar para responder, levando o teste a falhar devido a um timeout.

Dependências externas também são uma causa comum de flakiness. Se um teste insere informações em um banco de dados, é importante garantir que, ao final da execução do teste, os dados sejam limpos adequadamente para que o próximo teste comece em um ambiente limpo, sem influência de dados anteriores que possam causar resultados inesperados.

Diante de testes flaky em um sistema, é comum adotar algumas abordagens para lidar com eles. Uma opção é marcar o teste com `.skip`, desabilitando-o temporariamente até que a causa do problema seja identificada e resolvida. No entanto, isso pode resultar em acumulação de testes desabilitados ao longo do tempo, o que é problemático e pode dificultar a manutenção dos testes. Outra opção é mover o teste para uma categoria separada, reservada especificamente para testes flaky, mas também é importante acompanhar e corrigir esses testes periodicamente para evitar a criação de um "cemitério de testes".

Se ninguém estiver trabalhando para corrigir um teste flaky e ele estiver causando mais problemas do que benefícios, pode ser apropriado simplesmente excluí-lo. Se o teste não está fornecendo informações úteis ou sendo visualizado pela equipe, sua remoção pode ajudar a manter um conjunto de testes mais confiável e eficaz.

## Testes em Sistemas Legados

A definição de um sistema legado é ampla, mas podemos considerá-lo como um sistema que é difícil de ser testado. Nesse caso, a dificuldade não é uma escolha sua, mas sim decorrente do alto custo e esforço envolvidos na criação dos testes.

A resposta mais comum para lidar com sistemas legados é refatorá-los e, em seguida, testá-los. No entanto, se a refatoração for muito custosa e não for uma opção viável devido a decisões tomadas por terceiros, como o sistema estar funcionando e gerando lucro, o que você pode fazer?

O primeiro passo é entender o que torna o sistema legado difícil de testar. Identifique os pontos problemáticos e crie uma infraestrutura de configuração adequada para facilitar os testes. Analise as decisões arquiteturais do sistema e busque maneiras de torná-lo mais amigável para testes. Lembre-se de que sistemas legados nem sempre são bem estruturados, portanto, não tenha receio de encontrar soluções não elegantes para realizar os testes.

É importante adotar uma abordagem pragmática ao lidar com sistemas legados. Foque na criação de testes que cubram os aspectos críticos e de maior risco do sistema. Concentre-se nas partes que têm maior impacto nos resultados e nas funcionalidades mais importantes para o negócio.

Além disso, é fundamental estabelecer uma cultura de teste dentro da equipe, mesmo em sistemas legados. Eduque os membros da equipe sobre a importância dos testes e incentive-os a escrever testes sempre que possível, mesmo que em partes isoladas do sistema.

Por fim, lembre-se de que a jornada de testes em sistemas legados pode ser desafiadora, mas é um esforço que vale a pena. Aos poucos, à medida que você avança na criação de testes e melhora a qualidade do sistema, torna-se mais fácil justificar a refatoração e a adoção de práticas de desenvolvimento mais modernas.

## Não Tenho Tempo para Testar

Pense que escrever o código de produção está diretamente relacionado ao código de teste. Sem testes, o código de produção não está completo. Alocar um tempo para escrever testes, mesmo que isso signifique investir um pouco mais de dinheiro e tempo, é preferível a encontrar bugs no teste do que em produção que possam resultar em grandes perdas financeiras.

É importante reconhecer que bugs podem ocorrer, mas ao escrever testes, você está garantindo que os fluxos básicos do seu código funcionem corretamente e evitando problemas futuros.

Escrever testes não é um custo, mas sim um investimento. E é um investimento que se paga rapidamente. Testes bem elaborados reduzem o tempo gasto na depuração de erros, pois ajudam a identificar e corrigir problemas mais cedo no processo de desenvolvimento. Além disso, eles oferecem maior confiança na estabilidade e na qualidade do código.

Ao dedicar um tempo adequado aos testes, você está investindo na construção de um código mais robusto, confiável e de fácil manutenção. Testar é uma etapa essencial do desenvolvimento de software, e negligenciá-la pode resultar em consequências indesejadas a longo prazo.

Portanto, enxergue os testes como um investimento valioso para a qualidade do seu código e para a saúde do seu projeto como um todo. O tempo investido na criação de testes se traduzirá em economia de tempo e recursos no futuro.

## Desenvolvedores e QA

É crucial que os desenvolvedores escrevam testes, pois são os primeiros responsáveis por garantir que o que estão desenvolvendo funcione corretamente.

Os desenvolvedores geralmente se concentram bastante na verificação do código, enquanto os profissionais de QA podem se dedicar à validação. O QA pode se envolver mais diretamente com as partes interessadas do negócio e focar na validação dos requisitos e na garantia de que o sistema atenda às expectativas.

Além disso, os profissionais de QA podem contribuir com a infraestrutura de testes. Eles têm uma visão mais ampla do sistema como um todo e entendem as dificuldades enfrentadas ao escrever testes. Dessa forma, eles podem ajudar a equipe a resolver problemas de infraestrutura e criar soluções que facilitem a escrita de mais testes.

Os profissionais de QA também podem colaborar com os desenvolvedores ao pensar em diferentes casos de teste. Com sua experiência em testes e conhecimento do domínio do negócio, eles podem ajudar a identificar cenários de teste relevantes, cobrindo uma variedade de casos de uso e situações especiais.

A colaboração entre desenvolvedores e profissionais de QA é essencial para garantir a qualidade do software. Ao trabalharem em conjunto, eles podem compartilhar conhecimentos, identificar problemas de forma mais abrangente e tomar decisões informadas sobre o projeto. A sinergia entre essas duas funções resulta em um produto final mais robusto e confiável.