2012-05-22 17 views
8

Tengo un proyecto de prueba de unidad llamado "MyClassTest" en TeamTest. Este proyecto tiene tres TestMethods. Cada método necesita sus propios pasos de inicialización de prueba. Pero cuando aplico TestInitializeAttribute a tres métodos de inicialización, dice que el atributo no se debe usar más de una vez. Entonces, ¿cuál debería ser el atributo que se utilizará para inicializar cada método de prueba en Visual Studio Team Test?VS Team Test: Métodos de inicialización de prueba múltiple en la clase de prueba

Referencia:

  1. VS Team Test: .Net Unit Testing with Excel as Data Source: Adapter Failed

  2. How to create Startup and Cleanup script for Visual Studio Test Project?

  3. VS 2010 Load Tests Results with custom counters

  4. How to log unit test entry and leave in MSTest

  5. Can a unit test project load the target application's app.config file?

Respuesta

18

De acuerdo con la MSDNTestInitializeAttribute:

  • no puede utilizarse más de una vez (allowMultiple = false), y
  • no se puede heredar para crear su propia TestInitializeAttribute.

Por lo tanto, mi sugerencia es crear los Métodos de inicialización de prueba sin el atributo TestInitialize. Luego, en el único cheque método TestInitialize que es el actual ejecutada TestMethod y llamar al método initialize apropiado:

[TestClass] 
public class UnitTest 
{ 
    public TestContext TestContext { get; set; } 

    [TestInitialize] 
    public void Initialize() 
    { 
     switch (TestContext.TestName) 
     { 
      case "TestMethod1": 
       this.IntializeTestMethod1(); 
       break; 
      case "TestMethod2": 
       this.IntializeTestMethod2(); 
       break; 
      default: 
       break; 
     } 
    } 

    [TestMethod] 
    public void TestMethod1() 
    { 
    } 

    [TestMethod] 
    public void TestMethod2() 
    { 
    } 

    public void IntializeTestMethod1() 
    { 
     //Initialize Test Method 1 
    } 

    public void IntializeTestMethod2() 
    { 
     //Initialize Test Method 2 
    } 
} 
+1

Gracias. Esto parece factible. ¿Es la práctica estándar que la gente sigue? – Lijo

+0

Esta es la práctica que sigue mi equipo. No sé si hay otra forma mejor :) – Schaliasos

+5

'AllowMultiple = false' impone el uso único en el mismo elemento solamente ... eso significa que un solo método no se puede marcar con múltiples' TestInitializeAttribute'. La regla de que no se puede usar en diferentes métodos no tiene nada que ver con 'AllowMultiple = false'. –

3

Si necesitan tres separada ensu; ¡entonces probablemente deberían estar en tres accesorios separados, cada uno con su propio init!

+0

Schaliasos sugirió un método más arriba. Eso debería estar bien. ¿Ves alguna falla? – Lijo

+2

No .. en realidad no. Siempre que las tres pruebas estén relacionadas lógicamente. Yo personalmente ... Lo dividiría en tres accesorios, pero eso es algo de preferencia personal. Lo anterior se ve bien. ¿Se le requiere hacer una limpieza de prueba también? ¿Se puede usar el mismo enfoque? –

11

si tiene tres métodos de prueba, y cada método tiene su propia inicialización pasos, entonces ¿por qué te mueves inicialización al método que se ejecutará antes de cada prueba? El único beneficio que veo es ese lindo bloque de interruptores, que agrega algunas líneas a su archivo fuente. Pero te da una desventaja: al mirar cualquiera de estos métodos de prueba, no se puede decir realmente en qué contexto se ejecutará el método. Por lo tanto, utilizo el método de inicialización para configurar solo el contexto básico, que realmente es utilizado por todas las pruebas en el dispositivo.

Simplemente mueva la creación de contexto a arrange parte de cada método.

