Existe algum valor em escrever testes de unidade para o código que já funciona ao herdar aplicativos?

27

Obviamente, alguns aplicativos antigos não podem ser ou são extremamente difíceis de serem testados por causa da maneira como foram escritos.

Mas em alguns lugares, como alguns métodos auxiliares que provavelmente poderiam ser testados em unidade, devo me preocupar em escrever testes de unidade para eles?

Quero dizer, eles poderiam ser escritos como um cachorro, mas, por mais complexa que seja a lógica, o teste do tempo provou que funciona da maneira que deveria. Deveria me preocupar apenas em fazer testes de unidade se, por exemplo, refizer isso ou devo escrever testes de unidade para eles sempre que tiver tempo?

Existe algum valor em fazer isso?

Leve em consideração também que a definição do método pode ser vaga, e talvez eu precise pesquisar o que alguns dos métodos realmente devem fazer em determinadas condições.

RoboShop
fonte
4
Faça um favor a si mesmo e leia Trabalhando Efetivamente com o Código Legado . If é um livro inteiro dedicado a responder a esta e outras questões relacionadas.
9789 Reinholdichichs

Respostas:

15

Eu acho que você certamente deve escrever o maior número possível de testes para o aplicativo. Eles ajudarão você a aprender a base de código e a prepará-lo para a eventual refatoração ou novo desenvolvimento.

Existem alguns tipos de testes que você pode escrever nesse cenário, cada um deles com seus próprios méritos. Escrever esses testes ensinará muito sobre o aplicativo com o qual você está lidando.

Antes de tudo, antes de você começar a escrever testes de correção, escreva testes que capturem o comportamento atual , seja ele certo ou errado. É uma aposta bastante segura que você descubra bugs em casos de canto ou em partes do código que não foram completamente testadas ao executar o programa. Não se preocupe com o que o código deve fazer, apenas capture o que ele faz. À medida que prosseguir, não se preocupe em ler o código ou em gastar muito tempo tentando descobrir qual deve ser a saída. Basta executar seu teste e capturar essa saída em uma afirmação.

Isso fornecerá uma sólida base de entendimento de como o código opera e onde estão os principais pontos problemáticos ou áreas fracas. Se você descobrir bugs, poderá abordar pessoas com o poder de decidir se vale a pena consertar ou não e tomar essas decisões.

Em seguida, você pode escrever alguns testes maiores (no escopo) que cobrem partes do código que podem não ser facilmente testáveis ​​por unidade, mas onde ainda seria importante testar o máximo possível os fluxos de trabalho. Esses testes de fluxo de trabalho ou testes de integração , dependendo de como você deseja vê-los, fornecerão uma boa base para refatorar esses fluxos de trabalho, para torná-los mais testáveis ​​e protegê-lo quando for necessário adicionar um novo recurso que possa afetar um fluxo de trabalho existente.

Com o tempo, você criará um conjunto de testes para ajudar você ou a próxima pessoa que acabar herdando o aplicativo.

Adam Lear
fonte
13

Eu vejo testes de unidade como especificações, não meros testes. No caso específico que você mencionou, o valor real virá quando você tiver um teste de unidade antes de fazer qualquer alteração para se adequar às novas especificações. Se você deseja alterar o código herdado, a melhor maneira que vejo é fazer testes de unidade para a funcionalidade, isso não apenas trará uma rede de segurança, mas também nos ajudará a fornecer mais clareza sobre o que essa unidade específica faz. Também pode forçá-lo a fazer algumas pesquisas, conforme mencionado por você, o que é bom para o entendimento. Portanto, minha opinião é realizar um teste de unidade do módulo antes que ele esteja prestes a sofrer uma alteração.

Vinod R
fonte
Escreva os testes no idioma de nível mais alto que funcionará. Quando solicitado a estimar o tempo para fazer uma alteração, inclua o tempo necessário para escrever os testes ausentes. Você pode levar mais tempo para fazer a alteração, mas você colocará muito menos erros no campo.
kevin Cline
8
 > Is there any value in writing unit tests for code that 
 > already works when inheriting applications?

NÃO . Pela minha experiência, existe uma relação custo / benefício ruim para escrever testes de unidade depois que o código de produção foi gravado, porque é muito improvável / difícil encontrar maneiras de testar o código isoladamente sem refatoração pesada. Um dos benefícios do desenvolvimento orientado a testes é que você obtém código pouco acoplado. Se você escrever os testes depois, as chances são altas de que o código esteja firmemente acoplado.

SIM, você pode escrever testes de integração para o aplicativo para as funções nas quais planeja fazer alterações. Dessa forma, você pode fazer um teste de regressão para ver se suas alterações quebram alguma coisa.

SIM, do ponto de vista da qualidade e do desenvolvedor, é valioso ter testes.

NÃO do ponto de vista comercial, porque é muito difícil vender ao cliente que você precisa de tempo / dinheiro para não obter valor comercial real, mas a vaga promessa de que as mudanças nos negócios não piorarão as coisas.

k3b
fonte
+1 para testes de integração em vez de teste de unidade para este caso. Conselho muito pragmático
gbjbaanb
5

