Refatorar testes de unidade?
Quando trabalhamos com código legado e precisamos fazer mudanças, primeiro escrevemos testes sobre o comportamento atual. Dessa forma, podemos implementar novas mudanças com confiança. Podemos até refatorar o código.
O código legado geralmente é um código ruim e, após algumas refatorações, o código pode ficar mais simples, fácil de testar. Já que o refatorador foi validado pelos testes, devemos também refatorar os testes se pudermos torná-los mais simples / claros ou mantê-los como foram escritos?
Respostas
Os testes automatizados SÃO código, portanto, manter esse código faz sentido, incluindo testes de refatoração quando apropriado. Contudo:
código produtivo e testes têm requisitos de qualidade diferentes
- não invista tempo em coisas que não importam
código produtivo deve ter uma única fonte de verdade, enquanto os testes devem ser amplamente autocontidos
- duplicação não é necessariamente ruim
E, como Ewan aponta, você nunca deve alterar o código e os testes ao mesmo tempo. Juntos, code + tests são um sistema de autoteste. Uma mudança em uma parte é verificada executando-a junto com a outra parte. Mudar os dois ao mesmo tempo abre mão dessa segurança. Isso nem sempre é possível na prática (por exemplo, ao alterar uma preocupação transversal, como uma biblioteca padrão subjacente), mas seria tolice abrir mão dessa segurança sem uma necessidade muito forte.
Motivos comuns pelos quais refatorei os testes, sem nenhuma ordem específica: a API que está sendo testada mudou, mudando para uma abordagem de teste diferente (por exemplo, teste baseado em cenário vs teste baseado em propriedade, testes em nível de API vs testes em nível de comportamento), mudando o estrutura de teste (por exemplo, para obter melhores relatórios de falha ou para usar testes parametrizados), mudando a organização de teste (por exemplo, suítes e casos de estilo xUnit vs estilo RSpec descreva-o), livrando-se da duplicação acumulada (por exemplo, extração de código comum para criar um acessório) , ...
Quando trabalhamos com código legado e precisamos fazer mudanças, primeiro escrevemos testes sobre o comportamento atual. Dessa forma, podemos implementar novas mudanças com confiança. Podemos até refatorar o código.
Isso pode estar refletindo às vezes seu processo de trabalho, mas na minha experiência, um processo mais eficiente é:
você escreve testes
você refatora para tornar a mudança mais fácil
você implementa a mudança
Dessa forma, fica mais evidente que você refatora quando há um motivo real para uma alteração , não apenas porque o código "não está mais limpo".
Agora tente aplicar as mesmas medidas aos seus testes: você não refatora seus testes porque "eles não estão mais limpos" . Você os refatora quando eles começam a impedi-lo de fazer alterações fáceis em seu código existente.
Por exemplo, quando você tem dez testes chamando o mesmo método público de uma classe em testes, enquanto em seu código de produção esse método público é chamado apenas em um lugar, então esta é uma forma de duplicação de código por testes que pode impedi-lo de alterar a assinatura desse método público.
Eu normalmente deixaria assim, a menos que você realmente obtivesse o requisito para o último, ou mais geral: quando você perceber, essa duplicação de código exige que você faça a mesma alteração em seus testes em vários lugares.
Você pode querer começar refatorando os testes.
Os testes capturam o que o aplicativo legado faz; uma espécie de documentação. Os testes informam a entrada e a saída, o código informa o processo. Se os testes forem ruins, organizá-los (dependendo de quão ruins eles são) ajudará você a entender o código.
Também é uma ótima maneira de julgar se os testes agregam valor; um sistema legado em que trabalhei tinha grande cobertura de código, mas na inspeção os testes afirmavam coisas inúteis ... como garantir que Getters e Setters funcionassem (testando o framework .NET, não o aplicativo).
Depois de obter um teste limpo, você terá um melhor entendimento do código e poderá tomar melhores decisões sobre como refatorar o código.