¿MSTest tiene un equivalente al TestCase de NUnit?

107

Encuentro la TestCasefunción en NUnit bastante útil como una forma rápida de especificar parámetros de prueba sin necesidad de un método separado para cada prueba. ¿Hay algo similar en MSTest?

 [TestFixture]  
 public class StringFormatUtilsTest  
 {  
     [TestCase("tttt", "")]  
     [TestCase("", "")]  
     [TestCase("t3a4b5", "345")]  
     [TestCase("3&5*", "35")]  
     [TestCase("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 }  
tjjjohnson
fuente
¿Por qué no usas NUnit?
Mike de Klerk
1
@MikedeKlerk: Nunit es increíblemente lento si está utilizando Entity Framework ... Aparentemente, se refleja en todas sus clases generadas cada vez que ejecuta una prueba.
Robert Harvey
En términos generales, NUnit tiene más características que MSTest, si está utilizando MSTest sólo para ser capaz de ejecutar las pruebas con el Explorador de prueba VS, a continuación, puede hacer lo mismo con NUnit mediante la instalación de la extensión de adaptador de pruebas NUnit través NuGet
Stacked
1
Pruebe DataRow(), consulte: blogs.msdn.microsoft.com/devops/2016/06/17/…
Babak

Respuestas:

62

Microsoft anunció recientemente "MSTest V2" (ver artículo de blog ). Esto le permite utilizar de forma coherente (escritorio, UWP, ...) el DataRowatributo-!

 [TestClass]  
 public class StringFormatUtilsTest  
 {  
     [DataTestMethod]  
     [DataRow("tttt", "")]  
     [DataRow("", "")]  
     [DataRow("t3a4b5", "345")]  
     [DataRow("3&5*", "35")]  
     [DataRow("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 } 

Una vez más, el Explorador de pruebas de Visual Studio Express desafortunadamente no reconoce estas pruebas. ¡Pero al menos las versiones "completas" de VS ahora admiten esa característica!

Para usarlo, simplemente instale los paquetes NuGet MSTest.TestFramework y MSTest.TestAdapter (ambos en versión preliminar a partir de ahora).

Respuesta anterior:

Si no tiene que seguir con MSTest y solo lo está usando para poder ejecutar las pruebas a través del Explorador de pruebas porque solo tienes una edición de Visual Studio Express, entonces esta podría ser una solución para ti:

Existe la extensión VsTestAdapter VSIX para poder ejecutar pruebas NUnit a través de Test Explorer. Desafortunadamente, los usuarios de VS Express no pueden instalar extensiones ... ¡Pero afortunadamente el VsTestAdapter también viene con un paquete NuGet simple !

Por lo tanto, si es un usuario de VS Express, simplemente instale VsTestAdapter NuGet-Package y disfrute ejecutando sus pruebas / casos de prueba NUnit a través de Test Explorer.


Desafortunadamente, la declaración antes mencionada no es cierta. Si bien es perfectamente posible instalar el paquete a través de una edición Express, es inútil, ya que no puede utilizar el Explorador de pruebas. Anteriormente, había una nota al margen sobre una versión anterior de TestAdapter, que se eliminó de la página de descripción de 2.0.0 :

Tenga en cuenta que no funciona con VS Express

khlr
fuente
4
MSTest "v2" es ahora el marco predeterminado cuando se usa VS 2017. Ahora que esto será compatible con OOTB en la última versión, esa información probablemente debería ir al principio de la respuesta.
Marc L.
34

Sé que esta es una respuesta tardía, pero espero que ayude a otros.

Busqué por todas partes una solución elegante y terminé escribiendo una yo mismo. Lo usamos en más de 20 proyectos con miles de pruebas unitarias y cientos de miles de iteraciones. Ni una sola vez se perdió el ritmo.

https://github.com/Thwaitesy/MSTestHacks

1) Instale el paquete NuGet .

2) Herede su clase de prueba de TestBase

public class UnitTest1 : TestBase
{ }

3) Cree una propiedad, campo o método que devuelva IEnumerable

[TestClass]
public class UnitTest1 : TestBase
{
    private IEnumerable<int> Stuff
    {
        get
        {
            //This could do anything, get a dynamic list from anywhere....
            return new List<int> { 1, 2, 3 };
        }
    }
}

4) Agregue el atributo MSTest DataSource a su método de prueba, apuntando al nombre IEnumerable anterior. Esto debe estar completamente calificado.

[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
    var number = this.TestContext.GetRuntimeDataSourceObject<int>();

    Assert.IsNotNull(number);
}

Resultado final: 3 iteraciones como el DataSource normal :)

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MSTestHacks;

namespace Namespace
{
    [TestClass]
    public class UnitTest1 : TestBase
    {
        private IEnumerable<int> Stuff
        {
            get
            {
                //This could do anything, get a dynamic list from anywhere....
                return new List<int> { 1, 2, 3 };
            }
        }

        [TestMethod]
        [DataSource("Namespace.UnitTest1.Stuff")]
        public void TestMethod1()
        {
            var number = this.TestContext.GetRuntimeDataSourceObject<int>();

            Assert.IsNotNull(number);
        }
    }
}
Thwaitesy
fuente
¿Funcionaría esto también con múltiples parámetros para cada caso?
Lonefish
Debido a que hubo un cambio en la biblioteca subyacente, esto no funciona con MsTest "v2" . Este es el valor predeterminado para VS15 (VS 2017).
Marc L.
3
Sí, si está utilizando MSTest V2, hay un nuevo proveedor de casos de prueba que es similar al de NUnit. Por lo tanto, no es necesario este trabajo
Thwaitesy
Esto no parece funcionar en VS 2015, el archivo de configuración de la aplicación no se completa dinámicamente y, por lo tanto, no se encuentran las
Reed
13

Sé que esta es otra respuesta tardía, pero en mi equipo que está comprometido con el uso del marco de prueba de MS, desarrollamos una técnica que se basa solo en tipos anónimos para almacenar una matriz de datos de prueba y LINQ para recorrer y probar cada fila. No requiere clases o marcos adicionales, y tiende a ser bastante fácil de leer y comprender. También es mucho más fácil de implementar que las pruebas basadas en datos que utilizan archivos externos o una base de datos conectada.

Por ejemplo, digamos que tiene un método de extensión como este:

public static class Extensions
{
    /// <summary>
    /// Get the Qtr with optional offset to add or subtract quarters
    /// </summary>
    public static int GetQuarterNumber(this DateTime parmDate, int offset = 0)
    {
        return (int)Math.Ceiling(parmDate.AddMonths(offset * 3).Month / 3m);
    }
}

Puede usar una matriz de tipos anónimos combinados con LINQ para escribir pruebas como esta:

[TestMethod]
public void MonthReturnsProperQuarterWithOffset()
{
    // Arrange
    var values = new[] {
        new { inputDate = new DateTime(2013, 1, 1), offset = 1, expectedQuarter = 2},
        new { inputDate = new DateTime(2013, 1, 1), offset = -1, expectedQuarter = 4},
        new { inputDate = new DateTime(2013, 4, 1), offset = 1, expectedQuarter = 3},
        new { inputDate = new DateTime(2013, 4, 1), offset = -1, expectedQuarter = 1},
        new { inputDate = new DateTime(2013, 7, 1), offset = 1, expectedQuarter = 4},
        new { inputDate = new DateTime(2013, 7, 1), offset = -1, expectedQuarter = 2},
        new { inputDate = new DateTime(2013, 10, 1), offset = 1, expectedQuarter = 1},
        new { inputDate = new DateTime(2013, 10, 1), offset = -1, expectedQuarter = 3}
        // Could add as many rows as you want, or extract to a private method that
        // builds the array of data
    }; 
    values.ToList().ForEach(val => 
    { 
        // Act 
        int actualQuarter = val.inputDate.GetQuarterNumber(val.offset); 
        // Assert 
        Assert.AreEqual(val.expectedQuarter, actualQuarter, 
            "Failed for inputDate={0}, offset={1} and expectedQuarter={2}.", val.inputDate, val.offset, val.expectedQuarter); 
        }); 
    }
}

