2010-03-06 11 views
8

classe Esempio in pseudocodice:come testare o descrivere infinite possibilità?

class SumCalculator 
    method calculate(int1, int2) returns int 

cosa è un buon modo per verificare questo? In altre parole, come dovrei descrivere il comportamento di cui ho bisogno?

test1: canDetermineSumOfTwoIntegers 

o

test2: returnsSumOfTwoIntegers 

o

test3: knowsFivePlusThreeIsEight 

Test1 e Test2 sembrano vaghe e sarebbe bisogno di testare un calcolo specifico, in modo che in realtà non descrivere ciò che sta in fase di test. Eppure test3 è molto limitato.

Qual è un buon modo per testare tali classi?

risposta

10

ho iniziato ad esaminare le condizioni al contorno (max-Int, min-INT, zero, positivo, negativo) e alcuni casi tipici:

test1: sumOfPosAndPos 
test2: sumOfPosAndNeg 
test3: sumOfPosAndZero 
test4: sumOfNegAndZero 
test5: sumOfMaxIntAndMinInt 

ecc

+1

Forse aggiungere sumOfMaxIntAndMaxInt e verificare che la funzione riporti l'errore. Questo è il caso limite che posso pensare. – pmr

+0

sumOfMaxIntAndOne dovrebbe causare anche un'eccezione, non dovrebbe? Sarebbe un altro buon caso. Altrimenti sono d'accordo. Basti pensare a un paio di possibilità che differiscono leggermente e andare con quello. –

+1

Non dimenticare i test case negativi test6: sumOfStringAndPositive (dovrebbe generare un'eccezione o un errore di ritorno) –

5

Ci sono diverse filosofie. Roy Osherove, autore di The Art of Unit Testing, sembra prefer using explicit values e seleziona la rappresentazione più bassa (o più semplice) di ogni Equivalence Class.

Questo principio non si applica particolarmente bene al tuo esempio, ma funziona molto bene in molti altri scenari.

Se, ad esempio, una classe richiede un input di un numero intero positivo, si seleziona il numero perché è la rappresentazione più semplice di tutti gli interger positivi.

Personalmente preferisco piuttosto un principio che chiamo Constrained Non-Determinism. Il punto qui è che lasciamo che qualche tipo di fabbrica ci serva variabili anonime per il tipo dato, perché ci obbliga a stabilire la relazione direttamente nel test.

sto usando AutoFixture per fare questo (ma si potrebbe anche usare qualcos'altro), quindi in questo caso ho iniziato ad esaminare il SumCalculator in questo modo:

var fixture = new Fixture(); 
var int1 = fixture.CreateAnonymous<int>(); 
var int2 = fixture.CreateAnonymous<int>(); 
var expectedResult = int1 + int2; 
var sut = fixture.CreateAnonymous<SumCalculator>(); 

var result = sut.Calculate(int1, int2); 

Assert.AreEqual(expectedResult, result); 

In linea di principio, questo singolo test fornisce un specifica per il metodo Calculate. Non sappiamo mai quali siano i valori di int1 e int2, e questo è molto appropriato in tutti quei molti casi in cui in realtà non ha importanza.

3

se stai testando la funzione matematica, ti suggerirei di testarlo contro la sua funzione inversa, ad esempio: per la funzione che fa x = a + b, dovresti testarlo se ax = -b e xb = a , questo è solo per illustrazione, naturalmente non funzionerà su tutti i casi.

1

Un'altra alternativa potrebbe essere quella di utilizzare un Parameterized Test Case per rimuovere la duplicazione nei test.Fondamentalmente una tabella contiene tutti i dati per i test, in una forma tupla ([term1, term2, sum]), quindi un testcase itera sulla tabella per richiamare il testcase parametrizzato per testare una riga nella tabella:

I aggiungerebbe anche il test negativo (overflow qui): cosa si suppone che debba restituire calculate(MAXINT, 1)?

1

Vedere il lavoro di David Saff su Theory Tests; here (PDF) è un esempio. Questo è fondamentalmente un modo per affermare che qualcosa (come una funzione che è l'inverso della sua funzione) è vero per tutti i valori in alcuni set (incluso l'insieme di tutti i possibili valori) - ed esprime quell'asserzione come un test. Puoi eseguire alcune cose divertenti eseguendo il test con valori selezionati casualmente (se il set è troppo grande per essere eseguito in modo esauriente) e registrando automaticamente i guasti come test concreti specifici di regressione.