Introducción a Live Unit Testing

Live Unit Testing, cuando se habilita en una solución de Visual Studio, representa visualmente la cobertura y el estado de las pruebas. Live Unit Testing también ejecuta dinámicamente pruebas cada vez que modifica el código y le notifica inmediatamente cuando sus cambios provocan un error en las pruebas.

Live Unit Testing puede utilizarse para probar soluciones que tienen como destino .NET Framework, .NET Core o .NET 5+. En este tutorial, obtendrá información sobre cómo utilizar Live Unit Testing mediante la creación de una biblioteca de clases sencilla que tiene como destino .NET y podrá crear un proyecto de MSTest, cuyo destino es .NET, para probarlo.

La solución completa de C# puede descargarse desde el repositorio MicrosoftDocs/visualstudio-docs en GitHub.

Requisitos previos

Este tutorial exige la instalación previa de Visual Studio Enterprise con la carga de trabajo del desarrollo para escritorio de .NET.

Creación de la solución y del proyecto de biblioteca de clases

Empiece por crear una solución de Visual Studio denominada UtilityLibraries que conste de un solo proyecto de biblioteca de clases de .NET, StringLibrary.

La solución es simplemente un contenedor para uno o varios proyectos. Para crear una solución en blanco, abra Visual Studio y haga lo siguiente:

  1. Seleccione Archivo>Nuevo>Proyecto en el menú de nivel superior de Visual Studio.

  2. Escriba solución en el cuadro de búsqueda de la plantilla y luego seleccione la plantilla Solución en blanco. Asigne el nombre UtilityLibraries al proyecto.

  3. Termine de crear la solución.

Ahora que ha creado la solución, podrá crear una biblioteca de clases denominada StringLibrary que contenga una serie de métodos de extensión para trabajar con cadenas.

  1. En el Explorador de soluciones, haga clic con el botón derecho en la solución UtilityLibraries y seleccione Agregar>Nuevo proyecto.

  2. Escriba biblioteca de clases en el cuadro de búsqueda de la plantilla y seleccione la plantilla Biblioteca de clases que tiene como destino .NET o .NET Standard. Haga clic en Next.

  3. Asigne al proyecto el nombre StringLibrary.

  4. Haga clic en Crear para crear el proyecto.

  5. Reemplace todo el código existente en el editor de código por el siguiente:

    using System;
    
    namespace UtilityLibraries
    {
        public static class StringLibrary
        {
            public static bool StartsWithUpper(this string s)
            {
                if (String.IsNullOrWhiteSpace(s))
                    return false;
    
                return Char.IsUpper(s[0]);
            }
    
            public static bool StartsWithLower(this string s)
            {
                if (String.IsNullOrWhiteSpace(s))
                    return false;
    
                return Char.IsLower(s[0]);
            }
    
            public static bool HasEmbeddedSpaces(this string s)
            {
                foreach (var ch in s.Trim())
                {
                    if (ch == ' ')
                        return true;
                }
                return false;
            }
        }
    }
    

    StringLibrary tiene tres métodos estáticos:

    • StartsWithUpper devuelve true si una cadena comienza por una letra mayúscula; en caso contrario, devuelve false.

    • StartsWithLower devuelve true si una cadena comienza por una letra minúscula; en caso contrario, devuelve false.

    • HasEmbeddedSpaces devuelve true si una cadena contiene un espacio en blanco insertado; en caso contrario, devuelve false.

  6. Seleccione Compilar>Compilar solución en el menú de nivel superior de Visual Studio. La compilar debería ser correcta.

Crear el proyecto de prueba