Al usar esta técnica, es útil usar un mensaje formateado que incluya los datos de entrada en la afirmación para ayudarlo a identificar qué fila hace que la prueba falle.

He escrito en un blog sobre esta solución con más antecedentes y detalles en AgileCoder.net .

Gary.Ray
fuente
4
El mayor problema con esto es que si algún caso falla fuera de la matriz de valores, toda la prueba falla y no se prueban más casos.
ytoledano
Esto crea casos de prueba que pueden influirse entre sí.
BartoszKP
@BartoszKP Solo si el sistema bajo prueba tiene efectos secundarios, en cuyo caso probablemente esta no sea una técnica óptima.
Gary.Ray
@ Gary.Ray también cuando el sistema no tiene efectos secundarios aún . Además, cuando una prueba no pasa y otro desarrollador intenta solucionarlo, y pierde horas tratando de averiguar si la dependencia es importante o no. Esto es algo que no deberías hacer nunca, punto.
BartoszKP
Suficientemente bueno. +1
Trey Mack
7

Khlr dio buenas explicaciones detalladas y aparentemente este enfoque comenzó a funcionar en VS2015 Express para escritorio. Traté de dejar el comentario, pero mi falta de reputación no me permitió hacerlo.

Déjame copiar la solución aquí:

[TestClass]  
 public class StringFormatUtilsTest  
 {  
     [TestMethod]  
     [DataRow("tttt", "")]  
     [DataRow("", "")]  
     [DataRow("t3a4b5", "345")]  
     [DataRow("3&amp;amp;5*", "35")]  
     [DataRow("123", "123")]  
     public void StripNonNumeric(string before, string expected)  
     {  
         string actual = FormatUtils.StripNonNumeric(before);  
         Assert.AreEqual(expected, actual);  
     }  
 } 

Para usarlo, simplemente instale los paquetes NuGet MSTest.TestFramework y MSTest.TestAdapter .

Un problema es

Error CS0433 El tipo 'TestClassAttribute' existe tanto en 'Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version = 10.0.0.0 como en' Microsoft.VisualStudio.TestPlatform.TestFramework, Version = 14.0.0.0

Por lo tanto, elimine Microsoft.VisualStudio.QualityTools.UnitTestFramework de las referencias del proyecto.

Le invitamos a editar la respuesta original y eliminar esta.

Arte
fuente
0

MSTest tiene el atributo DataSource, que te permitirá alimentarlo con una tabla de base de datos, csv, xml, etc. Lo he usado y funciona bien. No conozco una forma de poner los datos justo arriba como atributos como en su pregunta, pero es muy fácil configurar las fuentes de datos externas y los archivos se pueden incluir en el proyecto. Lo tuve funcionando una hora desde que comencé, y no soy un experto en pruebas automatizadas.

https://msdn.microsoft.com/en-us/library/ms182527.aspx?f=255&MSPPError=-2147217396 tiene un tutorial completo basado en la entrada de la base de datos.

http://www.rhyous.com/2015/05/11/row-tests-or-paramerterized-tests-mstest-xml/ tiene un tutorial basado en la entrada de archivos XML.

CindyH
fuente