Ao contrário das outras respostas, é importante observar que algumas formas de teste podem se tornar frágeis quando o sistema em teste (SUT) é refatorado, se o teste for uma caixa branca.
Se eu estiver usando uma estrutura de simulação que verifique a ordem dos métodos chamados nas zombarias (quando a ordem é irrelevante porque as chamadas são livres de efeitos colaterais); se meu código for mais limpo com essas chamadas de método em uma ordem diferente e eu refatorar, meu teste será interrompido. Em geral, as zombarias podem introduzir fragilidade nos testes.
Se eu estiver verificando o estado interno do meu SUT, expondo seus membros privados ou protegidos (poderíamos usar "friend" no visual basic ou escalar o nível de acesso "internal" e usar "internalsvisibleto" em c #; em muitos idiomas OO, incluindo c # uma " subclasse específica de teste " pode ser usada) e, de repente, o estado interno da classe será importante - você pode refatorar a classe como uma caixa preta, mas os testes da caixa branca falharão. Suponha que um único campo seja reutilizado para significar coisas diferentes (não é uma boa prática!) Quando o SUT muda de estado - se o dividirmos em dois campos, talvez seja necessário reescrever testes quebrados.
As subclasses específicas de teste também podem ser usadas para testar métodos protegidos - o que pode significar que um refator do ponto de vista do código de produção é uma mudança radical do ponto de vista do código de teste. Mover algumas linhas para dentro ou fora de um método protegido pode não ter efeitos colaterais na produção, mas interromper um teste.
Se eu usar " ganchos de teste " ou qualquer outro código de compilação condicional ou específico do teste, pode ser difícil garantir que os testes não sejam interrompidos devido a dependências frágeis da lógica interna.
Portanto, para evitar que os testes sejam acoplados aos detalhes internos íntimos do SUT, isso pode ajudar a:
- Use stubs em vez de zombarias, sempre que possível. Para mais informações, consulte o blog de Fabio Periera sobre testes tautológicos e meu blog sobre testes tautológicos .
- Se estiver usando zombarias, evite verificar a ordem dos métodos chamados, a menos que seja importante.
- Tente evitar verificar o estado interno do seu SUT - use sua API externa, se possível.
- Tente evitar lógica específica de teste no código de produção
- Tente evitar o uso de subclasses específicas de teste.
Todos os pontos acima são exemplos de acoplamento de caixa branca usado em testes. Portanto, para evitar completamente a refatoração dos testes de quebra, use o teste de caixa preta do SUT.
Isenção de responsabilidade: Com o objetivo de discutir a refatoração aqui, estou usando a palavra um pouco mais amplamente para incluir alterações na implementação interna sem efeitos externos visíveis. Alguns puristas podem discordar e se referir exclusivamente ao livro Refatoração de Martin Fowler e Kent Beck - que descreve operações de refatoração atômica.
Na prática, tendemos a tomar etapas ininterruptas um pouco maiores do que as operações atômicas descritas lá e, em particular, alterações que deixam o código de produção se comportando de forma idêntica do lado de fora podem não deixar os testes aprovados. Mas acho justo incluir "um algoritmo substituto para outro algoritmo que tenha comportamento idêntico" como um refator, e acho que Fowler concorda. O próprio Martin Fowler diz que a refatoração pode quebrar os testes:
Ao escrever um teste de simulação, você está testando as chamadas de saída do SUT para garantir que ele fale adequadamente com seus fornecedores. Um teste clássico se preocupa apenas com o estado final - e não como esse estado foi derivado. Os testes mockistas são, portanto, mais acoplados à implementação de um método. Mudar a natureza das chamadas para os colaboradores geralmente causa um teste de simulação.
[...]
O acoplamento à implementação também interfere na refatoração, pois as alterações na implementação têm muito mais probabilidade de interromper os testes do que nos testes clássicos.
Fowler - Zombarias não são stubs