Devo refatorar meus testes de unidade quando extrair uma classe do Sistema em Teste?

13

Escrevi para esta classe que faz algumas coisas (talvez isso seja uma violação do Princípio da Responsabilidade Única). Agora percebo que alguma outra parte do projeto precisa de uma parte dessa lógica e a maneira como vou expô-la é extrair uma classe do meu System Under Test original.

Antecipo ser capaz de fazer isso sem precisar alterar nenhum código de teste, mas quando terminar, você poderá argumentar que o teste não é mais um teste de unidade . Ele estará testando a classe original e a classe que eu extraí. Em outras palavras, terei um caso de teste, mas dois sistemas em teste.

Devo refatorar meu código de teste depois que terminar? IE: Crie um ExtractedClassTest e mova todos os testes relevantes do OriginalClassTest para ele? Parece que pode ser um pouco arriscado: posso perder alguma cobertura no processo, pode não ser tão simples quanto mover um teste e acabaria reescrevendo algum código de teste que sei que costumava funcionar, mas que pode não ser mais, etc.

Por outro lado, se eu deixar o OriginalClassTest como está, posso ver que isso é um problema de manutenção de teste. Vai ser um pouco confuso descobrir onde estão os testes da ExtractedClass. Sua primeira impressão será que ela não existe. Com o tempo, com muitas refatorações de códigos de produção, isso pode se tornar um problema sério.

Eu sou novo no TDD, então gostaria de um conselho de um especialista. Obrigado!

Daniel Kaplan
fonte

Respostas:

7

Depois de assistir a essa incrível conversa "Ian Cooper: TDD, onde tudo deu errado", vou discordar do @pdr. Eu acho que você deve apenas manter os testes originais. Sua capacidade de refatorar seu sistema em teste sem interromper, escrever ou alterar nenhum teste é o objetivo de escrever testes em primeiro lugar.

Se eu testasse a classe extraída, testaria a implementação e não o comportamento. Como resultado, seria mais difícil refatorar meu código no futuro: esses novos testes provavelmente falhariam mesmo se o comportamento ainda funcionasse.

Daniel Kaplan
fonte
6

Durante a duração do desenvolvimento, tenha ambos. Mantenha os testes antigos como garantia de que você não quebrou nada, escreva novos testes (do zero) para ajudá-lo a projetar as classes como deveriam.

No final, execute e remova qualquer coisa que esteja extinta nos testes antigos. Tenha cuidado nesta análise; não remova algo porque você acha que deveria estar extinto. Demonstre para si mesmo (ou outra pessoa ou um pato de borracha) por que não é mais necessário. Interrompa o teste e verifique se outro teste o interrompe.

Tudo o que resta nos testes antigos deve ser feito caso a caso, mas principalmente deve ser reescrito na nova estrutura.

Como você está certo, não quer ficar com um pesadelo de manutenção. Mas você não quer menos cobertura do caminho do que antes.

pdr
fonte
1
Acabei de fazer isso e tenho que dizer que é bastante desmotivador. Embora minhas alterações tenham sido diretas, demorou cerca de duas horas para garantir que eu refatorasse meus testes corretamente e ainda tivesse a mesma cobertura. Tornou-se óbvio que eu deveria adicionar alguns testes extras ao novo teste apenas para ter certeza de que estava verificando as coisas. Eu acho que teria sido mais eficiente extrair a classe e deixar dois sistemas em teste. Essa quantidade de trabalho sugere que eu escrevi mal os testes?
Daniel Kaplan
1
@tieTYT: Difícil responder isso sem ficar sentado olhando para você. Às vezes, o TDD parece mais trabalho do que vale a pena. Outras vezes, você é lembrado por que se incomodou. E outras vezes, é você que está dificultando. Aprender a dizer a diferença é uma grande parte de melhorar o TDD.
Pd
Você acha que é possível que, nesse caso, eu não deva ter refatorado meus testes ou que isso seja improvável?
Daniel Kaplan
1
@tieTYT: Improvável, sim. Impossível, não.
pdr