Se possível, há ainda mais motivos para escrever testes para o código existente que "já funciona". Se não houver testes, é provável que o código esteja repleto de cheiros e poderia ser usada uma refatoração extensiva para ser aprimorada; o conjunto de testes ajudará você a refatorar. Pode até revelar que o código original não funciona corretamente; Lembro-me de uma vez que escrevi um teste para um método que gerava um relatório de vendas e descobri que não estava calculando as coisas corretamente, de modo que as vendas eram alguns milhares de dólares a mais do que realmente eram, e ninguém sabia nos cinco anos que o código estava em produção (felizmente, não era o fim financeiro real, apenas uma estimativa do relatório de vendas).

Obviamente, esse conselho só se aplica se você puder escrever os testes. Na minha experiência, uma base de código sem testes é quase impossível de adaptar os testes, porque você teria que reescrever metade dos módulos de código para ser abstrato o suficiente para dar suporte aos testes primeiro, e você não poderá fazer isso.

Wayne Molina
fonte
Por que um voto negativo por afirmar a verdade?
Wayne Molina
4

Absolutamente sim , porque os testes de unidade não devem verificar a exatidão, mas caracterizar o comportamento real do sistema. Especialmente em um projeto legado, muitos dos requisitos são implicitamente codificados no comportamento real.

Essa caracterização serve como uma linha de base da funcionalidade. Mesmo que o comportamento esteja incorreto do ponto de vista comercial, você impede que o comportamento se agrave ainda mais. Obter tração em um projeto herdado pode ser difícil, e isso fornece uma linha de base para que você possa avançar sem piorar as coisas.

Então, escreva todos os testes de unidade que puder. Para código que não pode ser testado, refatorar seu código para separar dependências introduzindo "costuras" no código - locais onde você pode separar o código que deseja testar do código que não deseja testar.

As idéias de testes de unidade como testes de caracterização e costuras são pontos principais em Trabalhando efetivamente com o código herdado de Michael Feathers, um livro que eu recomendo.

Matthew Rodatus
fonte
2

Eu mesmo ponderei sobre isso, pois há um monte de documentos legivelmente mal documentados, mas sem documentos, mas funcionando em nosso sistema legado.

Você faz uma boa observação:

Deveria me preocupar apenas em fazer testes de unidade se, por exemplo, refizer isso ou devo escrever testes de unidade para eles sempre que tiver tempo?

Se os requisitos mudarem, acho que seria mais valioso escrever os testes de unidade. Caso contrário, eu não me incomodaria, especialmente porque você não seria capaz de escrever testes adequados, porque você não conhece todas as condições.

sempre que tenho tempo?

Você tem tempo para priorizar, certo ?, portanto nunca acontecerá. :)

Michael
fonte
1

Você está tentando aproveitar aspectos dessa base de código que não foram usados ​​anteriormente em um aplicativo de produção? Escreva testes de unidade para esses cenários primeiro. Você precisa priorizar seu trabalho aqui, e acho que a The Art of Unit Testing teve alguns conselhos a esse respeito (em particular, como abordar o teste de bases de código herdadas).

Justin Simon
fonte
1

Não assuma que tudo está funcionando apenas porque o aplicativo está em execução ... normalmente, o "teste do tempo" mostra apenas que: a) você ainda não encontrou o resto dos defeitos; ou b) as pessoas que encontraram eles não os denunciaram. (Ou talvez os dois.) E mesmo o código que provavelmente está funcionando agora pode não funcionar da próxima vez que você precisar fazer uma alteração.

Os testes de unidade fornecem uma certa certeza de que determinada funcionalidade permanece intacta, além de fornecer uma maneira de demonstrar isso para uma quantidade razoável de casos. Isso é significativamente mais valioso do que "bisbilhotar e testar isso", mesmo para uma única correção de bug. Como bisbilhotar é mais parecido com o equivalente à integração ou aos testes do sistema, portanto, nesse sentido, o teste manual do aplicativo pode cobrir mais do que os testes de unidade, mas ainda assim o tempo é gasto de maneira ineficiente. Até mesmo algum método de automatizar esses testes é melhor do que fazê-las manualmente.)

Definitivamente, você deve escrever testes ao alterar o código, seja corrigindo ou refatorando. Você pode fazer o melhor para escrever testes, se não por outro motivo, a menos que economize algum tempo na próxima vez que precisar corrigir um defeito (e haverá uma próxima vez) ... embora, nesse caso, você é preciso equilibrar esse tempo com as expectativas de pessoas que fingem que o software está sempre livre de defeitos e, portanto, o tempo gasto em manutenção futura é "desperdiçado". (Porém, isso não significa que você deva ignorar os agendamentos atuais.) Em algum momento, se você fizer isso, terá cobertura suficiente para começar a demonstrar o valor dos testes em aplicativos herdados e que poderá ajudá-lo a gastar esse tempo em aplicativos futuros, o que deve liberar tempo para o desenvolvimento produtivo.

Dave DuPlantis
fonte
0

Do meu coração lala-land, direi que sim e não apenas isso, mas corte-o, refatore-o e continue testando, mas certifique-se de não ficar para trás em outros projetos importantes. Como programador ativo, se seu trabalho estiver em risco ou se um gerente lhe disser para se apropriar, então sim. Se a equipe ou a empresa sofrerem, negocie com seu gerente para que ele saiba que é necessário fazer testes para evitar que a empresa desastre. Se ele disser não se preocupe, você está fora do gancho (não necessariamente, delegar a culpa é uma habilidade de gerenciamento, portanto, verifique se você está fora do gancho ... realmente!)

Boa sorte!

Armando
fonte