Pruebas unitarias de código de Visual C# en una aplicación de la Tienda Windows
En este tema se describe una manera de crear pruebas unitarias para una clase de Visual C# en una aplicación de la Tienda Windows (también conocida como aplicación de la Tienda Windows) mediante Visual Studio Express 2012 para Windows 8 y el marco de pruebas unitarias de Microsoft. La clase Rooter muestra las memorias imprecisas de teoría límite del cálculo mediante la implementación de una función que calcula una estimación de raíz cuadrada de un número determinado. La aplicación Maths puede utilizar esta función para mostrar a un usuario las cosas divertidas que se pueden realizar con las matemáticas.
En este tema se muestra cómo se utilizan las pruebas unitarias como primer paso en el desarrollo. En este enfoque, primero tienes que escribir un método de prueba que compruebe un comportamiento concreto en el sistema que estés probando y, después, escribir el código que tenga que superar la prueba. Mediante la realización de cambios en el orden de los procedimientos siguientes, puedes invertir esta estrategia para escribir primero el código que deseas probar y escribe después las pruebas unitarias.
En este tema también se crea una solución única de Visual Studio y proyectos independientes para las pruebas unitarias y el DLL que desees probar. También puedes incluir las pruebas unitarias directamente en el proyecto DLL, o crear soluciones independientes para las pruebas unitarias y el DLL.
Nota
Visual Studio Ultimate, VS Premium y VS Professional proporcionan características adicionales para pruebas unitarias.
-
En VS Ultimate, VS Premium y VS Professional puedes usar cualquier marco de pruebas unitarias de código fuente abierto y de terceros que haya creado un adaptador complementario para el Explorador de pruebas de Microsoft. También puedes analizar y mostrar información de cobertura de código para las pruebas.
-
VS Ultimate y VS Premium te permiten ejecutar tus pruebas después de cada compilación.
-
VS Ultimate también contiene Microsoft Fakes, un marco de aislamiento para código administrado que te ayudará a centrar tus pruebas en tu propio código sustituyendo el código de prueba para el sistema y la funcionalidad de terceros.
Para obtener más información, consulta Verifying Code by Using Unit Tests en MSDN Library.
En este tema
Crear la solución y el proyecto de prueba unitaria
Comprobar que las pruebas se ejecutan en el Explorador de pruebas
Agregar la clase Rooter al proyecto Matemáticas
Acoplar el proyecto de prueba al proyecto de la aplicación
Aumentar de forma iterativa las pruebas y comprobar si se superan
Depurar una prueba que no se supera
Refactorizar el código
Crear la solución y el proyecto de prueba unitaria
En el menú Archivo, elige Nuevo y, a continuación, elige Nuevo proyecto.
En el cuadro de diálogo Nuevo proyecto, expande Instalado y, a continuación, expande Visual C# y elige Tienda Windows. A continuación, elige Aplicación vacía en la lista de plantillas de proyecto.
Asigna al proyecto el nombre Matemáticas y asegúrate de que esté seleccionado Crear directorio para la solución.
En el Explorador de soluciones, elige el nombre de la solución, elige Agregar en el menú contextual y, a continuación, elige Nuevo proyecto.
En el cuadro de diálogo Nuevo proyecto, expande Instalado y, a continuación, expande Visual C# y elige Tienda Windows. A continuación elige Biblioteca de pruebas unitarias (aplicaciones de la Tienda Windows) en la lista de plantillas de proyecto.
Abre UnitTest1.cs en el editor de Visual Studio.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; using Maths; namespace RooterTests { [TestClass] public class UnitTest1 [TestMethod] public void TestMethod1() { }
Ten en cuenta lo siguiente:
Cada prueba se define utilizando [TestMethod]. Un método de prueba debe devolver void y no puede tener parámetros.
Los métodos de prueba deben estar en una clase decorada con el atributo [TestClass].
Cuando se ejecutan las pruebas, se crea una instancia de cada clase de prueba. Los métodos de prueba se invocan en un orden no especificado.
Puedes definir métodos especiales que se invoquen antes y después de cada módulo, clase o método. Para obtener más información, consulta Usar miembros de Microsoft.VisualStudio.TestTools.UnitTesting en pruebas unitarias en MSDN Library.
Comprobar que las pruebas se ejecutan en el Explorador de pruebas
Inserta el código de prueba en TestMethod1 del archivo UnitTest1.cs:
[TestMethod] public void TestMethod1() { Assert.AreEqual(0, 0); }
Observa que la clase Assert proporciona varios métodos estáticos que puedes utilizar para comprobar los resultados en los métodos de prueba.
En el menú Prueba, elige Ejecutar y, a continuación, elige Ejecutar todas.
El proyecto de prueba se compila y ejecuta. Aparece la ventana Explorador de pruebas y la prueba se muestra debajo de Pruebas superadas. El panel Resumen de la parte inferior de la ventana proporciona detalles adicionales sobre la prueba seleccionada.
Agregar la clase Rooter al proyecto Matemáticas
En el Explorador de soluciones, elige el nombre del proyecto Matemáticas. En el menú contextual, elige Agregar y, a continuación, elige Clase.
Asigna al archivo de clase el nombre Rooter.cs.
Agrega el siguiente código al archivo Rooter.cs de la clase Rooter:
public Rooter() { } // estimate the square root of a number public double SquareRoot(double x) { return 0.0; }
La clase Rooter declara un constructor y el método de perito de SqareRoot.
El método SqareRoot es solo una implementación mínima, suficiente para probar la estructura básica de la configuración de pruebas.
Acoplar el proyecto de prueba al proyecto de la aplicación
Agrega una referencia a la aplicación Maths en el proyecto RooterTests.
En el Explorador de soluciones, elige el proyecto RooterTests y, a continuación, elige Agregar referencia en el menú contextual.
En el cuadro de diálogo Agregar referencia - RooterTests, expande Solución y elige Proyectos. A continuación, selecciona el elemento Maths.
Agrega una instrucción Using al archivo UnitTest1.cs:
Abre UnitTest1.cs.
Agrega este código debajo de la línea using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;:
using Maths;
Agrega una prueba que use la función Rooter. Agrega el código siguiente a UnitTest1.cpp:
[TestMethod] public void BasicTest() { Maths.Rooter rooter = new Rooter(); double expected = 0.0; double actual = rooter.SquareRoot(expected * expected); double tolerance = .001; Assert.AreEqual(expected, actual, tolerance); }
Compila la solución.
La nueva prueba aparece en el Explorador de pruebas en el nodo Pruebas no ejecutadas.
En el Explorador de pruebas, elige Ejecutar todas.
Has configurado los proyectos de prueba y de código, y comprobado que puedes ejecutar pruebas que ejecutan funciones en el proyecto de código. Ahora puedes empezar a escribir pruebas y código reales.
Aumentar de forma iterativa las pruebas y comprobar si se superan
Agrega una nuevo prueba:
[TestMethod] public void RangeTest() { Rooter rooter = new Rooter(); for (double v = 1e-6; v < 1e6; v = v * 3.2) { double expected = v; double actual = rooter.SquareRoot(v*v); double tolerance = ToleranceHelper(expected); Assert.AreEqual(expected, actual, tolerance); } }
Sugerencia
Te recomendamos que no cambies las pruebas que se han superado. En su lugar, agrega una nueva prueba, actualiza el código para que la prueba se supere, agrega otra prueba, y así sucesivamente.
Cuando los usuarios cambien los requisitos, deshabilita las pruebas que no sean correctas. Escribe nuevas pruebas y haz que funcionen de una en una, de la misma manera incremental.
En el Explorador de pruebas, elige Ejecutar todas.
La prueba sufre un error.
Sugerencia
Inmediatamente después de haberla escrito, comprueba que cada prueba sufre un error. Esto ayuda a evitar la fácil equivocación de escribir una prueba que nunca produce un error.
Mejora el código objeto de prueba para que la nueva prueba se supere. Cambia la función SqareRoot de Rooter.cs a lo siguiente:
public double SquareRoot(double x) { double estimate = x; double diff = x; while (diff > estimate / 1000) { double previousEstimate = estimate; estimate = estimate - (estimate * estimate - x) / (2 * estimate); diff = Math.Abs(previousEstimate - estimate); } return estimate; }
Compila la solución y, a continuación, en el Explorador de pruebas, elige Ejecutar todas.
Ahora se superan las tres pruebas.
Sugerencia
Desarrolla el código agregando pruebas de una en una. Asegúrate de que se superen todas las pruebas después de cada iteración.
Depurar una prueba que no se supera
Agrega otra prueba a UnitTest1.cs:
// Verify that negative inputs throw an exception. [TestMethod] public void NegativeRangeTest() { string message; Rooter rooter = new Rooter(); for (double v = -0.1; v > -3.0; v = v - 0.5) { try { // Should raise an exception: double actual = rooter.SquareRoot(v); message = String.Format("No exception for input {0}", v); Assert.Fail(message); } catch (ArgumentOutOfRangeException ex) { continue; // Correct exception. } catch (Exception e) { message = String.Format("Incorrect exception for {0}", v); Assert.Fail(message); } } }
En el Explorador de pruebas, elige Ejecutar todas.
La prueba sufre un error. Elige el nombre de la prueba en el Explorador de pruebas. Se resalta el error de aserción. El mensaje de error se puede ver en el panel de detalles del Explorador de pruebas.
Para ver por qué la prueba sufre un error, recorre paso a paso la función:
Establece un punto de interrupción al principio de la función SquareRoot.
En el menú contextual de la prueba no superada, elige Depurar pruebas seleccionadas.
Cuando la ejecución se detenga en el punto de interrupción, recorre paso a paso el código.
Agrega código al método Rooter para detectar la excepción:
public double SquareRoot(double x) { if (x < 0.0) { throw new ArgumentOutOfRangeException(); }
- En el Explorador de pruebas, elige Ejecutar todas para probar el método corregido y asegúrate de que no se haya introducido una regresión.
Ahora todas las pruebas se superan.
Refactorizar el código
Simplificar el cálculo central en la función SquareRoot
Cambia la implementación del resultado.
// old code //result = result - (result*result - v)/(2*result); // new code result = (result + v/result) / 2.0;
Elige Ejecutar todas para probar el método refactorizado y asegúrate de que no hayas introducido una regresión.
Sugerencia
Un conjunto estable de pruebas unitarias correctas proporciona la confianza de que no se han introducido errores al cambiar el código.
Refactorizar el código de prueba para eliminar código duplicado
Observa que el método RangeTest codifica de forma rígida el denominador de la variable de tolerancia que se utiliza en el método Assert. Si tienes la intención de agregar otras pruebas que utilizan el mismo cálculo de tolerancia, el uso de un valor codificado de forma rígida en varias ubicaciones puede provocar errores.
Agrega un método privado a la clase Unit1Test para calcular el valor de tolerancia y, después, llama a ese método en su lugar.
private double ToleranceHelper(double expected) { return expected / 1000; } ... [TestMethod] public void RangeTest() { ... // old code // double tolerance = expected/1000; // new code double tolerance = ToleranceHelper(expected); Assert.AreEqual(expected, actual, tolerance); } ...
Elige Ejecutar todas para probar el método refactorizado y asegúrate de que no hayas introducido un error.
Nota
Para agregar un método auxiliar a una clase de prueba, no debes agregar el atributo [TestMethod] al método. El Explorador de pruebas no registra el método que se va a ejecutar.