Pruebas unitarias y tipos genéricos

Actualización: noviembre 2007

Puede generar las pruebas unitarias para los métodos genéricos exactamente igual que para los demás métodos, como se describe en Cómo: Generar una prueba unitaria. En las secciones siguientes se proporciona información sobre la creación de pruebas unitarias para métodos genéricos y ejemplos de ello.

Argumentos de tipo y restricciones de tipo

Cuando Visual Studio genera una prueba unitaria para una clase genérica, como MyList<T>, genera dos métodos: una aplicación auxiliar genérica y un método de prueba. Si MyList<T> tiene una o más restricciones de tipo, el argumento de tipo debe cumplir todas las restricciones de tipo. Para asegurarse de que el código genérico sometido a prueba funcione según lo esperado para todas las entradas permitidas, el método de prueba llama al método de aplicación auxiliar genérico con todas las restricciones que se desea probar.

Ejemplos

En los ejemplos siguientes se ilustran las pruebas unitarias para los métodos genéricos:

  • Editar código de prueba generado. Este ejemplo incluye dos secciones, una de código de prueba generado y otra de código de prueba editado. Muestra cómo editar el código de prueba sin formato que se genera partiendo de una definición de método genérico para convertirlo en un método de prueba útil.

  • Utilizar una restricción de tipo. En este ejemplo se muestra una prueba unitaria para un método genérico que utiliza una restricción de tipo. En este ejemplo, la restricción del tipo no se cumple.

Ejemplo 1: Editar código de prueba generado

El código de prueba de esta sección prueba un método de código sometido a prueba denominado SizeOfLinkedList(). Este método devuelve un entero que especifica el número de nodos de la lista vinculada.

En el primer ejemplo de código, de la sección Código de prueba generado, se muestra el código de prueba sin editar tal y como lo ha generado Visual Studio Team System Test. En el segundo ejemplo, de la sección Código de prueba editado, se muestra cómo hacer que pruebe el funcionamiento del método SizeOfLinkedList para dos tipos de datos diferentes, int y char.

Este código ilustra dos métodos:

  • un método de aplicación auxiliar de prueba, SizeOfLinkedListTestHelper<T>(). De manera predeterminada, un método de aplicación auxiliar de prueba contiene la cadena "TestHelper" en su nombre.

  • un método de prueba, SizeOfLinkedListTest(). Todos los métodos de prueba se marcan con el atributo TestMethod.

Código de prueba generado

El código de prueba siguiente se generó a partir del método SizeOfLinkedList(). Dado que se trata de una prueba generada sin editar, es preciso modificarla para probar correctamente el método SizeOfLinkedList.

public void SizeOfLinkedListTestHelper<T>()

{

    T val = default(T); // TODO: Initialize to an appropriate value

    MyLinkedList<T> target = new MyLinkedList<T>(val); // TODO: Initialize to an appropriate value

    int expected = 0; // TODO: Initialize to an appropriate value

    int actual;

    actual = target.SizeOfLinkedList();

    Assert.AreEqual(expected, actual);

    Assert.Inconclusive("Verify the correctness of this test method.");

}

[TestMethod()]

public void SizeOfLinkedListTest()

{

   SizeOfLinkedListTestHelper<GenericParameterHelper>();

}

En el código anterior, el parámetro de tipo genérico es GenericParameterHelper. Aunque que puede editarlo para proporcionar tipos de datos concretos, como se muestra en el ejemplo siguiente, podría ejecutar la prueba sin editar esta instrucción.

Código de prueba editado

En el código siguiente, el método de prueba y el método de aplicación auxiliar de prueba se han editado para que prueben correctamente el método SizeOfLinkedList() de código sometido a prueba.

Método de aplicación auxiliar de prueba

El método de aplicación auxiliar de prueba realiza los pasos siguientes, que corresponden a las líneas del código etiquetadas como step 1 (paso 1) hasta step 5 (paso 5).

  1. Cree una lista vinculada genérica.

  2. Anexe cuatro nodos a la lista vinculada. El tipo de datos del contenido de estos nodos es desconocido.

  3. Asigne el tamaño esperado de la lista vinculada a la variable expected.  

  4. Calcule el tamaño real de la lista vinculada y asígneselo a la variable actual.

  5. Compare actual con expected en una instrucción Assert. Si el valor real no es igual al esperado, la prueba no se supera.

