Ejercicio: corregir una prueba con errores
En este momento, dispone de una manera de ejecutar las pruebas unitarias a medida que los cambios se mueven a través de la canalización de compilación. También tiene una forma de medir la cantidad de código que cubren las pruebas.
Siempre se recomienda ejecutar todas las pruebas localmente antes de enviarlas a la canalización. Pero ¿qué sucede cuando un usuario se olvida y envía un cambio que interrumpe la compilación?
En esta unidad, corregirá una compilación interrumpida a causa de una prueba unitaria con errores. Aquí podrá:
- Obtenga el código de inicio de GitHub.
- Agregue herramientas de cobertura de código al proyecto.
- Enviará el código al repositorio.
- Verá cómo la canalización se ejecuta automáticamente y se producen errores en las pruebas unitarias.
- Reproducirá el error localmente.
- Analizará y corregirá el error.
- Enviará una corrección y verá cómo la compilación se realiza correctamente.
Revisar la nueva prueba unitaria
La característica más reciente del equipo implica la tabla de clasificación. Es necesario obtener el número de puntuaciones de la base de datos para que podamos escribir una prueba unitaria para comprobar el método IDocumentDBRepository<T>.GetItemsAsync
.
Este es el aspecto de la prueba. Todavía no es necesario agregar ningún código.
[TestCase(0, ExpectedResult=0)]
[TestCase(1, ExpectedResult=1)]
[TestCase(10, ExpectedResult=10)]
public int ReturnRequestedCount(int count)
{
const int PAGE = 0; // take the first page of results
// Fetch the scores.
Task<IEnumerable<Score>> scoresTask = _scoreRepository.GetItemsAsync(
score => true, // return all scores
score => 1, // we don't care about the order
PAGE,
count // fetch this number of results
);
IEnumerable<Score> scores = scoresTask.Result;
// Verify that we received the specified number of items.
return scores.Count();
}
Recuerde que en una prueba NUnit, TestCase
proporciona datos insertados que se usan para probar ese método. NUnit llama al método de prueba unitaria ReturnRequestedCount
de una forma similar a la siguiente:
ReturnRequestedCount(0);
ReturnRequestedCount(1);
ReturnRequestedCount(10);
Esta prueba también usa la propiedad ExpectedResult
para simplificar el código de prueba y ayudar a que su intención sea más clara. NUnit compara automáticamente el valor devuelto con el valor de esta propiedad y, de esta manera, elimina la necesidad de llamar explícitamente a la aserción.
Elegiremos algunos valores que representan consultas típicas. También incluiremos 0 para cubrir ese caso perimetral.
Captura de la rama de GitHub
Como hizo anteriormente, capture la rama failed-test
de GitHub y restaure (o cambie a) esa rama.
En Visual Studio Code, abra el terminal integrado.
Ejecute los comandos
git fetch
ygit checkout
siguientes para descargar una rama denominadafailed-test
desde el repositorio de Microsoft y cambie a esa rama:git fetch upstream failed-test git checkout -B failed-test upstream/failed-test
Con fines de aprendizaje, denominaremos la rama
failed-test
. En la práctica, denominaría una rama en función de su propósito o característica.Ejecute estos comandos para crear un archivo de manifiesto de la herramienta local, instale la herramienta
ReportGenerator
y agregue el paquetecoverlet.msbuild
al proyecto de pruebas:dotnet new tool-manifest dotnet tool install dotnet-reportgenerator-globaltool dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
Necesita este paso porque la rama
failed-test
no contiene el trabajo que ha agregado a la ramaunit-tests
.Agregue el archivo del proyecto de prueba y el archivo de manifiesto de la herramienta al índice de ensayo y confirme los cambios.
git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj git add .config/dotnet-tools.json git commit -m "Configure code coverage tests"
Ejecute el comando
git push
siguiente para cargar la ramafailed-test
en el repositorio de GitHub:git push origin failed-test
Ver el error de prueba en la canalización
Supongamos que tenía prisa y envió su trabajo sin ejecutar las pruebas una última vez. Por suerte, la canalización puede ayudarle a detectar problemas anticipadamente cuando hay pruebas unitarias. Puede ver esto aquí.
En Azure Pipelines, realice un seguimiento de la compilación mientras se ejecuta por la canalización.
Expanda la tarea Ejecutar pruebas unitarias - Liberar mientras se ejecuta.
Verá que el método de prueba
ReturnRequestedCount
produce un error.La prueba se supera cuando el valor de entrada es 0, pero se produce un error cuando el valor de entrada es 1 o 10.
La compilación se publica en la canalización solo cuando la tarea anterior se realiza correctamente. En este caso, no se publicó la compilación debido a un error en las pruebas unitarias. Esto evita que la compilación se interrumpa accidentalmente para otros usuarios.
En la práctica, no siempre realizará un seguimiento manual de la compilación mientras se ejecuta. Estas son algunas formas de detectar el error:
Notificación por correo electrónico de Azure DevOps
Puede configurar Azure DevOps para que le envíe una notificación por correo electrónico cuando la compilación se haya completado. La línea del asunto empieza con "[Error de compilación]" cuando se produce un error en la compilación.
Azure Test Plans
En Azure DevOps, seleccione Test Plans y, después, Runs (Ejecuciones). Verá las series de pruebas recientes, incluida la que se acaba de ejecutar. Seleccione la última prueba completada. Verá que se produjeron errores en dos de las ocho pruebas.
El panel
En Azure DevOps, seleccione Overview (Información general) y, después, Dashboards (Paneles). Verá que el error se muestra en el widget Tendencia de los resultados de pruebas. El widget Code Coverage (Cobertura de código) está en blanco, lo que indica que no se ha ejecutado la cobertura de código.
La notificación de compilación
Aunque la rama
failed-test
no incluye la notificación de compilación en el archivo README.md, esto es lo que vería en GitHub cuando se produjera un error en la compilación:
Analizar los errores de las pruebas
Cuando se produce un error en las pruebas unitarias, normalmente tiene dos opciones, según la naturaleza del error:
- Si la prueba revela un defecto en el código, corrija el código y vuelva a ejecutar las pruebas.
- Si la funcionalidad ha cambiado, ajuste la prueba para que coincida con los nuevos requisitos.
Reproducir el error localmente
En esta sección, reproducirá el error localmente.
En Visual Studio Code, abra el terminal integrado.
En el terminal, ejecute este comando
dotnet build
para compilar la aplicación:dotnet build --configuration Release
En el terminal, ejecute este comando
dotnet test
para realizar las pruebas unitarias:dotnet test --no-build --configuration Release
Debería ver los mismos errores que en la canalización. A continuación, se muestra parte de la salida:
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Failed ReturnRequestedCount(1) [33 ms] Error Message: Expected: 1 But was: 0 Stack Trace: at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Failed ReturnRequestedCount(10) [1 ms] Error Message: Expected: 10 But was: 9 Stack Trace: at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Failed! - Failed: 2, Passed: 6, Skipped: 0, Total: 8, Duration: 98 ms
Encontrar la causa del error
Observará que cada prueba con errores genera un resultado que representa una unidad menos. Por ejemplo, cuando se espera 10, la prueba devuelve 9.
Observe el código fuente para el método que se está probando: LocalDocumentDBRepository<T>.GetItemsAsync
. Debería aparecer esto:
public Task<IEnumerable<T>> GetItemsAsync(
Func<T, bool> queryPredicate,
Func<T, int> orderDescendingPredicate,
int page = 1, int pageSize = 10
)
{
var result = _items
.Where(queryPredicate) // filter
.OrderByDescending(orderDescendingPredicate) // sort
.Skip(page * pageSize) // find page
.Take(pageSize - 1); // take items
return Task<IEnumerable<T>>.FromResult(result);
}
En este escenario, podría comprobar GitHub para ver si el archivo se cambió recientemente.
Sospecha que pageSize - 1
devuelve un resultado menos y que debería ser, simplemente, pageSize
. En nuestro escenario, se trata de un error realizado al enviar trabajo sin pruebas, pero en un escenario real podría comprobar con el desarrollador que cambió el archivo en GitHub para determinar el motivo del cambio.
Sugerencia
El análisis y la colaboración también tienen lugar en GitHub. Puede comentar una solicitud de incorporación de cambios o abrir un problema.
Corregir el error
En esta sección, corregirá el error volviendo a cambiar el código a su estado original y ejecutando las pruebas para comprobar la corrección.
En Visual Studio Code, abra Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs desde el Explorador de archivos.
Modifique el método
GetItemsAsync
tal y como se muestra aquí:public Task<IEnumerable<T>> GetItemsAsync( Func<T, bool> queryPredicate, Func<T, int> orderDescendingPredicate, int page = 1, int pageSize = 10 ) { var result = _items .Where(queryPredicate) // filter .OrderByDescending(orderDescendingPredicate) // sort .Skip(page * pageSize) // find page .Take(pageSize); // take items return Task<IEnumerable<T>>.FromResult(result); }
Esta versión cambia de
pageSize - 1
apageSize
.Guarde el archivo.
En el terminal integrado, compile la aplicación.
dotnet build --configuration Release
Debería ver que la compilación se realice correctamente.
En la práctica, podría ejecutar la aplicación y probarla brevemente. Con fines de aprendizaje, omitiremos eso por ahora.
En el terminal, ejecute las pruebas unitarias.
dotnet test --no-build --configuration Release
Verá que se superan las pruebas.
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Passed! - Failed: 0, Passed: 8, Skipped: 0, Total: 8, Duration: 69 ms
En el terminal integrado, agregue cada archivo modificado al índice, confirme los cambios e inserte la rama en GitHub.
git add . git commit -m "Return correct number of items" git push origin failed-test
Sugerencia
El punto (
.
) de este ejemplo degit add
es un carácter comodín. Coincide con todos los archivos no almacenados provisionalmente en el directorio actual y todos los subdirectorios.Antes de utilizar este carácter comodín, se recomienda ejecutar
git status
antes de la confirmación para asegurarse de estar realizando el ensayo con los archivos previstos.Vuelva a Azure Pipelines. Observe cómo el cambio se mueve por la canalización. Se superarán las pruebas y se realizará correctamente la compilación global.
Si quiere, puede seleccionar las pestañas Tests (Pruebas) y Code Coverage (Cobertura de código) cuando finalice la compilación para comprobar los resultados de las pruebas.
También puede consultar el panel para ver la tendencia de los resultados actualizada.
Magnífico. Se corrigió la compilación. A continuación, aprenderá a limpiar el entorno de Azure DevOps.