Recentemente, concluí uma refatoração de caixa preta. Não consigo fazer check-in, porque não consigo descobrir como testá-lo.
Em um nível alto, eu tenho uma classe cuja inicialização envolve capturar valores de alguma classe B. Se a classe B estiver "vazia", ela gera alguns padrões sensíveis. Eu extraí esta parte para um método que inicializa a classe B com os mesmos padrões.
Ainda tenho que descobrir o propósito / contexto de qualquer classe, ou como elas seriam usadas. Portanto, não consigo inicializar o objeto a partir de uma classe B vazia e verificar se ele tem os valores certos / faz a coisa certa.
Minha melhor idéia é executar o código original, codificar os resultados de métodos públicos, dependendo dos membros inicializados, e testar o novo código com relação a isso. Não sei bem por que me sinto vagamente desconfortável com essa ideia.
Existe um ataque melhor aqui?
fonte
Respostas:
Você está indo bem!
Criar testes de regressão automatizados geralmente é a melhor coisa que você pode fazer para tornar um componente refatorável. Pode ser surpreendente, mas esses testes geralmente podem ser escritos sem a compreensão completa do que o componente faz internamente, desde que você entenda as "interfaces" de entrada e saída (no significado geral dessa palavra). Fizemos isso várias vezes no passado para aplicativos legados completos, não apenas para classes, e isso frequentemente nos ajudou a evitar quebras que não entendíamos completamente.
No entanto, você deve ter dados de teste suficientes e garantir um entendimento firme do que o software faz do ponto de vista de um usuário desse componente; caso contrário, corre o risco de omitir casos de teste importantes.
É uma boa ideia IMHO implementar seus testes automatizados antes de iniciar a refatoração, e não depois, para que você possa fazer a refatoração em pequenas etapas e verificar cada etapa. A refatoração em si deve tornar o código mais legível, ajudando a aumentar a compreensão dos internos pouco a pouco. Portanto, as etapas do pedido nesse processo são
fonte
Um motivo importante para escrever testes de unidade é que eles documentam a API do componente de alguma forma. Não entender o objetivo do código em teste é realmente um problema aqui. A cobertura do código é outro objetivo importante, difícil de atingir sem saber quais ramificações de execução existem e como elas são acionadas.
No entanto, se for possível redefinir o estado de forma limpa (ou construir o novo objeto de teste toda vez), pode-se escrever um teste do tipo "lixeira para fora da lixeira" que apenas alimenta principalmente entrada aleatória no sistema e observa a saída.
Esses testes são difíceis de manter, pois quando falham, pode ser complexo dizer por que e quão sério é. A cobertura pode ser questionável. No entanto, eles ainda são muito melhores que nada. Quando esse teste falha, o desenvolvedor pode revisar as alterações mais recentes com mais atenção e, esperançosamente, identificar o bug.
fonte