tx130 limpieza limpiar l800 l555 l355 inyectores impresora hacer ecotank como cabezales cabezal .net nunit nunit-2.5
mi SkyDrive

.net - limpiar - limpieza de cabezales epson l800



NUnit-limpieza después de la falla de la prueba (11)

¿Cómo falla? ¿Es posible ponerlo en una prueba (do test) / catch (fix broken db) / finally block?

O puede llamar a un método privado para solucionarlo cuando haya verificado su condición de falla.

Tenemos algunas pruebas de NUnit que acceden a la base de datos. Cuando uno de ellos falla, puede dejar la base de datos en un estado incoherente, lo cual no es un problema, ya que reconstruimos la base de datos para cada ejecución de prueba, pero puede causar que otras pruebas fallen en la misma ejecución.

¿Es posible detectar que una de las pruebas falló y realizar algún tipo de limpieza?

No queremos escribir código de limpieza en cada prueba, ya lo hacemos ahora. Me gustaría llevar a cabo una limpieza en Desmontaje, pero solo si la prueba falla, ya que la limpieza puede ser costosa.

Actualización : para aclarar: me gustaría que las pruebas sean simples y NO incluya ninguna lógica de limpieza o manejo de errores. Tampoco quiero realizar el restablecimiento de la base de datos en cada ejecución de prueba, solo si la prueba falla. Y este código probablemente debería ejecutarse en el método de Desmontaje, pero no tengo conocimiento de ninguna forma de obtener información si la prueba que estamos realizando actualmente falla o si fue exitosa.

Actualización2 :

[Test] public void MyFailTest() { throw new InvalidOperationException(); } [Test] public void MySuccessTest() { Assert.That(true, Is.True); } [TearDown] public void CleanUpOnError() { if (HasLastTestFailed()) CleanUpDatabase(); }

Estoy buscando la implementación de HasLastTestFailed ()


¿Qué hay de usar un bloque Try-Catch, volver a lanzar la excepción atrapada?

