2009-11-23 19 views
11

Estoy escribiendo algunas pruebas de NUnit para las operaciones de la base de datos. Obviamente, si Add() falla, entonces Get() también fallará. Sin embargo, parece engañoso cuando Add() y Get() fallan porque parece que hay dos problemas en lugar de uno solo.¿Cómo ignoro una prueba basada en otra prueba en NUnit?

¿Hay alguna manera de especificar un 'orden' para que se ejecuten las pruebas, en caso de que si la primera prueba falla, se ignoren las siguientes pruebas?

En la misma línea, ¿hay alguna forma de solicitar las clases de prueba unitaria? Por ejemplo, me gustaría ejecutar mis pruebas para las operaciones básicas de la base de datos antes de las pruebas para datos de ida y vuelta desde la interfaz de usuario.

Nota: Esto es un poco diferente al hecho de que las pruebas dependen unas de otras, es más como asegurarse de que algo funciona antes de ejecutar una serie de pruebas. Es una pérdida de tiempo, por ejemplo, ejecutar un montón de operaciones de base de datos si no puede obtener una conexión a la base de datos en primer lugar.

Editar: Parece que algunas personas están perdiendo el punto. No estoy haciendo esto:

[Test] 
public void AddTest() 
{ 
    db.Add(someData); 
} 

[Test] 
public void GetTest() 
{ 
    db.Get(someData); 
    Assert.That(data was retrieved successfully); 
} 

Más bien, yo estoy haciendo esto:

[Test] 
public void AddTest() 
{ 
    db.Add(someData); 
} 

[Test] 
public void GetTest() 
{ 
    // need some way here to ensure that db.Add() can actually be performed successfully 
    db.Add(someData); 
    db.Get(somedata); 
    Assert.That(data was retrieved successfully); 
} 

En otras palabras, quiero asegurar que los datos se pueden añadir en primer lugar antes de que pueda prueba si se puede recuperar. La gente está asumiendo que estoy usando datos de la primera prueba para pasar la segunda prueba cuando este no es el caso. Estoy tratando de asegurar que una operación sea posible antes de intentar otra que dependa de ella.

Como ya he dicho, debe asegurarse de obtener una conexión con la base de datos antes de ejecutar las operaciones de la base de datos. O que puede abrir un archivo antes de realizar operaciones de archivos. O conéctese a un servidor antes de probar las llamadas API. O ... entiendes el punto.

+1

¡La respuesta aceptada es ** incorrecta **! Ver los comentarios – Graviton

Respuesta

-3

crear una variable global y regresar en la prueba de Get menos Add ponemos a true (hacer esto en la última línea de Add):

public boolean addFailed = false; 
public void testAdd() { 
    try { 
     ... old test code ... 
    } catch (Throwable t) { // Catch all errors 
     addFailed = true; 
     throw t; // Don't forget to rethrow 
    } 
} 
public void testGet() { 
    if (addFailed) return; 
    ... old test code ... 
} 
+0

Gracias. No es muy elegante, pero parece que NUnit no admite esta funcionalidad de forma nativa. –

+1

Lo que quiere es un truco, por lo que la solución es una, también;) –

+0

No soy partidario de esta solución. El método testGet no ha pasado, no se ha ejecutado. Debería informarse como tal. –

1

no creo que eso sea posible fuera de la caja.

De todos modos, el diseño de su clase de prueba tal como lo describió hará que el código de prueba sea muy frágil.

+0

No estoy ejecutando la prueba 'Add()' para agregar datos a la base de datos primero, y luego ejecutar la prueba 'Get()' para obtener los datos. Más bien, quiero asegurarme de que 'Add()' funcione primero antes de la prueba 'Get()', como decir "Ok, ¿puedo agregar datos a la base de datos? Bien, ahora agregue estos datos de prueba y vea si puedo recuperarlos. eso." –

0

MbUnit parece tener un DependsOnAttribute que le permita hacer lo que quiera.

Si el otro dispositivo de prueba o método de prueba falla, entonces esta prueba no plazo. Además, la dependencia fuerza esta prueba para ejecutar después de las que depende .

No sé nada sobre NUnit though.

+0

Gracias, eso es exactamente lo que estaba buscando. Todavía es lo suficientemente temprano para poder cambiar a MbUnit si quiero, así que lo investigaré. –

14

NUnit admite una sintaxis "Assume.That" para validar la instalación. Esto se documenta como parte del Theory (gracias clairestreb).En el espacio de nombres NUnit.Framework es una clase Assume. Para citar la documentación:

/// Provides static methods to express the assumptions 
/// that must be met for a test to give a meaningful 
/// result. If an assumption is not met, the test 
/// should produce an inconclusive result. 

Así que en su contexto:

public void TestGet() { 
    MyList sut = new MyList() 
    Object expecting = new Object(); 
    sut.Put(expecting); 
    Assume.That(sut.size(), Is(1)); 
    Assert.That(sut.Get(), Is(expecting)); 
} 
+2

Esta debería ser la respuesta aceptada, una forma excelente de declarar las dependencias, y "no concluyente" es precisamente el resultado correcto, que en la mayoría de los marcos de prueba termina en naranja: es decir, que todavía hay que hacer algo. – Abel

+1

7 años después, pero sigo volviendo a esta publicación, así que aquí está el documento: http://nunit.org/index.php?p=theory&r=2.5 – clairestreb

5

