No momento, estou refatorando parte de uma grande base de código sem nenhum teste de unidade. Tentei refatorar o código da maneira bruta, ou seja, tentando adivinhar o que o código está fazendo e quais mudanças não o mudariam, mas sem sucesso: ele quebra aleatoriamente os recursos em toda a base de código.
Observe que a refatoração inclui mover o código C # herdado para um estilo mais funcional (o código herdado não usa nenhum dos recursos do .NET Framework 3 e posterior, incluindo o LINQ), adicionando genéricos nos quais o código pode se beneficiar deles, etc.
Não posso usar métodos formais , considerando quanto eles custariam.
Por outro lado, presumo que pelo menos a regra "Qualquer código legado refatorado venha com testes de unidade" deve ser rigorosamente seguida, não importa quanto custaria. O problema é que, quando refatoro uma parte minúscula de um método privado 500 LOC, adicionar testes de unidade parece ser uma tarefa difícil.
O que pode me ajudar a saber quais testes de unidade são relevantes para um determinado pedaço de código? Suponho que a análise estática do código seja útil de alguma forma, mas quais são as ferramentas e técnicas que posso usar para:
Saiba exatamente quais testes de unidade devo criar,
E / ou sei se a alteração que fiz afetou o código original de uma maneira que está sendo executada de maneira diferente a partir de agora?
fonte
formal methods in software development
lo de qualquer maneira, porque é usado para provar a correção de um programa usando lógica de predicados e não teria aplicabilidade para refatorar uma grande base de código. Métodos formais normalmente usados para provar o código funcionam corretamente em áreas como aplicações médicas. Você está certo, é caro fazer, e é por isso que não é usado com frequência.Respostas:
Eu tive desafios semelhantes. O livro Trabalhando com Código Legado é um ótimo recurso, mas há uma suposição de que você pode usar a buzina em testes de unidade para apoiar seu trabalho. Às vezes isso simplesmente não é possível.
No meu trabalho de arqueologia (meu termo para manutenção em código legado como esse), sigo uma abordagem semelhante ao que você descreveu.
Nesse ponto, você deve ter uma lista de candidatos do que foi exposto e / ou manipulado por essa rotina. Algumas dessas manipulações provavelmente são inadvertidas. Agora eu uso
findstr
o IDE para entender quais outras áreas podem referenciar os itens na lista de candidatos. Passarei algum tempo entendendo como essas referências estão funcionando e qual é a sua natureza.Finalmente, depois de me iludir pensando que entendo os impactos da rotina original, farei minhas alterações uma por vez e executarei novamente as etapas de análise descritas acima para verificar se as alterações estão funcionando conforme o esperado para funcionar. Eu tento especificamente evitar alterar várias coisas ao mesmo tempo, pois descobri que isso explode quando tento verificar o impacto. Às vezes, você pode se safar de várias alterações, mas se eu puder seguir uma rota de cada vez, essa é a minha preferência.
Em resumo, minha abordagem é semelhante à que você expôs. É muito trabalho de preparação; depois faça mudanças individuais e cautelosas; e verifique, verifique, verifique.
fonte
Resposta curta: pequenos passos.
Considere estas etapas:
Mova a implementação para uma função diferente (privada) e delegue a chamada.
Adicione o código de registro (verifique se o registro não falha) em sua função original, para todas as entradas e saídas.
Execute seu aplicativo e faça o que puder com ele (uso válido, uso inválido, uso típico, uso atípico, etc.).
Agora você tem
max(call_count)
conjuntos de entradas e saídas para escrever seus testes; Você pode escrever um único teste que repete todos os seus parâmetros / conjuntos de resultados que você possui e os executa em um loop. Você também pode escrever um teste adicional que executa uma combinação específica (a ser usada para verificar rapidamente a passagem de um conjunto de E / S específico).Mover
// 500 LOC here
de volta para suaugly500loc
função (e remover a funcionalidade do log).Comece a extrair funções da grande função (não faça mais nada, apenas extraia funções) e execute testes. Após isso, você deverá ter mais poucas funções para refatorar, em vez da 500LOC.
Viva feliz para sempre.
fonte
Normalmente, os testes de unidade são o caminho a percorrer.
Faça os testes necessários que provam que a corrente funciona conforme o esperado. Não se apresse e o último teste deve deixá-lo confiante na saída.
Você está refatorando um pedaço de código, precisa saber exatamente o que ele faz e o que afeta. Então, basicamente, você precisa testar todas as zonas impactadas. Isso levará muito tempo ... mas esse é o resultado esperado de qualquer processo de refatoração.
Então você pode separar tudo sem problemas.
AFAIK, não existe uma técnica à prova de balas para isso ... você só precisa ser metódico (em qualquer método que se sinta confortável), muito tempo e muita paciência! :)
Felicidades e boa sorte!
Alex
fonte