try { //Some assertion } catch { CleanUpMethod(); throw; }


Desde la versión 2.5.7, NUnit permite que Teardown detecte si falló la última prueba. Una nueva clase TestContext permite que las pruebas accedan a información sobre sí mismos, incluidas las TestStauts.

Para obtener más información, consulte http://nunit.org/?p=releaseNotes&r=2.5.7

[TearDown] public void TearDown() { if (TestContext.CurrentContext.Result.Status == TestStatus.Failed) { PerformCleanUpFromTest(); } }


Esta idea me interesó, así que hice un poco de excavación. NUnit no tiene esta capacidad lista para usar, pero se proporciona un marco de extensibilidad completo con NUnit. Encontré este excelente artículo sobre la extensión de NUnit : fue un buen punto de partida. Después de jugar con él, se me ocurrió la siguiente solución: un método decorado con un atributo CleanupOnError personalizado se CleanupOnError si una de las pruebas en el dispositivo falla.

Así es como se ve la prueba:

[TestFixture] public class NUnitAddinTest { [CleanupOnError] public static void CleanupOnError() { Console.WriteLine("There was an error, cleaning up..."); // perform cleanup logic } [Test] public void Test1_this_test_passes() { Console.WriteLine("Hello from Test1"); } [Test] public void Test2_this_test_fails() { throw new Exception("Test2 failed"); } [Test] public void Test3_this_test_passes() { Console.WriteLine("Hello from Test3"); } }

donde el atributo es simplemente:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public sealed class CleanupOnErrorAttribute : Attribute { }

Y así es como se ejecuta desde el complemento:

public void RunFinished(TestResult result) { if (result.IsFailure) { if (_CurrentFixture != null) { MethodInfo[] methods = Reflect.GetMethodsWithAttribute(_CurrentFixture.FixtureType, CleanupAttributeFullName, false); if (methods == null || methods.Length == 0) { return; } Reflect.InvokeMethod(methods[0], _CurrentFixture); } } }

Pero esta es la parte difícil: el complemento debe colocarse en el directorio de complementos al lado del corredor NUnit. El mío se colocó junto al corredor NUnit en el directorio TestDriven.NET:

C:/Program Files/TestDriven.NET 2.0/NUnit/addins

( addins directorio de addins , no estaba allí)

EDITAR ¡ Otra cosa es que el método de limpieza debe ser static !

He pirateado un simple complemento, puedes descargar la fuente desde mi SkyDrive . Deberá agregar referencias a nunit.framework.dll , nunit.core.dll y nunit.core.interfaces.dll en los lugares apropiados.

Algunas notas: la clase de atributo se puede colocar en cualquier parte de tu código. No quería colocarlo en el mismo ensamblaje que el complemento, porque hace referencia a dos ensamblajes Core NUnit, por lo que lo coloqué en un ensamblaje diferente. Solo recuerde cambiar la línea en CleanAddin.cs , si decide colocarlo en otro lugar.

Espero que ayude.


Me gustaría que phsr sugiera por ahora y cuando pueda pagarlo, refactorizar las pruebas para que nunca tengan que depender de los mismos datos que necesita otra prueba, o incluso mejor, abstraer la capa de acceso a datos y burlarse de los resultados provenientes de esa base de datos. Parece que tus pruebas son bastante caras y deberías hacer toda tu lógica de consulta en la base de datos y la lógica de negocio en tu ensamblado; realmente no te importan los resultados que se devuelvan.

También podrás probar tu ExceptionHandling mucho mejor.


No digo que esta sea una gran idea, pero debería funcionar. Recuerde que las fallas de afirmación son solo excepciones. Además, no olvide que también hay un atributo [TestFixtureTearDown] que se ejecuta solo una vez después de que se hayan ejecutado todas las pruebas en el dispositivo.

Usando esos dos hechos, puede escribir algo así como establecer una bandera si falla una prueba y verificar el valor de la bandera en el accesorio de prueba.

No lo recomiendo, pero funcionaría. Realmente no está usando NUnit como estaba previsto, pero puede hacerlo.

[TestFixture] public class Tests { private bool testsFailed = false; [Test] public void ATest() { try { DoSomething(); Assert.AreEqual(....); } catch { testFailed = true; } } [TestFixtureTearDown] public void CleanUp() { if (testsFailed) { DoCleanup(); } } }


Otra opción es tener una función especial que arroje sus excepciones, que establece un cambio en la estructura de prueba que dice que se produjo una excepción.

public abstract class CleanOnErrorFixture { protected bool threwException = false; protected void ThrowException(Exception someException) { threwException = true; throw someException; } protected bool HasTestFailed() { if(threwException) { threwException = false; //So that this is reset after each teardown return true; } return false; } }

Luego usando tu ejemplo:

[TestFixture] public class SomeFixture : CleanOnErrorFixture { [Test] public void MyFailTest() { ThrowException(new InvalidOperationException()); } [Test] public void MySuccessTest() { Assert.That(true, Is.True); } [TearDown] public void CleanUpOnError() { if (HasLastTestFailed()) CleanUpDatabase(); } }

El único problema aquí es que el seguimiento Stack dará lugar a CleanOnErrorFixture


Puede agregar un método [TearDown] con
if (TestContext.CurrentContext.Result.Status != TestStatus.Passed)
algún código que se ejecutará si la prueba falla.


Sí hay. Puede utilizar el atributo de desmontaje que desmontará después de cada prueba. Querrá aplicar esa secuencia de comandos de "reinicio" de la base de datos que tiene y desmontar y volver a configurar antes y después de cada prueba.

Este atributo se usa dentro de TestFixture para proporcionar un conjunto común de funciones que se realizan después de ejecutar cada método de prueba.

Actualización : con base en los comentarios y la actualización de la pregunta, diría que puede usar el atributo de desmontaje y usar variables privadas para indicar si el contenido del método debe activarse.

Sin embargo, también vi que no desea ningún código complejo de lógica o manejo de errores.

Dado eso, pensaría que una instalación / Teardown estándar funcionaría mejor para usted. No importa si hay un error y no es necesario que tenga ningún código de manejo de errores.

Si necesita una limpieza especial porque las próximas pruebas dependen de la finalización exitosa de la prueba actual, le sugiero que revise sus pruebas; es probable que no dependan la una de la otra.


Si bien es posible obligar a nUnit a hacer esto, no es el diseño más sensato, siempre se puede establecer un archivo temporal en alguna parte y si ese archivo existe, ejecute la limpieza.

Recomendaría cambiar su código para que tenga habilitadas las transacciones de la base de datos y, al final de la prueba, simplemente revertir la base de datos al estado original (por ejemplo, descartar la transacción que representa sus pruebas unitarias).


Una opción que no se ha mencionado hasta ahora es ajustar la prueba en un objeto TransactionScope, por lo que no importa lo que ocurra, ya que la prueba nunca compromete nada con el DB.

Aquí hay algunos detalles sobre la técnica . Probablemente pueda encontrar más si realiza una búsqueda en las pruebas unitarias y en el haz de transacciones (aunque realmente está haciendo pruebas de integración si accede a un DB). Lo he usado con éxito en el pasado.

Este enfoque es simple, no requiere ninguna limpieza y asegura que las pruebas estén aisladas.

Editar- Acabo de notar que la respuesta de Ray Hayes también es similar a la mía.