Si tiene varios métodos, que usan contexto común, simplemente extraiga el método, que configurará el contexto para ellos, y llámelo en la parte arrange. También puede dividir cada configuración de contexto en varios pasos y reutilizar esos pasos (como se hace en las herramientas de Dado-Cuando-Ahí como Specflow).

Y, por supuesto, crear diferentes accesorios también la opción.

+1

En el ámbito de las pruebas de carga a través de pruebas de integración, como en el caso de las pruebas de carga una capa de servicio WCF, que quieren que los métodos de prueba para ser lo más limpio posible, debido a que el método de tiempo de ejecución de la prueba es lo que va a ser rastreados. Este es un caso claro en el que mover toda la lógica de inicialización para probar la inicialización es la única manera de hacerlo. –

+1

@DavidRodrigues no solo. Puede crear una clase TestFixture por separado para cada función que esté probando. Será muy simple y su método SetUp no tendrá ningún bloque de interruptores. También iría con algo como SpecFlow para las pruebas de aceptación. Hay buenos métodos dados que están muy bien organizados y pueden reutilizarse. SpecFlow escribe todos los tiempos de ejecución de los pasos en la ventana de salida –

4

Es un poco de un antiguo puesto, pero se le ocurrió la siguiente, que parece funcionar bien: En primer lugar, definir una clase de atributo:

[AttributeUsage(AttributeTargets.Method, Inherited = true)] 
public class InitialiseWithAttribute : Attribute 
{ 
    public string Id { get; private set; } 

    public InitialiseWithAttribute(string id) 
    { 
     Id = id; 
    } 
} 

a continuación, definir un método de extensión de alguna clase de servicios públicos convenientes :

public static bool IsInitialisedWith(this string testName, string value) 
    { 
     bool result = false; 
     Type testClassType = new StackFrame(1).GetMethod().DeclaringType; 
     MethodInfo methodInfo = testClassType.GetMethod(testName); 
     if (methodInfo != null) 
     { 
      InitialiseWithAttribute initialiseWithAttribute = 
       methodInfo.GetCustomAttribute<InitialiseWithAttribute>(true); 
      if (initialiseWithAttribute != null) 
      { 
       result = initialiseWithAttribute.Id == value; 
      } 
     } 
     return result; 
    } 

Ahora escribe sus pruebas, por lo tanto:

public TestContext TestContext {get; set;} 
    [TestInitialize] 
    public void TestInitialise() 
    { 
     if (TestContext.TestName.IsInitalisedWith("DoSomethingSpecial") 
     { 
      // ... Do something special 
     } 
     else 
     { 
      // ... Do something normal 
     } 
    } 

    [TestMethod] 
    [InitialiseWith("DoSomethingSpecial")] 
    public void MySpecialTest() 
    { 
     // The test 
    } 
2

En mi trabajo, presentamos un argumento al método TestInitialize para determinar cómo queremos que funcione la inicialización.

public partial class CommonActions 
{ 
    public void TestInitialize(bool adminTest) 
    { 
     try 
     { 
     if (adminTest) 
     { 
      //do stuff 
     } 

Tenemos una inicialización estándar en la definición de clase, que por defecto es falsa.

[TestClass] 
public class ProjectTestBase : FrameworkTestBase 
{ 
    public CommonActions common { get; set; } = new CommonActions(); 

    [TestInitialize] 
    public void TestInitialize() => common.TestInitialize(false); 

Luego, en los casos de prueba en sí puede anular la TestInitialize para cualquier prueba que desee.

[TestClass] 
public class SetReportsInAdmin : ProjectTestBase 
{ 
    [TestInitialize] 
    public new void TestInitialize() => common.TestInitialize(true); 

se utiliza un booleano para saber si la prueba Admin, que tiene que tener una carga extra para la configuración. Toma esto y aplica las variables que quieras de una manera que te brinde una inicialización múltiple mediante el uso de un método.

Cuestiones relacionadas