É útil para métodos de teste de unidade em que a única lógica é a proteção?

12

Digamos que eu tenha um método como este:

public void OrderNewWidget(Widget widget)
{
   if ((widget.PartNumber > 0) && (widget.PartAvailable))
   {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

Eu tenho vários métodos desse tipo no meu código (a metade frontal de uma chamada de serviço da Web assíncrona).

Estou discutindo se é útil cobri-los com testes de unidade. Sim, há lógica aqui, mas é apenas lógica de guarda. (Isso significa que garanto que tenho o material necessário antes de permitir a chamada do serviço web.)

Parte de mim diz "com certeza você pode testá-los à unidade, mas não vale o tempo" (estou em um projeto que já está atrasado).

Mas o outro lado diz: se você não testá-los, e alguém trocar os guardas, pode haver problemas.

Mas a primeira parte de mim responde: se alguém muda os guardas, então você está trabalhando mais para eles (porque agora eles precisam mudar os guardas e os testes de unidade dos guardas).

Por exemplo, se meu serviço assumir a responsabilidade de verificar a disponibilidade do Widget, talvez eu não queira mais essa proteção. Se estiver em teste de unidade, tenho que mudar dois lugares agora.

Eu vejo prós e contras nos dois sentidos. Então, pensei em perguntar o que os outros fizeram.

Vaccano
fonte
17
Você não está fazendo "mais trabalho" para os mantenedores. Se eles mudarem de lógica, deverão alterar os testes de unidade correspondentes. É assim que funciona. Não vejo seus contras: se seu teste de unidade não exigisse alterações, não estaria testando nada, precisaria? Você também pode questionar se o teste de unidade é útil.
Andrés F.
9
Isso está fora do tópico, mas eu mudaria a lógica para gerar uma exceção se o número da peça for 0 ou menos ou se a peça não estiver disponível, pois, na minha opinião, seria um erro permitir que alguém chame esse método com um widget falso, mascarando silenciosamente outro problema.
Matthew
2
@ Matthew ponto muito bom. Esta função está. A nomeação diz que vai pedir alguma coisa. E então não, mas você nunca saberá, a menos que aplique a mesma lógica existente, o que viola o DRY. Em outras palavras: se o design for alterado para ser mais correto, talvez essa pergunta não tenha sido feita em primeiro lugar.
Stijn
2
but it is not worth the time" (I am on a project that is already behind schedule).Somos desenvolvedores de software. A única vez que estão dentro do cronograma é quando estamos mortos :)
maple_shaft

Respostas:

26

Parte de mim diz "com certeza você pode testá-los à unidade, mas não vale o tempo" (estou em um projeto que já está atrasado).

São três testes muito curtos. Você passou tanto tempo se perguntando a pergunta.

Mas o outro lado diz: se você não testá-los, e alguém trocar os guardas, pode haver problemas.

Escute este lado.

Mas a primeira parte de mim responde: se alguém muda os guardas, então você está trabalhando mais para eles (porque agora eles precisam mudar os guardas e os testes de unidade dos guardas).

Se o seu mantenedor é uma porca TDD, você está tornando mais difícil para eles. Qualquer alteração que eu faça sem que haja uma alteração relacionada ou a adição de testes leva a que eu tenha que pensar muito. Na verdade, eu provavelmente adicionaria os testes antes de prosseguir e fazer a alteração.

A primeira parte de você está completamente errada. Dê um tapinha nas costas na segunda parte e pare de pensar nisso.

pdr
fonte
+1 para concisão, embora eu escrevi uma resposta muito heh
Jimmy Hoffa
3
+1. Sim, se os requisitos mudarem, alguns testes terão que ser adaptados.
Olivier Jacot-Descombes
Enquanto eu gosto do que você diz, tenho muitas instâncias desse tipo de chamada no meu código (a metade frontal de uma chamada assíncrona). Portanto, não são apenas três testes de unidade. Ainda assim, se é o caminho "certo", quero fazê-los.
Vaccano 28/11/2012
@ Vulcão: Quanto mais você precisar escrever, mais caminhos lógicos você não terá testes e mais necessário será escrevê-los.
Pd28
9

Simplificaria o teste de unidade se a lógica de guarda e a ordem real fossem métodos separados.

Na Widgetaula

public bool IsReadyForOrdering { get { return PartNumber > 0 && PartAvailable; } }

ou um método equivalente em outro lugar

public bool IsWidgetReadyForOrdering(Widget widget)
{
    return widget.PartNumber > 0 && widget.PartAvailable;
}

O método de pedido

public void OrderNewWidget(Widget widget)
{
   if (IsWidgetReadyForOrdering(widget)) {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

Agora os testes IsWidgetReadyForOrderingse tornaram fáceis. Não pense muito sobre isso. Teste-o!

Olivier Jacot-Descombes
fonte
1
Oof, lógica com estado em uma propriedade .. -1 que deve ser um método e deve levar o PartNumber, PartAvailable devido à sua simplicidade. Torne-o protegido se não precisar fazer parte da API pública, mas não uma propriedade. Também discordo em geral. A lógica de guarda dentro do método é totalmente boa e, aos meus olhos, melhor porque é um método tão pequeno que você está poluindo a classe para tornar um método já pequeno menor. Adicione-o à classe neste caso apenas se for uma lógica repetitiva.
Jimmy Hoffa
1
Primeiro, isso não responde à pergunta. Segundo, é falso. Você precisa escrever três testes de qualquer maneira. Terceiro, expõe detalhes da implementação à chamada de código desnecessariamente.
Pd28
8
@ JimmyHoffa: onde você vê alguma lógica estável nessa propriedade? De fato, o exemplo mostra como separar a lógica de alteração de estado (OrderNewWidget) da lógica sem alteração de estado (ReadyForOrdering). E acredito firmemente que extrair até essas pequenas funções melhorará o código, e não o tornará pior, como você afirma. Então, +1.
Doc Brown
2
O método OrderNewWidgetprovavelmente está em outra classe que Widget, uma vez que possui um Widgetargumento. Como o método não tem valor de retorno, testá-lo não é óbvio. Você teria que injetar uma WigdetOrderingServicezombaria que rastreia a OrderNewWidgetAsyncchamada.
Olivier Jacot-Descombes
2
@ JimmyHoffa: na verdade, sua definição de "sem estado" significa "estática" em C #. Portanto, o que você diz é "propriedades não devem acessar o estado de um objeto". Mas mesmo getters burros acessam variáveis ​​de estado, o que significa "escrever apenas propriedades estáticas" - o que não parece fazer muito sentido.
Doc Brown
6

Se você não tiver tempo na sua programação para testes de unidade, mas tiver tempo reservado para um uso sólido do controle de qualidade, pergunte se você pode roubar parte desse tempo de controle de qualidade para escrever testes de unidade ou se pode passar parte do período de controle de qualidade fazendo testes de unidade, ou talvez apenas lide com código que não seja de unidade. Infelizmente, os agendamentos que são imóveis obrigam você a fazer concessões ou trabalhar até a morte, geralmente sugiro a primeira opção, porque a segunda resultará em você incapaz de apoiar / manter o sistema corretamente pelo prazo.

Dito isto, à sua questão geral de testar as declarações de guarda; Sim! Absolutamente teste declarações de guarda! Essas são partes importantes do comportamento desse método; você não gostaria de descobrir que alguém não entendeu algo que fazia uma correção de bugs e removeu seus guardas ou mudou o &&para um ||? Os testes de unidade garantirão que: a) você realmente acertou a lógica em seus guardas eb) ninguém quebra essa lógica mais tarde sem receber uma queixa quando eles executam os testes de unidade, dizendo que deve ser assim por algum motivo.

Jimmy Hoffa
fonte
0

Há algumas excelentes respostas acima, e os pontos que eles colocam são muito importantes. Mas um que parece ter sido esquecido é que, se você tem um conjunto abrangente de testes de unidade, eles são lidos como uma especificação extremamente detalhada do código. Se você omitir a validação de teste apenas porque o código é tão fácil, é difícil ver como isso pode dar errado, parte de sua especificação está faltando. Se eu entrasse em uma equipe onde esses testes haviam sido perdidos, eu assumiria que seu serviço não estava validando seus argumentos.

Jules
fonte
-5

Código é código. Você deve tentar obter 100% de cobertura ao testar. Se não fosse importante, não estaria lá.

Superusuário
fonte