2010-03-06 11 views
8

clase Ejemplo en pseudocódigo:cómo probar o describir un sinfín de posibilidades?

class SumCalculator 
    method calculate(int1, int2) returns int 

¿Qué es una buena manera de probar esto? En otras palabras, ¿cómo debería describir el comportamiento que necesito?

test1: canDetermineSumOfTwoIntegers 

o

test2: returnsSumOfTwoIntegers 

o

test3: knowsFivePlusThreeIsEight 

Prueba1 y Test2 parecen vagos y que habría que probar con un cálculo específico, por lo que no describe realmente lo que se está probando. Sin embargo, test3 es muy limitado.

¿Cuál es una buena manera de probar dichas clases?

Respuesta

10

pondría a prueba las condiciones de contorno (max-int, min-INT, cero, positivo, negativo) y algunos casos típicos:

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

etc.

+1

Quizás agregue sumOfMaxIntAndMaxInt y verifique que la función reporte la falla. Este es el caso más límite que puedo pensar. – pmr

+0

sumOfMaxIntAndOne debería causar una excepción también, ¿no es así? Ese sería otro buen caso de borde. De lo contrario, estoy de acuerdo. Solo piense en un par de posibilidades que difieren un poco y vaya con eso. –

+1

No se olvide de los casos de prueba negativos test6: sumOfStringAndPositive (debería generar error de excepción o de retorno) –

5

Hay varias filosofías. Roy Osherove, autor de The Art of Unit Testing, parece prefer using explicit values, y selecciona la representación más baja (o la más simple) de cada Equivalence Class.

Ese principio no se aplica particularmente bien a su ejemplo, pero funciona muy bien en muchos otros escenarios.

Si, por ejemplo, una clase requiere una entrada de un entero positivo, elija el número porque es la representación más simple de todos los intergers positivos.

Personalmente, prefiero un principio al que llamo Constrained Non-Determinism. El punto aquí es que dejamos que algún tipo de fábrica nos sirva variables anónimas para el tipo dado, porque nos obliga a establecer la relación directamente en la prueba.

estoy usando AutoFixture para hacer esto (pero también se puede usar otra cosa), por lo que en este caso me gustaría probar la SumCalculator así:

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); 

En principio, esta sola prueba proporciona una especificación para el método Calculate. Nunca sabemos cuáles son los valores de int1 y int2, y eso es muy apropiado en todos los casos en los que realmente no importa.

3

si está probando la función matemática, le sugiero que la pruebe contra su función inversa, por ejemplo: para funciones que hacen x = a + b, debe probar si ax = -b y xb = a , esto es solo para ilustrar, por supuesto, no funcionará en todos los casos.

1

Otra alternativa aquí sería utilizar Parameterized Test Case para eliminar duplicación en las pruebas.Básicamente, una tabla contiene todos los datos de las pruebas, en forma de tupla ([term1, term2, suma]), luego un caso de prueba itera en la tabla al invocar el caso de prueba parametrizado para probar una fila en la tabla:

I también agregaría pruebas negativas (desbordamiento aquí): ¿qué se supone que devuelve calculate(MAXINT, 1)?

1

Vea el trabajo de David Saff en Theory Tests; here (PDF) es un ejemplo. Esto es básicamente una manera de hacer una afirmación de que algo (como una función que es la inversa de su función) es verdadero para todos los valores en algún conjunto (incluido el conjunto de todos los valores posibles) y expresar esa afirmación como una prueba. Puede hacer algunas cosas divertidas ejecutando su prueba con valores seleccionados aleatoriamente (si el conjunto es demasiado grande para ejecutar de manera exhaustiva), y registrar automáticamente las fallas como pruebas específicas de regresión concretas.

Cuestiones relacionadas