È utile per i metodi di unit test in cui l'unica logica sono le guardie?


12

Di 'che ho un metodo come questo:

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

Ho diversi di questi metodi nel mio codice (la metà anteriore di una chiamata asincrona al servizio Web).

Sto discutendo se è utile coprirli con i test unitari. Sì, qui c'è la logica, ma è solo la logica di guardia. (Il che significa che mi assicuro di avere le cose di cui ho bisogno prima di consentire la chiamata al servizio web.)

Una parte di me dice "sicuro che puoi testarli, ma non vale la pena" (sono su un progetto che è già in ritardo).

Ma l'altro lato di me dice che se non li collaudi e qualcuno cambia le Guardie, allora potrebbero esserci dei problemi.

Ma la prima parte di me risponde: se qualcuno cambia le guardie, allora stai solo facendo più lavoro per loro (perché ora devono cambiare le guardie e i test delle unità per le guardie).

Ad esempio, se il mio servizio si assume la responsabilità di verificare la disponibilità del Widget, potrei non volere più quella protezione. Se è in unit test, ora devo cambiare due posizioni.

Vedo pro e contro in entrambi i modi. Quindi ho pensato di chiedere cosa hanno fatto gli altri.


17
Non stai facendo "più lavoro" per i manutentori. Se cambiano logica, devono cambiare i test unitari corrispondenti. Funziona così. Non vedo i tuoi contro: se il tuo test unitario non dovesse essere modificato, allora non testerebbe nulla, vero? Potresti anche chiederti se il test unitario è utile.
Andres F.

9
Questo è fuori tema, ma cambierei la logica per generare un'eccezione se il numero di parte è 0 o inferiore, o se la parte non è disponibile, poiché a mio avviso sarebbe un bug consentire a qualcuno di chiamare quel metodo con un widget fasullo, mascherando silenziosamente un altro problema.
Matteo,

2
@Matthew ottimo punto. Questa funzione risiede. La denominazione ti dice che ordinerà qualcosa. E poi non lo farà, ma non lo saprai mai, a meno che non applichi la stessa logica che è dentro, che contiene SECCO. In altre parole: se il design fosse cambiato per essere più corretto, questa domanda forse non sarebbe stata posta in primo luogo.
stijn

2
but it is not worth the time" (I am on a project that is already behind schedule).Siamo sviluppatori di software. L'unica volta che siamo in programma è quando siamo morti :)
maple_shaft

Risposte:


26

Una parte di me dice "sicuro che puoi testarli, ma non vale la pena" (sono su un progetto che è già in ritardo).

Sono tre test molto brevi. Hai passato tutto il tempo a porsi la domanda.

Ma l'altro lato di me dice che se non li collaudi e qualcuno cambia le Guardie, allora potrebbero esserci dei problemi.

Ascolta questo lato.

Ma la prima parte di me risponde: se qualcuno cambia le guardie, allora stai solo facendo più lavoro per loro (perché ora devono cambiare le guardie e i test delle unità per le guardie).

Se il tuo manutentore è un dado TDD, lo stai rendendo più difficile per loro. Qualsiasi modifica apportata senza che vi sia una modifica correlata o un'aggiunta di test mi porta a pensare intensamente. In effetti, probabilmente aggiungerei i test prima di procedere e apportare la modifica.

La prima parte di te è semplicemente sbagliata. Dai una pacca sulla seconda parte e smetti di pensarci.


+1 per la sintonia anche se ho scritto anche una risposta heh
Jimmy Hoffa,

3
+1. Sì, se i requisiti cambiano, alcuni test dovranno essere adattati.
Olivier Jacot-Descombes,

Mentre mi piace quello che dici, ho molte istanze di questo tipo di chiamata nel mio codice (la metà anteriore di una chiamata asincrona). Quindi non si tratta solo di 3 test unitari. Tuttavia, se è il modo "giusto", allora voglio farlo.
Vaccano,

@Vaccano: più devi scrivere, più percorsi logici non hai test e più è necessario scriverli.
pdr,

9

Semplificherebbe i test unitari se la logica di guardia e l'ordinamento effettivo fossero metodi separati.