Método de prueba

El método de prueba se compila en el código al que se llama al ejecutar la prueba denominada SizeOfLinkedListTest. Realiza los pasos siguientes, que corresponden a las líneas en del código que están etiquetadas como step 6 (paso 6) y step 7 (paso 7).

  1. Especifique <int> al llamar al método de aplicación auxiliar de prueba, para comprobar que la prueba funciona para las variables integer.

  2. Especifique <char> al llamar al método de aplicación auxiliar de prueba, para comprobar que la prueba funciona para las variables char.  

public void SizeOfLinkedListTestHelper<T>()
{
    T val = default(T); 
    MyLinkedList<T> target = new MyLinkedList<T>(val); // step 1
    for (int i = 0; i < 4; i++) // step 2
    {
        MyLinkedList<T> newNode = new MyLinkedList<T>(val);
        target.Append(newNode);
    }
    int expected = 5; // step 3
    int actual;
    actual = target.SizeOfLinkedList(); // step 4
    Assert.AreEqual(expected, actual); // step 5
}

[TestMethod()]
public void SizeOfLinkedListTest() 
{
    SizeOfLinkedListTestHelper<int>();  // step 6
    SizeOfLinkedListTestHelper<char>(); // step 7
}
Nota:

Cada vez que se ejecuta la prueba SizeOfLinkedListTest, se llama dos veces al método TestHelper correspondiente. La instrucción ASSERT debe evaluarse en True cada vez para que se supere la prueba. Si la prueba no se supera, puede que no esté claro si el motivo reside en la llamada que especificó <int> o en la llamada que especificó <char>. Para hallar la respuesta, puede examinar la pila de llamadas o establecer puntos de interrupción en el método de prueba y, a continuación, depurar mientras se ejecuta la prueba. Para obtener más información, consulte Cómo: Depurar mientras se ejecuta una prueba en una solución ASP.NET.

Ejemplo 2: Utilizar una restricción de tipo

En este ejemplo se muestra una prueba unitaria para un método genérico que utiliza una restricción de tipo que no se cumple. En la primera sección se muestra código del proyecto de código sometido a prueba. Se resalta la restricción de tipo.

En la segunda sección se muestra el código del proyecto de prueba.

Proyecto de código sometido a prueba

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary2
{
    public class Employee
    {
        public Employee(string s, int i)
        {
        }
    }

    public class GenericList<T> where T : Employee
    {
        private class Node
        {
            private T data;
            public T Data
            {
                get { return data; }
                set { data = value; }
            }
        }
    }
}

Proyecto de prueba

Al igual que sucede con todas las pruebas unitarias recién generadas, debe agregar instrucciones ASSERT no inconclusas a esta prueba unitaria para que devuelva resultados útiles. No se agregan al método marcado con el atributo TestMethod, sino al método "TestHelper", que en esta prueba se denomina DataTestHelper<T>().

En este ejemplo, el parámetro de tipo genérico T tiene la restricción where T : Employee. Esta restricción no se cumple en el método de prueba. Por consiguiente, el método DataTest() contiene una instrucción ASSERT que comunica al programador que es preciso proporcionar la restricción de tipo aplicada a T. El mensaje de esta instrucción Assert es el siguiente: ("No appropriate type parameter is found to satisfies the type constraint(s) of T. " + "Please call DataTestHelper<T>() with appropriate type parameters.");

En otras palabras, al llamar al método DataTestHelper<T>() desde el método de prueba, DataTest(), debe pasar un parámetro de tipo Employee o una clase derivada de Employee.

using ClassLibrary2;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestProject1

{
    [TestClass()]
    public class GenericList_NodeTest
    {
    
        public void DataTestHelper<T>()
            where T : Employee
        {
            GenericList_Shadow<T>.Node target = new GenericList_Shadow<T>.Node(); // TODO: Initialize to an appropriate value
            T expected = default(T); // TODO: Initialize to an appropriate value
            T actual;
            target.Data = expected;
            actual = target.Data;
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("Verify the correctness of this test method.");
        }

        [TestMethod()]
        public void DataTest()
        {
            Assert.Inconclusive("No appropriate type parameter is found to satisfies the type constraint(s) of T. " +
            "Please call DataTestHelper<T>() with appropriate type parameters.");
        }
    }
}

Vea también

Otros recursos

Información general de pruebas unitarias

Crear pruebas unitarias