Compartir a través de


Creación de una prueba unitaria controlada por datos

Puede usar el marco de pruebas unitarias de Microsoft (MSTest) para código administrado para configurar un método de prueba unitaria para recuperar valores de un origen de datos. El método se ejecuta sucesivamente para cada fila del origen de datos, lo que facilita la prueba de una variedad de entradas mediante un único método.

Una prueba unitaria controlada por datos puede usar cualquiera de los siguientes tipos:

  • datos insertados con el atributo DataRow
  • datos de usuario usando el atributo DynamicData
  • de algún proveedor de origen conocido con el atributo DataSource

Método sometido a prueba

Por ejemplo, supongamos que tú tienes:

  1. Una solución denominada MyBank que acepta y procesa transacciones para distintos tipos de cuentas.

  2. Un proyecto de MyBank denominado BankDb que administra las transacciones de las cuentas.

  3. Una clase denominada Maths en el proyecto de BankDb que realiza las funciones matemáticas para asegurarse de que cualquier transacción sea ventajosa para el banco.

  4. Un proyecto de prueba unitaria denominado BankDbTests para probar el comportamiento del componente BankDb.

  5. Una clase de prueba unitaria denominada MathsTests para comprobar el comportamiento de la clase Maths.

Probaremos un método en Maths que agrega dos enteros mediante un bucle :

public int AddIntegers(int first, int second)
{
    int sum = first;
    for (int i = 0; i < second; i++)
    {
        sum += 1;
    }

    return sum;
}

Probar el método de prueba

Prueba controlada por datos insertada

Para las pruebas en línea, MSTest usa DataRow para especificar los valores utilizados por la prueba impulsada por datos. La prueba de este ejemplo se ejecuta sucesivamente para cada fila de datos.

[TestMethod]
[DataRow(1, 1, 2)]
[DataRow(2, 2, 4)]
[DataRow(3, 3, 6)]
[DataRow(0, 0, 1)] // The test run with this row fails
public void AddIntegers_FromDataRowTest(int x, int y, int expected)
{
    var target = new Maths();
    int actual = target.AddIntegers(x, y);
    Assert.AreEqual(expected, actual,
        "x:<{0}> y:<{1}>",
        new object[] {x, y});
}

Prueba impulsada por datos de miembros

MSTest usa DynamicData atributo para especificar el nombre, el tipo y la definición (se usa de forma predeterminada el tipo actual) del miembro que proporcionará los datos utilizados por la prueba controlada por datos.

Nota

Antes de MSTest 3.8, DynamicDataSourceType enumeración tenía dos miembros, Property y Method. El valor predeterminado era Property. A partir de MSTest 3.8, se agrega un nuevo miembro AutoDetect a la enumeración y es el valor predeterminado. Por lo tanto, ya no es necesario especificar DynamicDataSourceType.

public static IEnumerable<object[]> AdditionData
{
    get
    {
        return new[]
        { 
            new object[] { 1, 1, 2 },
            new object[] { 2, 2, 4 },
            new object[] { 3, 3, 6 },
            new object[] { 0, 0, 1 }, // The test run with this row fails
        };
    }
}

[TestMethod]
[DynamicData(nameof(AdditionData))]
public void AddIntegers_FromDynamicDataTest(int x, int y, int expected)
{
    var target = new Maths();
    int actual = target.AddIntegers(x, y);
    Assert.AreEqual(expected, actual,
        "x:<{0}> y:<{1}>",
        new object[] {x, y});
}

También se puede reemplazar el nombre para mostrar generado de forma predeterminada mediante la propiedad DynamicDataDisplayName del atributo DynamicData. La signatura de método del nombre para mostrar debe ser public static string y aceptar dos parámetros, el primero de tipo MethodInfo y el segundo de tipo object[].

public static string GetCustomDynamicDataDisplayName(MethodInfo methodInfo, object[] data)
{
    return string.Format("DynamicDataTestMethod {0} with {1} parameters", methodInfo.Name, data.Length);
}

[DynamicData(nameof(AdditionData), DynamicDataDisplayName = nameof(GetCustomDynamicDataDisplayName))]

Prueba controlada por datos del proveedor de origen

La creación de una prueba unitaria controlada por orígenes de datos implica los pasos siguientes:

  1. Cree un origen de datos que contenga los valores que se usan en el método de prueba. El origen de datos puede ser cualquier tipo registrado en la máquina que ejecuta la prueba.

  2. Agregue una propiedad TestContext pública de tipo TestContext a la clase de prueba.

  3. Creación de un método de prueba unitaria

  4. Agregue un atributo DataSourceAttribute a él.

  5. Usa la propiedad indexador DataRow para recuperar los valores que utilizas en una prueba.

Crear un origen de datos

Para probar el método AddIntegers, cree un origen de datos que especifique un intervalo de valores para los parámetros y la suma que espera que se devuelva. En este ejemplo, crearemos una base de datos de Sql Compact denominada MathsData y una tabla denominada AddIntegersData que contenga los siguientes nombres y valores de columna.

FirstNumber SecondNumber Sum
0 1 1
1 1 2
2 -3 -1

Adición de testContext a la clase de prueba

El marco de pruebas unitarias crea un objeto TestContext para almacenar la información del origen de datos para una prueba controlada por datos. A continuación, el marco establece este objeto como el valor de la propiedad TestContext que cree.