Las pruebas deben Nunca dependen unos de otros. Acabas de descubrir por qué. Las pruebas que dependen unas de otras son frágiles por definición. Si necesita los datos en el DB para la prueba de Get(), colóquelos allí en el paso de configuración.

+0

Excepto que no es frágil. Te estás perdiendo el punto. Debe asegurarse de que haya ciertas cosas disponibles antes de poder realizar las pruebas. En mi caso, necesito asegurarme de que 'Add()' funcione porque sin él, 'Get()' no tendrá datos para obtener. No importa si está en la configuración o no porque estoy usando 'Add()' en mi prueba 'Get()', pero necesito asegurarme de que 'Add()' realmente funcione antes de ejecutar la prueba. –

+4

Esto es para lo que son la burla y el punteado. En la prueba de 'Get()', debería poder proporcionar datos ficticios para que Get() trabaje con ellos, de modo que la prueba pueda ejecutarse sin 'Add()'. Esto podría significar pasar una subclase de 'Add()' que no hace nada que pueda hacer que falle. El punto es que una prueba unitaria solo debería probar la unidad en cuestión. Debería haber una manera de probar Get() sin probar Add(). Si obtiene la solución que está solicitando, no puede saber si 'Get()' funciona o no si 'Add()' está roto. Significa que no puede obtener una instantánea confiable de su sistema. – jcdyer

+0

@Daniel T. Te estás perdiendo el punto. Las pruebas siempre deben ser independientes entre sí. Eso significa que el uso de 'Add()' en una prueba para 'Get()' no es una buena idea. Si 'Add()' se rompe, las pruebas para 'Get()' también se romperán. Tu prueba no está aislada. ¿Quién dice que necesitas usar 'Add()' para preparar tu DB para 'Get()' ... – EricSchaefer

2

Creo que el problema es que está usando NUnit para ejecutar algo que no sea el tipo de pruebas de unidad que NUnit se hizo para ejecutar.

Básicamente, desea que AddTest se ejecute antes de GetTest y desea que NUnit deje de ejecutar las pruebas si se produce un error en AddTest.

El problema es que eso es antitético a las pruebas unitarias: se supone que las pruebas son completamente independientes y se ejecutan en cualquier orden.

El concepto estándar de Unit Testing es que si tiene una prueba sobre la funcionalidad 'Agregar', puede usar la funcionalidad 'Agregar' en la prueba 'Obtener' y no preocuparse si 'Agregar' funciona dentro del 'Obtener' prueba. Usted sabe que 'Agregar' funciona: tiene una prueba para eso.

El principio 'FIRST' (http://agileinaflash.blogspot.com/2009/02/first.html) describe cómo deben comportarse las pruebas unitarias. La prueba que desea escribir viola tanto 'I' (Aislado) como 'R' (Repetible).

Si le preocupa que la conexión de la base de datos caiga entre sus dos pruebas, le recomendaría que en lugar de conectarse a una base de datos real durante la prueba, su código utilice algún tipo de interfaz de datos, y para la prueba, deberías estar usando una interfaz simulada. Si el punto de la prueba es para ejercitar la conexión de la base de datos, entonces simplemente puede estar utilizando la herramienta incorrecta para el trabajo; eso no es realmente una prueba de Unidad.

+0

Lo que dices tiene mucho sentido, pero sigo teniendo problemas para entender cómo puedo aislar 'Get()' de 'Add()'. Tal como lo veo, es como tener una caja vacía. Tienes que ser capaz de poner algo dentro de la caja antes de que puedas probar si puedes sacarlo. –

+0

Están tan aislados como pueden. Si quiere 'Get()', obviamente necesita 'Put()' primero en esa misma prueba (o en configuración). El aislamiento proviene del hecho de que sus dos pruebas están probando cosas totalmente diferentes: sus primeras pruebas 'Put()' y sus segundas pruebas 'Get()'. Si 'Put()' falla, ambos fallarán, pero está bien. No hay una regla de Pruebas de unidades que indique que si un área del sistema se rompe, debe romper exactamente una prueba; solo necesita romper * al menos * una prueba, con suerte una de las cuales prueba específicamente esa área. –

+0

Tuve una conversación con un compañero de trabajo y él dijo que, aunque en teoría, sería bueno evitar que fallara la cascada, rara vez hay un caso en la práctica donde un fallo en cascada en realidad obstaculiza algo. En otras palabras, si tiene más de 200 pruebas y la prueba para ver si los datos pueden recuperarse de la base de datos ha fallado, sería bueno ignorar el resto de las pruebas, ya que también fallarán automáticamente. Pero debido a que las pruebas generalmente se ejecutan rápidamente y se deben agrupar de acuerdo con la capa que está probando, debería ser bastante fácil ver el problema. –

0

No puede suponer ningún orden de ejecución del dispositivo de prueba, por lo que debe verificar los requisitos previos dentro de sus clases de prueba.

Segregue su prueba Agregar en una clase de prueba, p. Agregue pruebas y coloque las pruebas de obtención en otra clase de prueba, p. Ej. clase GetTests.

En el método [TestFixtureSetUp] de la clase GetTests, compruebe que tiene acceso a la base de datos en funcionamiento (por ejemplo, el trabajo de Add) y, de lo contrario, Assert.Ignore o Inconclusive, según lo considere apropiado.

Esto cancelará el accesorio de prueba GetTests cuando no se cumplan sus requisitos previos, y se saltará el intentar ejecutar cualquiera de las pruebas unitarias que contiene. (¡Creo que soy un novato en nUnit)

Cuestiones relacionadas