2010-01-14 18 views
6

¿Hay alguna forma de que pueda acceder a la excepción manejada por la estructura MSTest usando TestContext o algún otro método en una clase de prueba base?MSTest Test Context Exception Handling

Si se produce una excepción no controlada en una de mis pruebas, me gustaría examinar todos los elementos del diccionario de excepción.Data y mostrarlos al resultado de la prueba para ayudarme a descubrir por qué falló la prueba (usualmente agregue datos a la excepción para ayudarnos a depurar en el entorno de producción, por lo que me gustaría hacer lo mismo para las pruebas).

Nota: No estoy probando que SE SUPONE UNA EXCEPCIÓN A HAPPEN (tengo otras pruebas para eso), estoy probando un caso válido, solo necesito ver los datos de excepción.

Aquí hay un ejemplo de código de lo que estoy hablando.

[TestMethod] 
public void IsFinanceDeadlineDateValid() 
{ 
    var target = new BusinessObject(); 
    SetupBusinessObject(target); 

    //How can I capture this in the text context so I can display all the data 
    //in the exception in the test result... 

    var expected = 100; 
    try 
    { 
     Assert.AreEqual(expected, target.PerformSomeCalculationThatMayDivideByZero()); 
    } 
    catch (Exception ex) 
    { 
     ex.Data.Add("SomethingImportant", "I want to see this in the test result, as its important"); 
     ex.Data.Add("Expected", expected); 
     throw ex; 
    } 

} 

que entender que hay cuestiones en torno a eso que probablemente no debería tener un procedimiento de este tipo de encapsulación, pero también tenemos pruebas Sub Para probar toda la funcionalidad de PerformSomeCalculation ...

Sin embargo, si la prueba falla, el 99% de las veces, vuelvo a ejecutar, así que no puedo depurar nada sin esta información. También me gustaría hacer esto a nivel GLOBAL, de modo que si alguna prueba falla, obtengo la información en los resultados de la prueba, en lugar de hacerlo para cada prueba individual.

Aquí está el código que pondría la información de excepción en los resultados de la prueba.

public void AddDataFromExceptionToResults(Exception ex) 
    { 
     StringBuilder whereAmI = new StringBuilder(); 
     var holdException = ex; 
     while (holdException != null) 
     { 
      Console.WriteLine(whereAmI.ToString() + "--" + holdException.Message); 
      foreach (var item in holdException.Data.Keys) 
      { 
       Console.WriteLine(whereAmI.ToString() + "--Data--" + item + ":" + holdException.Data[item]); 
      } 

      holdException = holdException.InnerException; 
     } 
    } 
+0

Véase también: http://stackoverflow.com/questions/37660311/method-for-handling-exceptions-in-mstest/39208343#39208343 – Almund

Respuesta

3

He estado teniendo el mismo problema, no parece haber soporte para esto. Ni siquiera puedes usar el enganche de excepción no administrado de ApplicationDomain ya que si MSTEST no detectaba excepciones antes de que llegaran a ese punto, se bloqueaba.

solución posible:

private delegate void TestImplDelegate(); 

    private void RunTestWithExceptionLogging(TestImplDelegate testImpl) 
    { 
     try 
     { 
      testImpl(); 
     } 
     catch (Exception e) 
     { 
      string message = e.Message; // don't warn about unused variables 

      // do logging here 
     } 
    } 

    [TestMethod] 
    public void test1() 
    { 
     RunTestWithExceptionLogging(test1Impl); 
    } 
    private void test1Impl() 
    { 
     // test code goes here 

     throw new Exception("This should get logged by the test wrapper."); 
    } 

    [TestMethod] 
    public void test2() 
    { 
     RunTestWithExceptionLogging(test2Impl); 
    } 
    private void test2Impl() 
    { 
     // test code goes here 

     throw new Exception("This should get logged by the test wrapper."); 
    } 

Desde luego no es óptima, pero al menos de esta manera usted no tiene múltiples copias del código de gestión de excepciones.

Yo recomendaría la presentación de una solicitud de función para esto en http://connect.microsoft.com/ (o ver si alguien ya lo ha solicitado, y añadir a su voto.)

1

Aquí es una obra "limpia" en torno al cual va a poner la excepción en una propiedad TestBase.TestContext (o donde quieras en tu instancia de TestBase).

El ejemplo usa postsharp (que es una lib de AOP) para inyectar try-catch a su código en tiempo de compilación. Inyectará a todos los métodos que tengan el atributo [TestMethod]. - la edición gratuita de postsharp hará el trabajo, sin necesidad de una licencia.

Lo primero que tienes que hacer es crear el atributo AOP.Los atributos define lo que se hará en caso de excepción y + definir las condiciones para la inyección, así es como se hace:

/// <summary> 
/// Catch exceptions of tests and save them in <see cref="TestBase"/> under TestContext.Properties. This is done since MSTEST does not supply any mechanism to catch tests exceptions. 
/// </summary> 
[SerializableAttribute] 
public class CodedTestsExceptionsHandlingAop : OnExceptionAspect 
{ 
    /// <summary> 
    /// The name of the property that will be added to the test context properties object. 
    /// </summary> 
    public const string FailureExceptionProerty = "FailureException"; 

    /// <summary> 
    /// Save the exception in a <see cref="TestBase"/> and rethrow. 
    /// </summary> 
    /// <param name="args"></param> 
    public override void OnException(MethodExecutionArgs args) 
    { 
     var testBase = (Framework.TestBase) args.Instance;//The instance running the test inherits from TestBase. 
     testBase.TestContext.Properties.Add("FailureException", args.Exception); 

     args.FlowBehavior = FlowBehavior.RethrowException; 
    } 

    /// <summary> 
    /// Make sure only test methods will get this AOP. 
    /// </summary> 
    /// <param name="method"></param> 
    /// <returns></returns> 
    public override bool CompileTimeValidate(MethodBase method) 
    { 
     if (method.IsDefined(typeof(TestMethodAttribute))) 
      return true; 

     return false; 
    } 
} 

segunda cosa, tendrá que añadir el siguiente atributo de nivel de ensamblado a su proyecto de pruebas (que también es necesario tener instalado PostSharp si no es en el mismo proyecto como su TestBase), esto se aplicará la inyección de AOP sobre el conjunto de pruebas:

[assembly: CodedTestsExceptionsHandlingAop(AttributeTargetTypes = "*", AttributeTargetElements = MulticastTargets.Method)] 
0

Si estás con ganas de probar esperados le excepciones podría usar el ExpectedExceptionAttribute

Creo que ser capaz de obtener la excepción para una prueba unitaria sería más útil cuando se trata de una excepción inesperada y desea iniciar sesión o recopilar información adicional sobre la excepción, en lugar de confiar en el TestExplorer para encontrar una prueba fallida.