2009-05-16 12 views
6

Algunas de mis pruebas de unidad mstest ayudan a detectar las condiciones de carrera de subprocesamiento múltiple, y como tales son más útiles cuando se ejecutan muchas veces seguidas, pero solo quiero hacer esto para pruebas de prueba específicas. - no todo el tiempo.Repita la prueba de prueba mstest varias veces

¿Hay alguna manera de configurar mstest (preferiblemente en el Editor de la lista de prueba) para ejecutar una prueba varias veces?

Respuesta

10

Tenía que hacer algo similar, así que se me ocurrió una solución para esto.

No es simple, pero una vez que todo está configurado, puede reutilizarlo en todos los proyectos. También tengo una descarga de este código en GitHub (https://github.com/johnkoerner/MSTestLooper), pero en caso de que desaparezca en algún momento, así es como lo hice.

Primero creamos un atributo que aplicaremos a nuestra clase para indicarle que ejecute todas las pruebas varias veces. Haga todo esto en un ensamblaje por separado, porque la DLL necesita vivir en una ubicación especial.

[Serializable] 
public class TestLooperAttribute : TestClassExtensionAttribute 
{ 
    private static readonly Uri thisGuy = new Uri("urn:TestLooperAttribute"); 

    private string _PropertyName; 
    public string PropertyName 
    { 
     get 
     { return _PropertyName; } 
     set 
     { 
      _PropertyName = value; 
     } 
    } 
    public override Uri ExtensionId 
    { 

     get { 
      return thisGuy; } 
    } 


     public override TestExtensionExecution GetExecution() 
    { 

     return new TestLooperExecution(PropertyName); 
    } 
} 

A continuación tenemos para crear una prueba personalizada clase de ejecución de clase:

class TestLooperExecution : TestExtensionExecution 
{ 
    private string PropertyName; 

    public TestLooperExecution(string PropertyName) 
    { 
     this.PropertyName = PropertyName; 
    } 

    public override ITestMethodInvoker CreateTestMethodInvoker(TestMethodInvokerContext InvokerContext) 
    { 
     return new TestLooperInvoker(InvokerContext, PropertyName); 
    } 

    public override void Dispose() 
    { 
     //TODO: Free, release or reset native resources 
    } 

    public override void Initialize(TestExecution Execution) 
    { 
     //TODO: Wire up event handlers for test events if needed 

    } 
} 

Por último añadimos un invocador costumbre, que es donde se realice el bucle:

class TestLooperInvoker : ITestMethodInvoker 
{ 
    private TestMethodInvokerContext m_invokerContext; 
    private string PropertyName; 

    public TestLooperInvoker(TestMethodInvokerContext InvokerContext, string PropertyName) 
    { 
     m_invokerContext = InvokerContext; 
     this.PropertyName = PropertyName; 
    } 

    public TestMethodInvokerResult Invoke(params object[] args) 
    { 

     // Our helper results class to aggregate our test results 
     HelperTestResults results = new HelperTestResults(); 

     IEnumerable<object> objects = m_invokerContext.TestContext.Properties[PropertyName] as IEnumerable<object>; 

     foreach (var d in objects) 
      results.AddTestResult(m_invokerContext.InnerInvoker.Invoke(d), new object[1] { d.GetType().ToString()}); 

     var output = results.GetAllResults(); 
     m_invokerContext.TestContext.WriteLine(output.ExtensionResult.ToString()); 

     return output; 
    } 
} 

Los HelperTestResults class solo crea cadenas para la salida, puede manejar esto como desee y no quiero incluir ese código porque hará que esta publicación sea mucho más larga.

Compilar esto en un DLL y entonces usted necesita para copiarlo en

C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies 

También tiene que crear una entrada de registro para la clase:

Windows Registry Editor Version 5.00 
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\EnterpriseTools\QualityTools\TestTypes\{13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b}\TestTypeExtensions\TestLooperAttribute] 
"AttributeProvider"="TestLooper.TestLooperAttribute, TestLooper" 

Ahora que tiene todo eso Hecho, finalmente puede utilizar la clase:

using System; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using TestLooper; 
using System.Collections.Generic; 
namespace UnitTestSamples 
{ 
    [TestLooper(PropertyName="strings")] 
    public class UnitTest1 
    { 
     public static List<String> strings = new List<String>(); 
     private TestContext testContextInstance; 

     public TestContext TestContext 
     { 
      get 
      { 
       return testContextInstance; 
      } 
      set 
      { 
       testContextInstance = value; 
      } 
     } 
     [ClassInitialize()] 
     public static void Init(TestContext x) 
     { 
      strings.Add("A"); 
      strings.Add("B"); 
      strings.Add("C"); 
      strings.Add("D"); 

     } 

     [TestInitialize()] 
     public void TestInit() 
     { 
      if (!TestContext.Properties.Contains("strings")) 
      testContextInstance.Properties.Add("strings", strings); 
     } 

     [TestMethod] 
     [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "DataDriven1.csv", "DataDriven1#csv", DataAccessMethod.Sequential)] 
     [DeploymentItem("DataDriven1.csv")] 
     public void TestMethodStrings(string s) 

     { 
      int value1 = Convert.ToInt32(TestContext.DataRow["Col1"]); ; 
      TestContext.WriteLine(String.Format("{0}:{1}", s, value1)); 
     } 
    } 
} 

Tenga en cuenta que nuestro método de prueba acepta un parámetro, que viene f rom del looper de prueba. También muestro esto usando una prueba basada en datos, para mostrar que puedes combinar los dos para generar grandes permutaciones en tus conjuntos de datos.

+0

Ni siquiera sabía que MSTest tuviera tanta extensibilidad. Esto es genial, gracias! –

2

Considere crear una prueba para derivar un par de hilos. La lista de prueba no le permitirá tener múltiples entradas para la misma prueba. Sin embargo, podría asignar la prueba de subprocesos múltiples a su propia lista y llamarla solo cuando desee ejecutar esa prueba en particular.

+0

Ese es un enfoque interesante. Gracias. –

2

Supongo que la respuesta es no.

3
[TestMethod()] 
public void RepetableTest(){ 
    for(int i = 0; i < repeatNumber; i++){ 

    //test code goes here 


    } 
} 
+1

Ver http://stackoverflow.com/questions/25565574/run-unittest-several-time-not-just-loop-it? por qué esto no siempre logra el resultado requerido. – Ricibob

Cuestiones relacionadas