El paso siguiente consiste en crear el proyecto de prueba unitaria para probar la biblioteca StringLibrary. Siga estos pasos para crear las pruebas unitarias:

  1. En el Explorador de soluciones, haga clic con el botón derecho en la solución UtilityLibraries y seleccione Agregar>Nuevo proyecto.

  2. Escriba prueba unitaria en el cuadro de búsqueda de plantillas, seleccione C# como lenguaje y luego seleccione Proyecto de prueba unitaria de MSTest para la plantilla de .NET. Haga clic en Next.

    Nota:

    En Visual Studio 2019 versión 16.9, el nombre de la plantilla de proyecto MSTest es Proyecto de prueba unitaria.

  3. Asigne al proyecto el nombre StringLibraryTests y haga clic en Siguiente.

  4. Seleccione la plataforma de destino recomendada o .NET 8 y, después, elija Crear.

    Nota:

    En este tutorial de introducción, Live Unit Testing se utiliza con el marco de pruebas de MSTest. También puede usar los marcos de pruebas de xUnit y NUnit.

  5. El proyecto de prueba unitaria no puede acceder automáticamente a la biblioteca de clases que está probando. Para conceder acceso a la biblioteca de prueba, agregue una referencia al proyecto de biblioteca de clases. Para ello, haga clic con el botón secundario en el proyecto StringLibraryTests y seleccione Agregar>Referencia de proyecto. En el cuadro de diálogo Administrador de referencias, asegúrese de que la pestaña Solución esté seleccionada y elija el proyecto StringLibrary, como se muestra en la ilustración siguiente.

    The Reference Manager dialog

    The Reference Manager dialog

  6. Reemplace el código de prueba unitaria reutilizable que proporciona la plantilla por el código siguiente:

    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using UtilityLibraries;
    
    namespace StringLibraryTest
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestStartsWithUpper()
            {
                // Tests that we expect to return true.
                string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва" };
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsTrue(result,
                                  $"Expected for '{word}': true; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void TestDoesNotStartWithUpper()
            {
                // Tests that we expect to return false.
                string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство",
                                   "1234", ".", ";", " " };
                foreach (var word in words)
                {
                    bool result = word.StartsWithUpper();
                    Assert.IsFalse(result,
                                   $"Expected for '{word}': false; Actual: {result}");
                }
            }
    
            [TestMethod]
            public void DirectCallWithNullOrEmpty()
            {
                // Tests that we expect to return false.
                string[] words = { String.Empty, null };
                foreach (var word in words)
                {
                    bool result = StringLibrary.StartsWithUpper(word);
                    Assert.IsFalse(result,
                                   $"Expected for '{(word == null ? "<null>" : word)}': " +
                                   $"false; Actual: {result}");
                }
            }
        }
    }
    
  7. Guarde el proyecto seleccionando el icono Guardar de la barra de herramientas.

    Como el código de prueba unitaria incluye algunos caracteres que no son ASCII, verá el cuadro de diálogo siguiente en el que se advierte de que algunos caracteres se perderán si el archivo se guarda en el formato ASCII predeterminado.

  8. Elija el botón Guardar con otra codificación.

    Choose a file encoding

    Choose a file encoding

  9. En la lista desplegable Codificación del cuadro de diálogo Opciones avanzadas para guardar, elija Unicode (UTF-8 sin signatura) - Página de códigos 65001, como se muestra en la ilustración siguiente:

    Choosing the UTF-8 encoding

  10. Para compilar el proyecto de prueba unitaria, seleccione Compilar>Recompilar solución en el menú de nivel superior de Visual Studio.

Ha creado una biblioteca de clases, así como algunas pruebas unitarias la misma. Ya ha completado los pasos preliminares necesarios para utilizar Live Unit Testing.

Habilitar Live Unit Testing

Hasta ahora, aunque ha escrito las pruebas para la biblioteca de clases StringLibrary, no las ha ejecutado. Live Unit Testing las ejecuta automáticamente una vez que lo habilite. Para ello, haga lo siguiente:

  1. Si quiere, seleccione la ventana del editor de código que contiene el código para StringLibrary. Se trata de Class1.cs para un proyecto de C# o de Class1.vb para un proyecto de Visual Basic. Este paso le permite inspeccionar visualmente el resultado de las pruebas y el alcance de la cobertura de código una vez que habilite Live Unit Testing.

  2. Seleccione Prueba>Live Unit Testing>Iniciar en el menú de nivel superior de Visual Studio.

  3. Compruebe la configuración de Live Unit Testing asegurándose de que la raíz del repositorio incluye la ruta de acceso a los archivos de origen para el proyecto de utilidad y el proyecto de prueba. Seleccione Next (Siguiente) y Finish (Finalizar).

  1. En la ventana Live Unit Testing, seleccione el vínculo incluir todas las pruebas. (O bien seleccione el icono del botón Lista de reproducción y, luego, seleccione StringLibraryTest, que selecciona todas las pruebas por debajo. A continuación, anule la selección del botón Lista de reproducción para salir del modo de edición).

  2. Visual Studio recompilará el proyecto e iniciará Live Unit Test, que ejecuta automáticamente todas las pruebas.

  1. Visual Studio recompilará el proyecto e iniciará Live Unit Test, que ejecuta automáticamente todas las pruebas.

