Conceptos básicos de prueba unitaria
Este tema describe los fundamentos de pruebas unitarias de escritura y ejecución en el Explorador de pruebas de Visual Studio.Contiene las siguientes secciones:
Información general de pruebas unitarias
- Inicio rápido
El ejemplo de la solución de MyBank
Crear proyectos de prueba unitaria
Escribir las pruebas
Ejecutar pruebas en el Explorador de pruebas
Ejecutar y ver pruebas de la barra de herramientas del Explorador de pruebas
Ejecutar pruebas después de cada compilación
Filtrar y agrupar la lista de pruebas
Pruebas unitarias de depuración
Herramientas adicionales para las pruebas unitarias
Generar código de aplicación de pruebas
Generar varias pruebas utilizando métodos de prueba en los datos
Analizar la cobertura código de pruebas unitarias
Aislar métodos de prueba unitaria con Microsoft Fakes
Información general de pruebas unitarias
El Explorador de pruebas de Visual Studio está diseñado para dar soporte a los programadores y a los equipos que incorporan las pruebas unitarias en las prácticas de desarrollo de software.Las pruebas unitarias ayudan a garantizar la corrección de su programa comprobando que el código de aplicación hace lo que espera que haga.En las pruebas unitarias, se analiza la funcionalidad del programa para detectar los comportamientos comprobables discretos que puede probar como unidadesindividuales.Utiliza un marco de pruebas unitarias para crear pruebas de los comportamientos y para notificar los resultados de las pruebas.
La pruebas unitarias tienen el efecto mayor si es una parte integral del flujo de trabajo de desarrollo de software.En cuanto escriba la función u otro bloque de código de aplicación, cree las pruebas unitarias que comprueben el comportamiento del código en respuesta a casos estándar, límites e incorrectos de datos de entrada y que comprueban cualquier suposición explícita o implícita creada por el código.En un procedimiento de desarrollo de software conocido como desarrollo orientado a pruebas, debe crear las pruebas unitarias antes de escribir el código y se utilizan las pruebas unitarias como documentación de diseño y especificaciones funcionales de la funcionalidad.
El Explorador de pruebas proporciona una manera flexible y eficaz de ejecutar las pruebas unitarias y ver los resultados en Visual Studio.Visual Studio instala los marcos de pruebas unitarias de Microsoft para el código administrado y nativo.El Explorador de pruebas puede ejecutar las marcos de terceros y de origen abierto de pruebas unitarias que han implementado interfaces complementarias del Explorador de pruebas.Se pueden agregar muchos de estos marcos a través del administrador de extensiones de Visual Studio y la galería de Visual Studio.Vea Cómo: Instalar frameworks de prueba unitaria de terceros.
Las vistas de Explorador de pruebas pueden mostrar todas las pruebas, o solo las pruebas sin errores, no superadas, que no se han ejecutado todavía, ni se han omitido.Se pueden filtrar las pruebas en cualquier vista por el texto coincidente en el cuadro de búsqueda en el nivel global o seleccionando uno de los filtros predefinidos.Se puede ejecutar cualquier selección de las pruebas en cualquier momento.Cuando se utiliza Visual Studio Ultimate, se pueden ejecutar pruebas automáticamente después de cada compilación.Los resultados de una ejecución de pruebas son inmediatamente evidentes en la barra de éxito/error en la parte superior de la ventana del explorador.Los detalles de un resultado del método de prueba se muestran al seleccionar la prueba.
Inicio rápido
Para obtener una introducción a la prueba unitaria que le guía directamente en la codificación, vea uno de estos temas:
Tutorial: Crear y ejecutar pruebas unitarias en código administrado
Inicio rápido: Desarrollo basado en pruebas con el Explorador de pruebas
Pruebas unitarias de código nativo con el Explorador de pruebas
El ejemplo de la solución de MyBank
En este tema, utilizamos el desarrollo de una aplicación ficticia denominada MyBank como ejemplo.No se necesita que el código real siga las explicaciones en este tema.Los métodos de prueba se escriben en C# y mostrados mediante el marco de pruebas unitarias de Microsoft para el código administrado, Sin embargo, los conceptos fácilmente se transfieren a otros lenguajes y marcos.
El primer intento en un diseño para la aplicación MyBank incluye un componente de las cuentas que representa una cuenta individual y las transacciones con el banco y un componente de la base de datos que representa la funcionalidad para agregar y administrar las cuentas individuales.
Creamos una solución MyBank que contiene dos proyectos:
Accounts
BankDb
El primer intento en el diseño del proyecto de Accounts contiene una clase para contener información básica sobre una cuenta, una interfaz que especifique la funcionalidad común de cualquier tipo de cuenta, como depositar y retirar activos de la cuenta y una clase derivada de la interfaz que representa una cuenta que comprueba.Comenzamos el proyecto de las cuentas por crear los archivos de código fuente siguientes:
AccountInfo.cs define la información básica para una cuenta.
IAccount.cs define una interfaz estándar de IAccountpara una cuenta, incluidos los métodos para depositar y para retirar los activos de una cuenta y recuperar el saldo de cuenta.
CheckingAccount.cs contiene la clase CheckingAccount que implementa la interfaz de IAccounts para una cuenta que comprueba.
Sabemos por experiencia que una cosa que una retirada de una cuenta que comprueba debe hacer es asegurarse de que la cantidad retirada es menor que el saldo de la cuenta.Sobrescribimos el método IAccount.Withdaw en CheckingAccount por un método que compruebe la existencia de esta condición.El método puede presentar el siguiente aspecto:
public void Withdraw(double amount)
{
if(m_balance >= amount)
{
m_balance -= amount;
}
else
{
throw new ArgumentException(amount, "Withdrawal exceeds balance!")
}
}
Ahora que tenemos algo de código, es el momento para probar.
Crear proyectos de prueba unitaria
Un proyecto de prueba unitaria refleja normalmente la estructura de un solo proyecto de código.En el ejemplo de MyBank, se agregan los proyectos de prueba de dos unidades denominados AccountsTests y BankDbTests a la solución de MyBanks .Los nombres del proyecto de prueba son arbitrarios, pero la adopción de una convención de nomenclatura estándar es una buena idea.
Para agregar un proyecto de prueba unitaria a una solución:
En el menú Archivo , elija Nuevo y elija Proyecto (CTRL + MAYÚS + N en el teclado).
En el cuadro de diálogo Nuevo proyecto, expanda el nodo Instalado , elija el idioma que desea utilizar para el proyecto de prueba y, a continuación, elija Prueba.
Para utilizar uno de los marcos de pruebas unitarias de Microsoft, elija Proyecto de prueba unitaria de la lista de plantillas de proyecto.Si no, elija la plantilla de proyecto de prueba unitaria que desea utilizar.Para probar el proyecto Accounts del ejemplo, se llamaría al proyecto AccountsTests.
Precaución No todos los marcos de terceros y código abierto de prueba unitaria proporcionan una plantilla de proyecto de Visual Studio.Vea el documento del marco para obtener información sobre cómo crear un proyecto.
En el proyecto de prueba unitaria, agregue una referencia al proyecto de código sometido a prueba, en nuestro ejemplo al proyecto Cuentas.
Para crear la referencia al proyecto de código:
Seleccione el proyecto en el Explorador de soluciones.
Haga clic en la opción Agregar referencia del menú Proyecto.
En el cuadro de diálogo Administrador de referencias, abra el nodo Solución y elija Proyectos.Seleccione el nombre del proyecto de código y cierre el cuadro de diálogo.
Cada proyecto de prueba unitaria contiene clases que reflejan los nombres de las clases en el proyecto de código.En nuestro ejemplo, el proyecto AccountsTests contendría las clases siguientes:
La claseAccountInfoTests contiene los métodos de prueba unitaria para la clase AccountInfo en el proyecto BankAccount .
La claseCheckingAccountTests contiene los métodos de prueba unitaria para la clase CheckingAccount .
Escribir las pruebas
El marco de pruebas unitarias que se utiliza y Visual Studio IntelliSense le guiarán a través de la creación de pruebas unitarias para un proyecto de código.Para ejecutar en el Explorador de pruebas, la mayoría de los marcos requieren que se agreguen atributos específicos para identificar métodos de prueba unitaria.Los marcos también proporcionan una manera —habitualmente con extractos assert o atributos de método— para indica si el método de prueba ha pasado o ha producido errores.Otros atributos identifican métodos de instalación opcionales que están en la inicialización de la clase y antes de que se destruya cada método de prueba y los métodos de destrucción que se ejecutan después de cada método de prueba y antes de que la clasese destruya.
El patrón AAA (organizar, representar, validar) es una manera común de escribir las pruebas unitarias para un método en pruebas.
La sección Organizar de un método de prueba unitaria inicializa objetos y establece el valor de los datos que se pasa al método en pruebas.
La sección Actuar invoca el método en pruebas con parámetros organizados.
La sección Validar comprueba que la acción del método en pruebas se comporte como se espera.
Para probar el método CheckingAccount.Withdraw del ejemplo, podemos escribir dos pruebas: una que compruebe el comportamiento estándar del método y otra que compruebe si una retirada más en el equilibrio producirá un error.Agregue a la clase CheckingAccountTests los siguientes métodos:
[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
// arrange
double currentBalance = 10.0;
double withdrawal = 1.0;
double expected = 9.0;
var account = new CheckingAccount("JohnDoe", currentBalance);
// act
account.Withdraw(withdrawal);
double actual = account.Balance;
// assert
Assert.AreEqual(expected, actual);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Withdraw_AmountMoreThanBalance_Throws()
{
// arrange
var account = new CheckingAccount("John Doe", 10.0);
// act
account.Withdraw(1.0);
// assert is handled by the ExcpectedException
}
Observe que Withdraw_ValidAmount_ChangesBalance utiliza un fragmento explícito de Assert para determinar si métodos de prueba pasan o fallan, mientras que Withdraw_AmountMoreThanBalance_Throws utiliza el atributo ExpectedException para determinar el éxito del método de prueba.En segundo plano, un marco de prueba unitaria envuelve métodos de prueba en fragmentos try/catch.En la mayoría de los casos, si se produce una excepción, se omiten los errores del método de prueba y la excepción.El atributo ExpectedException hace que el método de prueba tenga éxito si se produce la excepción especificada.
Para obtener más información sobre marcos de pruebas unitarias de Microsoft, vea uno de los temas siguientes:
Ejecutar pruebas en el Explorador de pruebas
Al compilar el proyecto de prueba, las pruebas aparecen en el Explorador de pruebas.Si el Explorador de pruebas no está visible, elija Prueba en el menú de Visual Studio, elija Ventanas y elija Explorador de pruebas.
Cuando se ejecutan, se escriben y se vuelven a ejecutar las pruebas, la vista predeterminada del Explorador de pruebas muestra los resultados en grupos de Pruebas no superadas, Pruebas superadas, Pruebas saltadas y Pruebas no ejecutadas.Se puede elegir un título del grupo para abrir la vista que muestra todas las pruebas en ese grupo.
Ejecutar y ver pruebas de la barra de herramientas del Explorador de pruebas
La barra de herramientas del Explorador de pruebas le ayuda a detectar, organizar y ejecutar pruebas que le interesan.
Se puede elegir Ejecutar todas para ejecutar todas las pruebas, o elegir Ejecutar para elegir un subconjunto de pruebas para ejecutarse.Después de ejecutar un conjunto de pruebas, un resumen de la ejecución de pruebas aparece en la parte inferior de la ventana del Explorador de pruebas.Seleccione una prueba para ver los detalles de esa prueba en la sección inferior.Elija Abrir prueba en el menú contextual (teclado: F12) para mostrar el código fuente de la prueba seleccionada.
Ejecutar pruebas después de cada compilación
Precaución |
---|
Ejecutar pruebas unitarias después de cada compilación sólo se admite en Visual Studio Ultimate. |
Para ejecutar las pruebas unitarias después de cada compilación local, elija Prueba en el menú estándar, elija Ejecutar pruebas después de compilar en la barra de herramientas del Explorador de pruebas. |
Filtrar y agrupar la lista de pruebas
Si tiene un gran número de pruebas, se puede escribir en el cuadro de búsqueda del Explorador de pruebas para filtrar la lista por la cadena especificada.Se puede limitar más el evento de filtro eligiendo de la lista de filtros.
Para agrupar las pruebas por categoría, elija el botón Agrupar por . |
Para obtener más información, vea Ejecutar pruebas unitarias con el Explorador de pruebas
Pruebas unitarias de depuración
Se puede utilizar el Explorador de pruebas para iniciar una sesión de depuración para las pruebas.Ejecutar código con el depurador de Visual Studio sin problemas le guía de uno a otro entre las pruebas unitarias y el proyecto en pruebas.Para iniciar la depuración:
En el editor de Visual Studio, establezca un punto de interrupción en uno o más métodos de prueba que desea depurar.
[!NOTA]
Dado que los métodos de prueba se pueden ejecutar en cualquier orden, establezca puntos de interrupción en todos los métodos de prueba que desea depurar.
En el Explorador de pruebas, seleccione los métodos de prueba y después elija Depurar pruebas seleccionadas en el acceso directo.
Para obtener más información sobre el depurador, consulte Depurar en Visual Studio.
Herramientas adicionales para las pruebas unitarias
Generar código de aplicación de pruebas
Si se escriben las pruebas antes de escribir el código del proyecto, se puede utilizar IntelliSense para generar clases y métodos del código del proyecto.Escriba un fragmento en un método de prueba que llama a la clase o método que se desea generar, vuelva a abrir el menú de IntelliSense bajo la llamada.Si la llamada es un constructor de la nueva clase, elija Generar nuevo tipo del menú y siga el asistente para insertar la clase del proyecto de código.Si la llamada es a un método, elija Generar nuevo método del menú de IntelliSense.
Generar varias pruebas utilizando métodos de prueba en los datos
[!NOTA]
Estos procedimientos se aplican para probar únicamente los métodos que se escriben utilizando el marco de pruebas unitarias de Microsoft para el código administrado.Si se usa otro marco, consulte la documentación de .NET framework para la funcionalidad equivalente.
Los métodos controlados por datos de pruebas permiten comprobar un intervalo de valores en un método de prueba unitaria.Para crear un método controlado por datos de prueba unitaria, decore el método con un atributo DataSource que especifica el origen de datos y la tabla que contiene los valores de las variables que se desean probar.En el cuerpo del método, se pueden asignar los valores de fila a variables utilizando el indizador TestContext.DataRow[NombreColumna] .
Por ejemplo, suponga que agregamos un método innecesario a la clase CheckingAccount denominado AddIntegerHelper.AddIntegerHelper agrega dos enteros.
Para crear una prueba controlada por datos para el método AddIntegerHelper , primero creamos una base de datos en Access denominada AccountsTest.accdb y una tabla denominada AddIntegerHelperData.La tabla AddIntegerHelperData define columnas para especificar el primer y segundo operando de suma y una columna para especificar el resultado esperado.Rellenamos varias filas con valores adecuados.
[DataSource(
@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\MyBank\TestData\AccountsTest.accdb",
"AddIntegerHelperData"
)]
[TestMethod()]
public void AddIntegerHelper_DataDrivenValues_AllShouldPass()
{
var target = new CheckingAccount();
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
int actual = target.AddIntegerHelper(x, y);
Assert.AreEqual(expected, actual);
}
El método con atributos se ejecuta una vez para cada fila de la tabla.El explorador de pruebas informa de un error de prueba para el método si no se supera cualquiera de las iteraciones.El panel de detalles de resultados de pruebas para el método muestra el método de estado de éxito/error en cada fila de datos.
Para obtener más información, vea Cómo: Crear una prueba unitaria controlada por datos
Analizar la cobertura código de pruebas unitarias
[!NOTA]
La cobertura de código de la prueba unitaria está disponible para código nativo y los lenguajes administrados y todos los marcos de pruebas unitarias que se pueden ejecutar por el marco de pruebas unitarias.
Se puede determinar la cantidad del código de producto que está siendo probado realmente por las pruebas unitarias con la herramienta de cobertura de código de Visual Studio.Se puede ejecutar la cobertura de código en pruebas seleccionadas o en todas las pruebas de una solución.La ventana de resultados de la cobertura de código muestra el porcentaje de bloques de código de producto que se han ejecutado por línea, función, clase, espacio de nombres y módulo.
Para ejecutar la cobertura de código para los métodos de prueba de una solución,
elija Pruebas en el menú de Visual Studio y elija Analizar cobertura de código.
Elija uno de estos comandos:
Pruebas seleccionadas ejecuta los métodos de prueba que ha seleccionado en el Explorador de pruebas.
Todas las pruebas ejecuta todos los métodos de prueba en la solución.
Los resultados de cobertura aparecen en la ventana de resultados de la cobertura de código.
Para obtener más información, vea Usar cobertura de código para determinar la cantidad de código que se está probando.
Aislar métodos de prueba unitaria con Microsoft Fakes
[!NOTA]
Microsoft Fakes sólo está disponible en Visual Studio Ultimate.Microsoft Fakes sólo se puede utilizar con los métodos de prueba que se escriben utilizando los marcos de pruebas unitarias para código administrado.
El problema
Los métodos de prueba unitaria que se centran en comprobar el código interno en una función pueden ser difíciles de escribir cuando el método en prueba llama a funciones que introducen dependencias externas.Por ejemplo, los métodos de la clase de ejemplo CheckingAccount deberían probablemente hacer llamadas al componente de BankDb para actualizar la base de datos principal.Podemos refactorizar la clase CheckingAccount para que tenga el aspecto siguiente:
class CheckingAccount : IAccount
{
public CheckingAccount(customerName, double startingBalance, IBankDb bankDb)
{
m_bankDb = bankDb;
// set up account
}
public void Withdraw(double amount)
{
if(m_balance >= amount)
{
m_balance = m_MyBankDb.Withdraw(m_accountInfo.ID, amount);
}
else
{
throw new ArgumentException(amount, "Withdrawal exceeds balance!")
}
}
private IBankDb m_bankDb = null;
// ...
Las pruebas unitarias de este método CheckingAccount.Withdraw ahora pueden fallar debido a los problemas producidos por la llamada a m_bankDb.Withdraw.La base de datos o la conexión de red podrían perderese o los permisos en la base de datos podrían ser incorrectos.Un error en la llamada m_bankDB.Withdraw provocaría que la prueba no se supere por razones que no están relacionadas con el código interno.
La solución de Microsoft Fakes
Microsoft Fakes crea un ensamblado que contiene las clases y métodos que se pueden utilizar para las clases de los métodos de prueba unitaria que producen dependencias.Una clase alternativa en el módulo generado de Fakes declara un método y un delegado para cada método público en el componente de destino.En un método de prueba, se implementa el delegado para crear el comportamiento exacto de la llamada de dependencia en el método que se desee probar.
En nuestro ejemplo, podemos crear un ensamblado de Fakes para el proyecto BankDb y después utilizar la clase StubIBankDb generada por Fakes y que se deriva de la interfaz IBankDb para quitar la incertidumbre producida por las interacciones con la base de datos.Una versión modificada del método de prueba Withdraw_ValidAmount_ChangesBalance tendría el aspecto siguiente:
[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
// arrange
double currentBalance = 10.0;
double withdrawal = 1.0;
double expected = 9.0;
// set up the Fakes object and delegate
var stubBankDb = new MyBank.Stubs.StubIBankDb();
stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }
var account = new CheckingAccount("JohnDoe", currentBalance, stubBankDb);
// act
account.Withdraw(withdrawal);
double actual = account.Balance;
// assert
Assert.AreEqual(expected, actual);
}
Esta línea del método de prueba:
stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }
implementa el delegado de Fakes para el método Withdraw utilizando una expresión lamba.El método stubBankDb.Withdraw llama al delegado y devuelve siempre la cantidad especificada, que permite que el método de prueba compruebe de forma fiable el comportamiento del método Accounts .
Más acerca de Microsoft Fakes
Microsoft Fakes utiliza dos enfoques para crear clases substitutas:
Los códigos auxiliares representan las clases sustitutas derivadas de la interfaz de la clase principal de dependencia de destino.Los métodos de código auxiliar se pueden sustituir por los métodos virtuales públicos de la clase de destino.
Instrumentación del runtime de usode las cuñas para desviar llamadas a un método de destino a un método sustituto de correcciones de compatibilidad para los métodos no virtuales.
En ambos métodos, utilice delegados generados de llamadas a métodos de dependencia para especificar el comportamiento que se desea en el método de prueba.
Para obtener más información, vea Aislar el código probado con Microsoft Fakes.