Si solo tuviera una afirmación por prueba; ¿Cómo probar múltiples entradas?

15

Estoy tratando de construir algunos casos de prueba, y he leído que debes intentar limitar el número de afirmaciones por caso de prueba.

Entonces mi pregunta es, ¿cuál es la mejor manera de probar una función con múltiples entradas? Por ejemplo, tengo una función que analiza una cadena del usuario y devuelve el número de minutos. La cadena puede estar en el formulario "5w6h2d1m", donde w, h, d, mcorresponde al número de semanas, horas, días y minutos.

Si quisiera seguir la '1 afirmación por regla de prueba', ¿tendría que hacer varias pruebas para cada variación de entrada? Eso parece una tontería, así que en cambio tengo algo como:

self.assertEqual(parse_date('5m'), 5)
self.assertEqual(parse_date('5h'), 300)
self.assertEqual(parse_date('5d') ,7200)
self.assertEqual(parse_date('1d4h20m'), 1700)

En el caso de una prueba. ¿Hay una mejor manera?

speg
fuente
La mejor manera de hacerlo es usando parámetros (algunos marcos soportan esta característica, todos los marcos deberían). De esta forma, está probando un solo comportamiento pero teniendo en cuenta muchos casos de prueba y aún puede ver qué valores de parámetros causaron un error si se produce un error
Kemoda el

Respuestas:

23

Una forma más pragmática de ver una afirmación por "regla" de prueba es hacer que sus afirmaciones en una sola prueba cubran un solo concepto.

De esta manera, todavía está probando un solo concepto en una sola prueba. En su caso, si su cadena de entrada se analiza correctamente en una sola fecha.

Debe ejercer su juicio caso por caso para verificar si es mejor probar un solo concepto con múltiples afirmaciones o tener una sola afirmación en muchas pruebas.

Elija la opción que permita realizar pruebas más claras, menos repetición y al mismo tiempo que sus pruebas puedan resaltar diferentes puntos de fallas en su método. Desea que quede claro cuando una prueba falla exactamente lo que sucedió en lugar de tener que depurar su prueba para averiguar qué salió mal.

Gilles
fuente
17

Depende mucho de su biblioteca de pruebas. En la biblioteca C # NUnit puedes hacer algo como:

[TestCase('5m', 5)]
[TestCase('5h', 300)]
[TestCase('5d', 7200)]
[TestCase('1d4h20m', 1700)]
public void ParseDateTest(inputString, expectedMinutes)
{
    Assert.That(parse_date(inputString), Is.EqualTo(expectedMinutes));
}
Scroog1
fuente
En java con testng tienes métodos
@DataProvider
esa es la mejor solución en mi humilde opinión. en casi todos los idiomas puedes parametrizar tus pruebas. para java: @Parameterized , JunitParams , Zohhak
piotrek
3

Sí, haga múltiples pruebas para cada variación de entrada.

El objetivo principal de una afirmación por pauta de prueba es tener (idealmente) que un error conduce a una falla de prueba y viceversa para que sepa exactamente qué falló. Entonces puede trabajar con una prueba muy precisa para depurar la causa raíz y verificar. Puede romper esto con una afirmación, y puede estar bien con múltiples afirmaciones. En este escenario particular, tendría una prueba para cada sufijo y algunas combinaciones de pedidos.

Con suerte, está claro por qué aislar las pruebas es un beneficio: pierde menos tiempo depurando cuando algo sale mal. Ahora, si está realmente seguro de que es poco probable que la prueba falle, y que la sobrecarga de la búsqueda a través de la prueba es pequeña, entonces quizás tenga sentido simplemente probarlos todos a la vez para ahorrar tiempo de implementación.

Pero la historia ha demostrado que nunca vale la pena ahorrar un poco de tiempo escribiendo código a expensas de leer / usar código . De ahí la directriz.

Telastyn
fuente
1

Los puristas dirían que las aserciones para diferentes valores de entrada deben ponerse en métodos de prueba separados dentro de la clase de prueba. Una razón para esto es que, dependiendo de su IU de prueba, a menudo es más fácil distinguir entre fallas de prueba individuales que entre afirmaciones individuales, lo que podría llevarlo a identificar la fuente de falla más rápidamente.

Al probar con JUnit, podemos evitar esto usando la versión de los métodos de aserción * con un argumento de cadena inicial para diferenciar una aserción de otra dentro del mismo método de prueba.

self.assertEqual("just minutes", parse_date('5m'), 5)
self.assertEqual("just hours", parse_date('5h'), 300)
self.assertEqual("just days", ('5d') ,7200)
self.assertEqual("days, hours, minutes", parse_date('1d4h20m'), 1700)
Mike Partridge
fuente