Cuando se termina de ejecutar las pruebas, en Live Unit Testing se muestran los resultados globales y el resultado de las pruebas individuales. Además, en la ventana del editor de código se muestra gráficamente la cobertura del código de prueba y el resultado de las pruebas. Como se muestra en la ilustración siguiente, las tres pruebas se han ejecutado correctamente. También muestra que nuestras pruebas han cubierto todas las rutas de acceso de código en el método StartsWithUpper y que esas pruebas se han ejecutado correctamente (lo que se indica mediante la marca de verificación de color verde, "✓"). Por último, muestra que ninguno de los otros métodos de StringLibrary tiene cobertura de código (lo que se indica mediante una línea azul, "➖").

The Live Test Explorer and code editor window after starting Live Unit testing

The Live Test Explorer and code editor window after starting Live Unit testing

También puede obtener información más detallada sobre la cobertura y los resultados de las pruebas si selecciona un icono de cobertura de código determinado en la ventana del editor de código. Para examinar este detalle, haga lo siguiente:

  1. Haga clic en la marca de verificación verde situada en la línea if (String.IsNullOrWhiteSpace(s)) del método StartsWithUpper. Como se muestra en la ilustración siguiente, Live Unit Testing indica que las tres pruebas cubren esa línea de código y que todas se han ejecutado correctamente.

    Code coverage for the if conditional statement

    Code coverage for the if conditional statement

  2. Haga clic en la marca de verificación verde situada en la línea return Char.IsUpper(s[0]) del método StartsWithUpper. Como se muestra en la ilustración siguiente, Live Unit Testing indica que solo dos pruebas cubren esa línea de código y que todas se han ejecutado correctamente.

    Code coverage for the return statement

    Code coverage for the return statement

El problema principal que Live Unit Testing identifica es la cobertura de código incompleta. Este tema se tratará en la sección siguiente.

Expandir la cobertura de pruebas

En esta sección, podrá ampliar las pruebas unitarias al método StartsWithLower. Al hacerlo, Live Unit Testing continuará dinámicamente para probar el código.

Para ampliar la cobertura de código al método StartsWithLower, haga lo siguiente:

  1. Agregue los métodos TestStartsWithLower y TestDoesNotStartWithLower al archivo de código fuente de prueba del proyecto:

    // Code to add to UnitTest1.cs
    [TestMethod]
    public void TestStartsWithLower()
    {
        // Tests that we expect to return true.
        string[] words = { "alphabet", "zebra", "abc", "αυτοκινητοβιομηχανία", "государство" };
        foreach (var word in words)
        {
            bool result = word.StartsWithLower();
            Assert.IsTrue(result,
                          $"Expected for '{word}': true; Actual: {result}");
        }
    }
    
    [TestMethod]
    public void TestDoesNotStartWithLower()
    {
        // Tests that we expect to return false.
        string[] words = { "Alphabet", "Zebra", "ABC", "Αθήνα", "Москва",
                           "1234", ".", ";", " "};
        foreach (var word in words)
        {
            bool result = word.StartsWithLower();
            Assert.IsFalse(result,
                           $"Expected for '{word}': false; Actual: {result}");
        }
    }
    
  2. Modifique el método DirectCallWithNullOrEmpty agregando el código siguiente inmediatamente después de la llamada al método Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsFalse.

    // Code to add to UnitTest1.cs
    result = StringLibrary.StartsWithLower(word);
    Assert.IsFalse(result,
                   $"Expected for '{(word == null ? "<null>" : word)}': " +
                   $"false; Actual: {result}");
    
  3. Cuando se modifica el código fuente, Live Unit Testing ejecuta automáticamente las pruebas nuevas y modificadas. Como se muestra en la ilustración siguiente, todas las pruebas, incluidas las dos que se han agregado y la que se ha modificado, se han realizado correctamente.

    The Live Test Explorer after expanding test coverage

    The Live Test Explorer after expanding test coverage

  4. Cambie a la ventana que contiene el código fuente de la clase StringLibrary. Ahora, Live Unit Testing muestra que nuestra cobertura de código se ha extendido al método StartsWithLower.

    Code coverage for the StartsWithLower method

    Code coverage for the StartsWithLower method

En algunos casos, las pruebas correctas pueden mostrarse atenuadas en el Explorador de pruebas. Eso indica que una prueba se está ejecutando actualmente, o que la prueba no se ha vuelto a ejecutar porque no ha habido ningún cambio en el código que pudiera afectar a la prueba desde que se ejecutó por última vez.

Hasta ahora, todas nuestras pruebas se han realizado correctamente. En la siguiente sección, examinaremos cómo puede controlar los errores de pruebas.