In Widgetclasse

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

o un metodo equivalente da qualche altra parte

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

Il metodo dell'ordine

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

Ora i test sono IsWidgetReadyForOrderingdiventati facili. Non pensarci più a lungo. Provalo!


1
Oof, logica stateful in una proprietà .. -1 che dovrebbe essere un metodo e dovrebbe prendere PartNumber, PartAvailable per la sua semplicità. Renderlo protetto se non è necessario che faccia parte dell'API pubblica ma non sia una proprietà. Inoltre, in genere non sono d'accordo. La logica di guardia all'interno del metodo va benissimo, e ai miei occhi meglio perché è un metodo così piccolo che stai semplicemente inquinando la classe per ridurre un metodo già piccolo. Aggiungilo alla classe in questo caso solo se è una logica ripetitiva.
Jimmy Hoffa,

1
Innanzitutto, questo non risponde alla domanda. Secondo, non è vero. È necessario scrivere tre test in entrambi i modi. In terzo luogo, espone inutilmente i dettagli di implementazione al codice chiamante.
pdr,

8
@JimmyHoffa: dove vedi qualche logica stateful in quella proprietà? In effetti, l'esempio mostra come separare la logica che cambia lo stato (OrderNewWidget) dalla logica non statechanging (ReadyForOrdering). E sono fermamente convinto che l'estrazione anche di quelle piccole funzioni migliorerà il codice e non lo peggiorerà, come dici. Quindi +1.
Doc Brown,

2
Il metodo OrderNewWidgetè probabilmente in un'altra classe rispetto a Widget, poiché ha un Widgetargomento. Poiché il metodo non ha alcun valore di ritorno, il test non è ovvio. Dovresti iniettare un WigdetOrderingService-mock che tiene traccia della OrderNewWidgetAsyncchiamata.
Olivier Jacot-Descombes,

2
@JimmyHoffa: in realtà, la tua definizione di "stateless" significa "statico" in C #. Pertanto, ciò che dici è "le proprietà non devono accedere allo stato di un oggetto". Ma anche i getter stupidi accedono alle variabili di stato, quindi ciò significherebbe "scrivere solo proprietà statiche", il che sembra non avere molto senso.
Doc Brown,

6

Se non hai tempo nel tuo programma per i test unitari ma hai tempo da dedicare al solido utilizzo del QA, chiedi se puoi rubare un po 'di quel tempo QA per scrivere test unitari o se puoi trascorrere un po' del periodo di QA fare test unitari, o forse semplicemente occuparsi di codice non unit test. Sfortunatamente programmi che sono inamovibili ti costringono a fare concessioni o a lavorare fino alla morte, generalmente ti suggerisco la prima opzione perché la seconda ti renderà incapace di supportare / mantenere il sistema correttamente per il periodo di validità.

Detto questo, alla tua domanda generale di test delle dichiarazioni di guardia; Sì! Assolutamente test delle dichiarazioni di guardia! Quelle sono parti importanti del comportamento di quel metodo, non vorresti scoprire che qualcuno ha frainteso qualcosa facendo una correzione di bug e ha rimosso le tue guardie o cambiato &&in un ||vero? I test unitari garantiranno che a) la logica sulle tue guardie sia effettivamente corretta eb) nessuno la rompa successivamente in seguito senza ricevere un reclamo quando eseguono i test unitari dicendo loro che dovrebbe essere così per qualche motivo.


0

Ci sono alcune risposte eccellenti sopra e i punti che fanno sono molto importanti. Ma quello che sembra essersi perso è che tu abbia una serie completa di test unitari, che leggono come una specifica estremamente dettagliata del codice. Se si omette il test di convalida solo perché il codice è così semplice, è difficile vedere come potrebbe andare storto, manca parte delle specifiche. Se fossi entrato in un team in cui questi test erano andati persi, avrei effettivamente supposto che il tuo servizio non stesse convalidando i suoi argomenti.


-5

Il codice è codice. Dovresti provare a ottenere una copertura del 100% durante i test. Se non fosse importante non sarebbe lì.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.