2010-02-26 23 views
7

Estoy usando NUnit para escribir pruebas de unidad para una biblioteca que un colega mío ha escrito. Su biblioteca contiene una gran cantidad de depuración. Afirma que se desencadena en entradas no válidas. Cuando escribo las pruebas de la unidad y le doy información inválida a su biblioteca, su Debug.Assert arroja un cuadro de mensaje quejándose de la mala entrada.NUnit conflicto con Debug.Assert

Creo que es bueno que su biblioteca arroje una afirmación sobre una entrada no válida, pero al mismo tiempo quiero que las pruebas de la unidad cubran datos incorrectos. Pero cuando hago esto, aparece el cuadro de mensaje y tengo que hacer clic manualmente en Aceptar para continuar con las pruebas unitarias restantes.

En caso de que no esté claro, mi problema es que el proceso de prueba de la unidad se detiene en Debug.Assert. Se supone que las personas deben ejecutar sus pruebas unitarias antes de cualquier registro y se supone que es automático y no deben lanzar mensajes a menos que una prueba haya fallado.

¿Cuál es el "mejor" enfoque en este caso?

Respuesta

3

Eche un vistazo a la documentación de MSDN para Debug.Assert method. Específicamente en "Observaciones", se explica cómo se puede desactivar la interfaz de usuario:

<configuration> 
    <system.diagnostics> 
    <assert assertuienabled="false" logfilename="c:\\myFile.log" /> 
    </system.diagnostics> 
</configuration> 

Por lo tanto me gustaría sugerir que el archivo de la aplicación de configuración tiene esta por defecto y su colega se enciende Assert a la interfaz de usuario cada vez que se siente útil hazlo.

2

Como ya notó Henk, suprimir la interfaz de usuario es inútil, porque quiere que su código falle. Cuando no se desea cambiar su código, puede escribir una escucha de seguimiento personalizado que se produce una excepción, de la siguiente manera:

public class ProductionTraceListener : DefaultTraceListener 
{ 
    public override void Fail(string message, string detailMessage) 
    { 
     string failMessage = message; 

     if (detailMessage != null) 
     { 
      failMessage += " " + detailMessage; 
     } 

     throw new AssertionFailedException(failMessage); 
    } 
} 

[Serializable] 
public class AssertionFailedException : Exception 
{ 
    public AssertionFailedException() { } 
    public AssertionFailedException(string message) : base(message) { } 
    public AssertionFailedException(string message, Exception inner) 
     : base(message, inner) { } 
    protected AssertionFailedException(SerializationInfo info, 
     StreamingContext context) : base(info, context) { } 
} 

Y usted puede registrarlo como sigue:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <system.diagnostics> 
    <trace> 
     <listeners> 
     <clear /> 
     <add name="Default" 
      type="[Namespace].ProductionTraceListener, [Assembly]" /> 
     </listeners> 
    </trace> 
    </system.diagnostics> 
</configuration> 

Como ya se podría esperar del nombre del oyente del seguimiento ProductionTraceListener, uso esa cosa en mi entorno de producción (aplicaciones web) y no en las pruebas de mi unidad. Si bien puede usar este truco en las pruebas de su unidad, le aconsejo que cambie su código. IMO solo debe usar afirmaciones para rutas de código que nunca deberían ejecutarse, y si lo hacen, la prueba debería fallar. En su situación, quiere tener una prueba exitosa cuando falla una afirmación, lo cual es contrario a la intuición.

Mi consejo es cambiar el código y usar las comprobaciones normales de if (x) throw ArgumentException() para ver si hay condiciones previas (o usar CuttingEdge.Conditions) y usar esas afirmaciones solo para rutas de código que nunca deberían ejecutarse. También intente usar Trace.Assert en lugar de Debug.Assert, porque también desea que esos comprobantes se comprueben en su entorno de producción. Cuando lo haya hecho, puede usar el ProductionTraceListener en su entorno de producción, y este UnitTestTraceListener en su unidad prueba.

public class UnitTestTraceListener : DefaultTraceListener 
{ 
    public override void Fail(string message, string detailMessage) 
    { 
     string failMessage = message; 

     if (detailMessage != null) 
     { 
      failMessage += " " + detailMessage; 
     } 

     // Call to Assert method of used unit testing framework. 
     Microsoft.VisualStudio.TestTools.UnitTesting.Assert.Fail(
      failMessage); 
    } 
} 

Buena suerte.

+0

Esto se vería bien para Trace.Assert(), pero el OP menciona Debug.Assert(). –

+0

Además, desea que el código falle * en las pruebas unitarias * cuando las ejecuta como parte de un proceso de compilación automatizado. Los Asserts son para que los desarrolladores se beneficien al ejecutar el código. – Rob

+0

@Henk && @Rob: No estoy seguro de seguirte. La configuración de 'ProductionTraceListener' en el entorno de prueba de la unidad permitiría que las pruebas de la unidad fallaran cuando los métodos no lanzaran la 'AssertionFailedException' esperada. Cuando las pruebas unitarias se ejecutan en modo de depuración, esto hará exactamente lo que él quiera, ¿no es así? Por favor iluminame. – Steven

2

Una opción simple que considero efectiva es usar el estándar ConsoleTraceListener, que permitirá las comprobaciones Debug.Asert para disparar, pero dirigirá su salida a la pestaña NUnit Text Output sin tener que influir en la prueba unitaria.

Puede agregar esto a su configuración de prueba ...

[SetUp] 
public void SetUp() 
{ 
    // Replace pop-up assert trace listener with one that simply logs a message. 
    Debug.Listeners.Clear(); 
    Debug.Listeners.Add(new ConsoleTraceListener()); 
} 

Pero no se olvide de comprobar la salida de texto cuando una prueba falla!