Controlar errores de pruebas

En esta sección, explorará cómo puede usar Live Unit Testing para identificar, solucionar y abordar los errores de pruebas. Para ello, debe expandir la cobertura de las pruebas al método HasEmbeddedSpaces.

  1. Agregue el método siguiente al archivo de prueba:

    [TestMethod]
    public void TestHasEmbeddedSpaces()
    {
        // Tests that we expect to return true.
        string[] phrases = { "one car", "Name\u0009Description",
                             "Line1\nLine2", "Line3\u000ALine4",
                             "Line5\u000BLine6", "Line7\u000CLine8",
                             "Line0009\u000DLine10", "word1\u00A0word2" };
        foreach (var phrase in phrases)
        {
            bool result = phrase.HasEmbeddedSpaces();
            Assert.IsTrue(result,
                          $"Expected for '{phrase}': true; Actual: {result}");
        }
    }
    
  2. Cuando se ejecuta la prueba, en Live Unit Testing se indica que se ha producido un error en el método TestHasEmbeddedSpaces, como se muestra en la ilustración siguiente:

    The Live Test Explorer reporting a failed test

    The Live Test Explorer reporting a failed test

  3. Seleccione la ventana en la que se muestra el código de biblioteca. Live Unit Testing ha ampliado la cobertura de código al método HasEmbeddedSpaces. También informa de los errores de pruebas agregando un símbolo "🞩" rojo a las líneas cubiertas por pruebas erróneas.

  4. Mantenga el mouse sobre la línea que contiene la signatura del método HasEmbeddedSpaces. En Live Unit Testing se muestra información que indica que una prueba cubre el método, como se muestra en la ilustración siguiente:

    Live Unit Testing information on a failed test

    Live Unit Testing information on a failed test

  5. Seleccione la prueba errónea TestHasEmbeddedSpaces. En Live Unit Testing se proporcionan algunas opciones, como la ejecución y la depuración de todas las pruebas, como se muestra en la ilustración siguiente:

    Live Unit Testing options for a failed test

    Live Unit Testing options for a failed test

  6. Seleccione Depurar todo para depurar la prueba con error.

  7. Visual Studio ejecuta la prueba en modo de depuración.

    La prueba asigna cada cadena de una matriz a una variable denominada phrase y la pasa al método HasEmbeddedSpaces. La ejecución del programa se pone en pausa e invoca al depurador la primera vez que la expresión de aserción es false. En la ilustración siguiente se muestra el cuadro de diálogo de excepción que resulta del valor inesperado en la llamada al método Microsoft.VisualStudio.TestTools.UnitTesting.Assert.IsTrue.

    Live Unit Testing exception dialog

    Live Unit Testing exception dialog

    Además, todas las herramientas de depuración que proporciona Visual Studio están disponibles para facilitar la solución de problemas en la prueba con error, como se muestra en la ilustración siguiente:

    Visual Studio debugging tools

    Visual Studio debugging tools

    Tenga en cuenta que, en la ventana Automático, el valor de la variable phrase es "Name\tDescription", que es el segundo elemento de la matriz. El método de prueba espera que HasEmbeddedSpaces devuelva true cuando se le pasa esta cadena; en su lugar, devuelve false. Evidentemente, no reconoce "\t", el carácter de tabulación, como un espacio insertado.

  8. Seleccione Depurar>Continuar, presione F5 o haga clic en el botón Continuar de la barra de herramientas para continuar ejecutando el programa de prueba. La prueba ha finalizado porque se ha producido una excepción no controlada. Esto proporciona información suficiente para una investigación preliminar del error. TestHasEmbeddedSpaces, la rutina de prueba, ha realizado una suposición incorrecta, o bien HasEmbeddedSpaces no reconoce correctamente todos los espacios insertados.

  9. Para diagnosticar y corregir el problema, comience por el método StringLibrary.HasEmbeddedSpaces. Mire la comparación en el método HasEmbeddedSpaces. Considera que U+0020 es un espacio insertado. Sin embargo, el estándar Unicode incluye otros caracteres de espacio. Esto sugiere que el código de biblioteca ha probado incorrectamente la presencia de un carácter de espacio en blanco.

  10. Reemplace la comparación de igualdad por una llamada al método System.Char.IsWhiteSpace:

    if (Char.IsWhiteSpace(ch))
    
  11. Live Unit Testing vuelve a ejecutar de forma automática el método de prueba con errores.

    En Live Unit Testing se muestran los resultados actualizados, que también aparecen en la ventana del editor de código.