ti-enxame.com

Como você mantém seus testes funcionando de forma eficiente durante o redesenho?

Uma base de código bem testada tem vários benefícios, mas o teste de certos aspectos do sistema resulta em uma base de código que é resistente a alguns tipos de mudança.

Um exemplo é o teste de saída específica - por exemplo, texto ou HTML. Os testes são freqüentemente (ingenuamente?) Escritos para esperar um determinado bloco de texto como saída para alguns parâmetros de entrada ou para pesquisar seções específicas em um bloco.

Mudar o comportamento do código, para atender a novos requisitos ou porque o teste de usabilidade resultou em mudança na interface, requer a mudança dos testes também - talvez até testes que não são especificamente testes de unidade para o código que está sendo alterado.

  • Como você gerencia o trabalho de localizar e reescrever esses testes? E se você não puder simplesmente "executá-los e deixar que a estrutura os resolva"?

  • Que outros tipos de código sob teste resultam em testes habitualmente frágeis?

15
Alex Feinman

Eu sei que o pessoal do TDD vai odiar essa resposta, mas uma grande parte para mim é escolher cuidadosamente onde testar algo.

Se eu enlouquecer demais com os testes de unidade nas camadas inferiores, nenhuma mudança significativa pode ser feita sem alterar os testes de unidade. Se a interface nunca for exposta e não se destina a ser reutilizada fora do aplicativo, isso é apenas uma sobrecarga desnecessária para o que poderia ter sido uma mudança rápida.

Por outro lado, se o que você está tentando mudar for exposto ou reutilizado, cada um desses testes que você vai ter que mudar é evidência de algo que você pode estar quebrando em outro lugar.

Em alguns projetos, isso pode significar projetar seus testes da camada de aceitação para baixo, em vez de dos testes de unidade para cima. e ter menos testes de unidade e mais testes de estilo de integração.

Isso não significa que você ainda não possa identificar um único recurso e código até que esse recurso atenda aos critérios de aceitação. Significa simplesmente que, em alguns casos, você acaba não medindo os critérios de aceitação com testes de unidade.

10
Bill

Acabei de completar uma grande revisão da minha pilha SIP, reescrevendo todo o transporte TCP. a maioria das refatorações.)

Em resumo, há um TIdSipTcpTransport, subclasse de TIdSipTransport. Todos os TIdSipTransports compartilham um conjunto de testes comum. Interno ao TIdSipTcpTransport havia várias classes - um mapa contendo pares de conexão/mensagem de inicialização, threaded TCP, um servidor threaded TCP server, e assim por diante).

Aqui está o que eu fiz:

  • Excluí as aulas que iria substituir.
  • Excluídos os conjuntos de testes para essas classes.
  • Esquerda o conjunto de testes específico para TIdSipTcpTransport (e ainda havia o conjunto de testes comum para todos os TIdSipTransports).
  • Executou os testes TIdSipTransport/TIdSipTcpTransport, para certificar-se de que todos falharam.
  • Todos os testes comentados, exceto um TIdSipTransport/TIdSipTcpTransport.
  • Se eu precisasse adicionar uma classe, eu adicionaria testes de escrita para construir funcionalidade suficiente para que o único teste não comentado passasse.
  • Ensaboe, enxágue e repita.

Assim, eu sabia o que ainda precisava fazer, na forma de testes comentados (*), e sabia que o novo código estava funcionando conforme o esperado, graças aos novos testes que escrevi.

(*) Realmente, você não precisa comentá-los. Apenas não os execute; 100 testes reprovados não são muito encorajadores. Além disso, em minha configuração específica, compilar menos testes significa um loop teste-gravação-refatoração mais rápido.

4
Frank Shearar

Quando os testes são frágeis, geralmente acho que é porque estou testando a coisa errada. Considere, por exemplo, a saída HTML. Se você verificar a saída HTML real, seu teste será frágil. Mas você não está interessado na saída real, está interessado em saber se ela transmite as informações que deveria. Infelizmente, fazer isso requer fazer afirmações sobre o conteúdo do cérebro do usuário e, portanto, não pode ser feito automaticamente.

Você pode:

  • Gere o HTML como um teste de fumaça para se certificar de que ele realmente roda
  • Use um sistema de modelo, para que você possa testar o processador do modelo e os dados enviados ao modelo, sem realmente testar o modelo exato em si.

O mesmo tipo de coisa acontece com o SQL. Se você declarar o SQL real que suas classes tentam fazer, você terá problemas. Você realmente deseja afirmar os resultados. Portanto, uso um banco de dados de memória SQLITE durante meus testes de unidade para ter certeza de que meu SQL realmente faz o que deveria.

3
Winston Ewert