public TestContext TestContext { get; set; }

En el método de prueba, accede a los datos a través de la propiedad de indizador DataRow del TestContext.

Nota

.NET Core no admite el atributo DataSource. Si intenta acceder a los datos de prueba de esta manera en un proyecto de prueba unitaria de .NET Core, UWP o WinUI, verá un error similar a "'TestContext' no contiene una definición para 'DataRow' y no se puede encontrar ningún método de extensión accesible 'DataRow' que acepte un primer argumento del tipo 'TestContext' (¿falta una directiva using o una referencia de ensamblado?)".

Escribir el método de prueba

El método de prueba para AddIntegers es bastante sencillo. Para cada fila del origen de datos, llame a AddIntegers con los valores de las columnas FirstNumber y SecondNumber como parámetros, y compruebe el valor devuelto contra el valor de la columna Sum.

[TestMethod]
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0; Data Source=C:\Data\MathsData.sdf;", "Numbers")]
public void AddIntegers_FromDataSourceTest()
{
    var target = new Maths();

    // Access the data
    int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
    int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
    int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
    int actual = target.AddIntegers(x, y);
    Assert.AreEqual(expected, actual,
        "x:<{0}> y:<{1}>",
        new object[] {x, y});
}

Especificar el DataSourceAttribute

El atributo DataSource especifica la cadena de conexión para el origen de datos y el nombre de la tabla que se usa en el método de prueba. La información exacta de la cadena de conexión difiere, dependiendo del tipo de origen de datos que use. En este ejemplo, usamos una base de datos SqlServerCe.

[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0;Data Source=C:\Data\MathsData.sdf", "AddIntegersData")]

Advertencia

La cadena de conexión puede contener datos confidenciales (por ejemplo, una contraseña). La cadena de conexión se almacena en texto sin formato en el código fuente y en el ensamblado compilado. Restrinja el acceso al código fuente y al ensamblado para proteger esta información confidencial.

El atributo DataSource tiene tres constructores.

[DataSource(dataSourceSettingName)]

Un constructor con un parámetro usa información de conexión que se almacena en el archivo app.config para la solución. El dataSourceSettingsName es el nombre del elemento Xml en el archivo de configuración que especifica la información de conexión.

El uso de un archivo app.config permite cambiar la ubicación del origen de datos sin realizar cambios en la propia prueba unitaria. Para obtener información sobre cómo crear y usar un archivo de app.config, consulte Tutorial: Uso de un archivo de configuración para definir un origen de datos

[DataSource(connectionString, tableName)]

El constructor DataSource con dos parámetros especifica la cadena de conexión para el origen de datos y el nombre de la tabla que contiene los datos del método de prueba.

Las cadenas de conexión dependen del tipo del tipo de origen de datos, pero debe contener un elemento Provider que especifique el nombre invariable del proveedor de datos.

[DataSource(
    dataProvider,
    connectionString,
    tableName,
    dataAccessMethod
    )]

Uso de TestContext.DataRow para acceder a los datos

Para acceder a los datos de la tabla AddIntegersData, use el indexador TestContext.DataRow. DataRow es un objeto DataRow, por lo que puedes obtener los valores de columna mediante índices o nombres de columna. Dado que los valores se devuelven como objetos, conviértalos en el tipo adecuado:

int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);

Ejecución de la prueba y visualización de los resultados

Cuando haya terminado de escribir un método de prueba, compile el proyecto de prueba. El método de prueba aparece en Test Explorer en el grupo Not Run Tests. Al ejecutar, escribir y volver a ejecutar las pruebas, el Explorador de pruebas muestra los resultados en los grupos de Pruebas no superadas, Pruebas superadas y Pruebas no ejecutadas. Puede elegir Ejecutar todo para ejecutar todas las pruebas o elegir Ejecutar para elegir un subconjunto de pruebas que se van a ejecutar.

La barra de resultados de la prueba en la parte superior de Explorador de pruebas se anima a medida que se ejecuta la prueba. Al final de la ejecución de pruebas, la barra estará verde si todas las pruebas han superado o rojo si se ha producido algún error en alguna de las pruebas. Un resumen de la ejecución de la prueba aparece en el panel de detalles de la parte inferior de la ventana Explorador de pruebas. Seleccione una prueba para ver los detalles de esa prueba en el panel inferior.

Nota

Hay un resultado para cada fila de datos y también un resultado de resumen. Si la prueba se supera en cada fila de datos, el resumen de la ejecución se mostrará como Superado. Si se produjo un error en la prueba en cualquier fila de datos, la ejecución de resumen se muestra como Error.

Si ha ejecutado el método AddIntegers_FromDataRowTest, AddIntegers_FromDynamicDataTest o AddIntegers_FromDataSourceTest del ejemplo, la barra de resultados se vuelve roja y el método de prueba se mueve al grupo Pruebas no superadas. Se produce un error en una prueba controlada por datos si se produce un error en alguno de los métodos iterados del origen de datos. Al elegir una prueba basada en datos que ha fallado en la ventana Test Explorer, el panel de detalles muestra los resultados de cada iteración identificada por el índice de fila de datos. En nuestro ejemplo, parece que el algoritmo de AddIntegers no controla correctamente los valores negativos.

Cuando se corrige el método de prueba y se vuelve a ejecutar la prueba, la barra de resultados se vuelve verde y el método de prueba se traslada al grupo prueba superada.