Ejercicio: Desarrollo de pruebas unitarias mediante herramientas de GitHub Copilot
GitHub Copilot puede ayudarle a escribir pruebas unitarias para el código. Hay varias maneras de usar GitHub Copilot para generar pruebas unitarias:
- Generar casos de prueba: puede usar GitHub Copilot para generar casos de prueba para el código. Copilot puede sugerir casos de prueba basados en el código que ha escrito. A continuación, puede usar estos casos de prueba para crear pruebas unitarias para el código.
- Generar métodos de prueba: Copilot también puede generar métodos de prueba para el código. Puede usar estos métodos de prueba para crear pruebas unitarias para el código.
- Generar aserciones de prueba: Copilot puede sugerir aserciones que puede usar en las pruebas unitarias. Estas aserciones pueden ayudarle a comprobar el comportamiento del código.
- Generar simulacros de prueba: Copilot puede generar objetos ficticios que puede usar en las pruebas unitarias. Estos objetos ficticios pueden ayudarle a aislar el código que está probando de sus dependencias.
- Generar datos de prueba: Copilot puede generar datos de prueba que puede usar en las pruebas unitarias. Estos datos de prueba pueden ayudarle a probar el código con entradas diferentes.
- Generar código de configuración de prueba: Copilot puede generar código de instalación para las pruebas unitarias. Este código puede ayudarle a configurar el entorno de prueba antes de ejecutar las pruebas.
- Generar código de desmontaje de la prueba: Copilot puede generar código de desmontaje para las pruebas unitarias. Este código puede ayudarle a limpiar el entorno de prueba después de ejecutar las pruebas.
La solución existente incluye un proyecto de prueba unitaria denominado UnitTests. Este proyecto ya contiene pruebas unitarias que cubren parcialmente las clases de servicio en el proyecto ApplicationCore.
En este ejercicio, usará GitHub Copilot para completar las siguientes tareas:
Examine el enfoque de las pruebas unitarias implementadas por el proyecto UnitTests.
Amplíe el proyecto UnitTests para empezar a probar las clases de acceso a datos en el proyecto de
Library.Infrastructure.
Examen del enfoque de las pruebas unitarias implementadas por el proyecto UnitTests
El código base existente incluye un proyecto UnitTests que implementa la siguiente estructura de carpetas:
- UnitTests\
- ApplicationCore\
- LoanService\
ExtendLoan.csReturnLoan.cs
- PatronService\
RenewMembership.cs
- LoanService\
- LoanFactory.cs
- PatronFactory.cs
- ApplicationCore\
Esta estructura refleja y admite la parte Services del proyecto de ApplicationCore.
- ApplicationCore\
- Servicios\
- LoanService.cs: contiene los métodos
ExtendLoanyReturnLoan. - PatronService.cs: contiene el método
RenewMembership.
- LoanService.cs: contiene los métodos
- Servicios\
En esta sección del ejercicio, usará GitHub Copilot para examinar el enfoque de pruebas unitarias implementado por el proyecto UnitTests.
Completa los siguientes pasos para usar esta sección del ejercicio:
Abra la vista Chat.
Agregue los siguientes archivos al contexto de chat:
LoanFactory.cs,PatronFactory.cs,ExtendLoan.cs,ReturnLoan.cs,RenewMembership.cs,LoanService.cs,PatronService.cs.Los archivos se encuentran en las carpetas
tests/UnitTests,tests/UnitTests/ApplicationCore/LoanService,tests/UnitTests/ApplicationCore/PatronServiceysrc/Library.ApplicationCore/Services.Escriba lo siguiente:
@workspace Explain the approach to unit testing that's been implemented in this workspace.Este mensaje pide a GitHub Copilot que explique el enfoque de las pruebas unitarias en el contexto del área de trabajo. En el mensaje se incluyen varios archivos para proporcionar contexto para la respuesta.
Dedique un minuto a revisar la respuesta de GitHub Copilot.
Debería ver una explicación similar a la siguiente descripción:
- Dependencias simuladas: las pruebas usan
NSubstitutepara crear implementaciones ficticias de interfaces. - Organización de pruebas: las pruebas se organizan en archivos independientes en función de los métodos que se están probando. Por ejemplo, los métodos
ExtendLoanyReturnLoanse prueban en archivos independientes en la carpetaLoanService. - Aserciones: las aserciones se usan para comprobar el resultado esperado de cada prueba.
- Escenarios de prueba: las pruebas cubren varios escenarios para cada método, como devolver diferentes estados en función de la entrada.
- Aislamiento: cada prueba está aislada de otras personas para evitar efectos secundarios.
- Métodos de fábrica: los métodos de fábrica se usan para crear datos de prueba de forma coherente.
- Dependencias simuladas: las pruebas usan
Escriba lo siguiente:
@workspace What are the benefits of this approach to unit testing?Dedique un minuto a revisar la respuesta de GitHub Copilot.
Debería ver una explicación que identifique una lista de ventajas similar a la siguiente lista:
- Aislamiento de dependencias: el uso de simulacros aísla la unidad de trabajo de sus dependencias.
- Repetibilidad y coherencia: los métodos fábrica proporcionan una manera coherente de crear datos de prueba.
- Legibilidad y mantenimiento: los métodos de prueba descriptivos y una disposición clara de los pasos de prueba mejoran la legibilidad de las pruebas.
- Cobertura completa: probar varios escenarios garantiza que el código sea sólido y controle diferentes casos perimetrales.
- Separación de preocupaciones: la separación de la creación de datos de prueba de la propia lógica de prueba mantiene las pruebas limpias y centradas en el comportamiento que se está probando.
- Comentarios inmediatos: la ejecución de pruebas unitarias proporciona comentarios inmediatos sobre la exactitud del código.
Agregue los siguientes archivos al contexto de chat:
ExtendLoan.cs,ReturnLoan.cs,RenewMembership.cs,LoanFactory.cs,PatronFactory.cs,LoanService.cs,PatronService.cs.Escriba lo siguiente:
@workspace How can I extend the `UnitTests` project to begin testing methods in the `Library.Infrastructure` project? Provide a process overview.Este mensaje pide a GitHub Copilot que proporcione información general sobre el proceso para ampliar el proyecto
UnitTestspara comenzar a probar métodos en el proyectoLibrary.Infrastructure. En el mensaje se incluyen varios archivos para proporcionar contexto para la respuesta.Dedique un minuto a revisar la respuesta de GitHub Copilot.
Debería ver una explicación similar a la siguiente descripción:
1. Add Project Reference: - Open the `UnitTests.csproj` file located at `tests/UnitTests/UnitTests.csproj`. - Add a reference to the `Library.Infrastructure` project. 2. Identify methods to test: - Identify the methods in the `Library.Infrastructure` project that need to be tested. For example, if you want to test the `LoanService` class, identify the methods in the `LoanService` class that need to be tested. 3. Create Test Classes: - Create new test classes in the `tests/UnitTests` directory to test the methods in the `Library.Infrastructure` project. For example, if you want to test `LoanService`, create a file named `LoanServiceTests.cs`. 4. Write Unit Tests: - In the newly created test classes, write unit tests for the methods in the `Library.Infrastructure` project. Use the xUnit framework for writing tests and NSubstitute for mocking dependencies. 5. Run Tests: - Use Visual Studio Code's integrated terminal or the Test Explorer to run the tests. - Ensure that the tests are discovered and executed correctly.
Ampliar el proyecto UnitTests para empezar a probar las clases de acceso a datos
En esta sección del ejercicio, usará GitHub Copilot para ayudarle a crear pruebas unitarias para el proyecto de Library.Infrastructure.
El proyecto Library.Infrastructure contiene clases de acceso a datos que interactúan con el sistema de archivos para cargar y guardar datos. El proyecto incluye las siguientes clases:
- JsonData: clase que carga y guarda datos JSON.
- JsonLoanRepository: clase que implementa la interfaz ILoanRepository y usa la clase JsonData para cargar y ahorrar datos de préstamo.
- JsonPatronRepository: clase que implementa la interfaz IPatronRepository y usa la clase JsonData para cargar y guardar los datos de patrón.
Empezará escribiendo pruebas unitarias para la clase JsonLoanRepository.
Completa los siguientes pasos para usar esta sección del ejercicio:
Agregue los siguientes archivos al contexto de chat:
UnitTests.csproj.Escriba el siguiente símbolo del sistema en la vista Chat:
@workspace Explain how to add a reference to the Library.Infrastructure project inside `UnitTests.csproj`.Este mensaje pide a GitHub Copilot que explique cómo agregar una referencia al proyecto de
Library.Infrastructuredentro del archivoUnitTests.csproj.Use la respuesta de GitHub Copilot para actualizar el archivo UnitTests.csproj.
El archivo UnitTests.csproj actualizado debe tener un aspecto similar al siguiente código XML:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <IsPackable>false</IsPackable> <IsTestProject>true</IsTestProject> </PropertyGroup> <ItemGroup> <PackageReference Include="coverlet.collector" Version="6.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PackageReference Include="NSubstitute" Version="5.1.0" /> <PackageReference Include="xunit" Version="2.5.3" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" /> </ItemGroup> <ItemGroup> <Using Include="Xunit" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\src\Library.ApplicationCore\Library.ApplicationCore.csproj" /> <ProjectReference Include="..\..\src\Library.Infrastructure\Library.Infrastructure.csproj" /> </ItemGroup> </Project>Abra el archivo
JsonLoanRepository.cs.JsonLoanRepository.csse encuentra en la carpetasrc/Library.Infrastructure/Data/.Dedique un minuto a revisar el archivo
JsonLoanRepository.cs.using Library.ApplicationCore; using Library.ApplicationCore.Entities; namespace Library.Infrastructure.Data; public class JsonLoanRepository : ILoanRepository { private readonly JsonData _jsonData; public JsonLoanRepository(JsonData jsonData) { _jsonData = jsonData; } public async Task<Loan?> GetLoan(int id) { await _jsonData.EnsureDataLoaded(); foreach (Loan loan in _jsonData.Loans!) { if (loan.Id == id) { Loan populated = _jsonData.GetPopulatedLoan(loan); return populated; } } return null; } public async Task UpdateLoan(Loan loan) { Loan? existingLoan = null; foreach (Loan l in _jsonData.Loans!) { if (l.Id == loan.Id) { existingLoan = l; break; } } if (existingLoan != null) { existingLoan.BookItemId = loan.BookItemId; existingLoan.PatronId = loan.PatronId; existingLoan.LoanDate = loan.LoanDate; existingLoan.DueDate = loan.DueDate; existingLoan.ReturnDate = loan.ReturnDate; await _jsonData.SaveLoans(_jsonData.Loans!); await _jsonData.LoadData(); } } }Observe los detalles siguientes sobre la clase
JsonLoanRepository:- La clase
JsonLoanRepositorycontiene dos métodos:GetLoanyUpdateLoan. - La clase
JsonLoanRepositoryusa un objetoJsonDatapara cargar y ahorrar datos de préstamos.
Empezará escribiendo pruebas unitarias para el método
GetLoan.- La clase
Cree la siguiente estructura de carpetas en el proyecto
UnitTests.- Infraestructura\
- JsonLoanRepository\
Esta estructura de carpetas refleja el enfoque usado para las pruebas unitarias
Library.ApplicationCore.- Infraestructura\
Cree un archivo de clase denominado
GetLoanen la carpetaJsonLoanRepository.Dedique un minuto a tener en cuenta los requisitos de constructor de campo y clase para las pruebas unitarias
GetLoan.El método
JsonLoanRepository.GetLoanrecibe un parámetro de identificador de préstamo cuando se llama. El método usa_jsonData.EnsureDataLoadedpara obtener los datos JSON más recientes y_jsonData.Loanspara buscar un préstamo coincidente. Si el método encuentra un identificador de préstamo coincidente, devuelve un objeto de préstamo rellenado (populated). Si el método no puede encontrar un identificador de préstamo coincidente, devuelvenull.Para las pruebas unitarias GetLoan:
Puede usar un objeto de repositorio de préstamo ficticio (
_mockLoanRepository) para ayudar a probar el caso en el que se encuentra un identificador coincidente. Cargue el simulacro con el identificador que desea encontrar. La claseReturnLoanTestmuestra cómo simular la interfazILoanRepositoryy crear instancias de un objeto de repositorio de préstamo ficticio.Puede usar un objeto de repositorio de préstamos no ficticios (
_jsonLoanRepository) para probar el caso en el que no se encuentra ningún identificador coincidente. Solo tiene que especificar un identificador de préstamo que sepa que no está en el archivo (nada más de 100 debería funcionar).Necesitará un objeto
JsonDatapara crear un objetoJsonLoanRepositoryno ficticio. Dado que el proyectoUnitTestsno tiene acceso al objetoJsonDatacreado por el proyectoConsoleApp, deberá crear uno mediante la interfazIConfiguration.
Agregue los siguientes archivos al contexto de chat:
JsonLoanRepository.cs,ReturnLoan.cs,LoanService.cs,LoanFactory.cs,JsonData.cs.Escriba lo siguiente:
@workspace Create fields and a class constructor for the `GetLoan.cs` file. The class will be used to create unit tests for the GetLoan method in the `JsonLoanRepository.cs` file. Create the following private readonly fields: `_mockLoanRepository`, `_jsonLoanRepository`, `_configuration`, and `_jsonData`. Instantiate the fields in the `GetLoanTest` constructor. Use `ConfigurationBuilder` to create a `_configuration` object that can be used to instantiate the JsonData object.Este mensaje pide a GitHub Copilot que sugiera campos y un constructor de clase.
Dedique un minuto a revisar la respuesta de GitHub Copilot.
Debería ver una sugerencia de código similar al siguiente fragmento de código:
using NSubstitute; using Library.ApplicationCore; using Library.ApplicationCore.Entities; using Library.ApplicationCore.Interfaces; using Library.Infrastructure.Data; using Microsoft.Extensions.Configuration; namespace UnitTests.Infrastructure.JsonLoanRepository; public class GetLoanTest { private readonly ILoanRepository _mockLoanRepository; private readonly JsonLoanRepository _jsonLoanRepository; private readonly IConfiguration _configuration; private readonly JsonData _jsonData; public GetLoanTest() { _mockLoanRepository = Substitute.For<ILoanRepository>(); _configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); _jsonData = new JsonData(_configuration); _jsonLoanRepository = new JsonLoanRepository(_jsonData); } // Add test methods here }Use la sugerencia de código proporcionada por GitHub Copilot para actualizar
GetLoan.cs.Observe los siguientes problemas:
Hay un conflicto entre el espacio de nombres y el uso de
JsonLoanRepositoryen el código. Debe actualizar el espacio de nombres en GetLoans.cs para seguir el patrón usado en los archivosReturnLoan.csyRenewMembership.cs.Si
ILoanRepositoryno se reconoce en el código, es posible que tenga que agregar una directivausingparaLibrary.ApplicationCorea la parte superior del archivo.Si el objeto
_configurationno se crea una instancia correctamente, es posible que debas actualizar la línea de código que contieneConfigurationBuilder. Puede simplificar el código para usar_configuration = new ConfigurationBuilder().Build();.Si GitHub Copilot sugiere un
using Library.ApplicationCore.Interfaces, puede eliminarlo de la parte superior del archivo.
Actualice el archivo
GetLoan.cspara que coincida con el siguiente fragmento de código:using NSubstitute; using Library.ApplicationCore; using Library.ApplicationCore.Entities; using Library.Infrastructure.Data; using Microsoft.Extensions.Configuration; namespace UnitTests.Infrastructure.JsonLoanRepositoryTests; public class GetLoanTest { private readonly ILoanRepository _mockLoanRepository; private readonly JsonLoanRepository _jsonLoanRepository; private readonly IConfiguration _configuration; private readonly JsonData _jsonData; public GetLoanTest() { _mockLoanRepository = Substitute.For<ILoanRepository>(); _configuration = new ConfigurationBuilder().Build(); _jsonData = new JsonData(_configuration); _jsonLoanRepository = new JsonLoanRepository(_jsonData); } }Agregue los siguientes archivos al contexto de chat:
JsonLoanRepository.cs,ReturnLoan.cs,LoanService.cs,LoanFactory.cs,JsonData.cs,Loans.json.Seleccione el contenido del archivo
GetLoan.csy a continuación, escriba el siguiente mensaje en la vista Chat:@workspace Update the selection to include a unit test for the `JsonLoanRepository.GetLoan` method. The unit test should test the case where a loan ID is found in the data. Use `_mockLoanRepository` to arrange the expected return loan. Use `_jsonLoanRepository` to return an actual loan. Asserts should verify that the return loan ID matches the expected loan ID. Use a loan ID that exists in the `Loans.json` file.Este mensaje pide a GitHub Copilot que sugiera una prueba unitaria para el método
JsonLoanRepository.GetLoan. La prueba unitaria debe probar el caso en el que se encuentra un identificador de préstamo en los datos. La prueba debe usar_mockLoanRepositorypara organizar el préstamo devuelto esperado,_jsonLoanRepositorydevolver un préstamo real y afirma que el identificador del préstamo devuelto coincide con el identificador de préstamo esperado. El identificador del préstamo debe existir en el archivoLoans.json.Dedique un minuto a revisar la respuesta de GitHub Copilot.
Debería ver una sugerencia de código similar al siguiente fragmento de código:
using NSubstitute; using Library.ApplicationCore; using Library.ApplicationCore.Entities; using Library.Infrastructure.Data; using Microsoft.Extensions.Configuration; using Xunit; namespace UnitTests.Infrastructure.JsonLoanRepositoryTests; public class GetLoanTest { private readonly ILoanRepository _mockLoanRepository; private readonly JsonLoanRepository _jsonLoanRepository; private readonly IConfiguration _configuration; private readonly JsonData _jsonData; public GetLoanTest() { _mockLoanRepository = Substitute.For<ILoanRepository>(); _configuration = new ConfigurationBuilder().Build(); _jsonData = new JsonData(_configuration); _jsonLoanRepository = new JsonLoanRepository(_jsonData); } [Fact(DisplayName = "JsonLoanRepository.GetLoan: Returns loan when loan ID is found")] public async Task GetLoan_ReturnsLoanWhenLoanIdIsFound() { // Arrange var loanId = 1; // Use a loan ID that exists in the Loans.json file var expectedLoan = new Loan { Id = loanId, BookItemId = 101, PatronId = 202, LoanDate = DateTime.Now, DueDate = DateTime.Now.AddDays(14) }; _mockLoanRepository.GetLoan(loanId).Returns(expectedLoan); await _jsonData.EnsureDataLoaded(); // Ensure data is loaded // Act var actualLoan = await _jsonLoanRepository.GetLoan(loanId); // Assert Assert.NotNull(actualLoan); Assert.Equal(expectedLoan.Id, actualLoan?.Id); } }Use la sugerencia de código proporcionada por GitHub Copilot para actualizar
GetLoan.cs.El método
JsonLoanRepository.GetLoanllama a_jsonData.EnsureDataLoadedpara asegurarse de que se cargan los datos JSON. Puede eliminar la línea de código que llama a_jsonData.EnsureDataLoadeden el método de prueba si se incluye.Si la clase
Loanno se reconoce en tu código, asegúrate de que tienes una instrucciónusing Library.ApplicationCore.Entitiesen la parte superior del archivo GetLoan.cs. La claseLoanse encuentra en el espacio de nombresLibrary.ApplicationCore.Entities.Compile la solución
AccelerateDevGitHubCopilotpara asegurarse de que no hay errores.Use la característica de autocompletar de GitHub Copilot para crear una prueba para el caso en el que no se encuentra el identificador del préstamo.
Cree una línea en blanco después del método
GetLoan_ReturnsLoanWhenLoanIdIsFound.Acepte las sugerencias de autocompletar para crear un nuevo método de prueba.
Dedique un minuto a revisar la respuesta de GitHub Copilot.
La característica de autocompletar de GitHub Copilot probablemente simulará un préstamo esperado aunque no sea necesario. Puede eliminar el código que simula un préstamo esperado, pero necesita un identificador de préstamo que no exista en el archivo
Loans.json.Debería ver una sugerencia de código similar a uno de los siguientes fragmentos de código:
[Fact(DisplayName = "JsonLoanRepository.GetLoan: Returns null when loan ID is not found")] public async Task GetLoan_ReturnsNullWhenLoanIdIsNotFound() { // Arrange var loanId = 999; // Use a loan ID that does not exist in the Loans.json file var expectedLoan = new Loan { Id = loanId, BookItemId = 101, PatronId = 202, LoanDate = DateTime.Now, DueDate = DateTime.Now.AddDays(14) }; _mockLoanRepository.GetLoan(loanId).Returns(expectedLoan); // Act var actualLoan = await _jsonLoanRepository.GetLoan(loanId); // Assert Assert.Null(actualLoan); }Acepta la sugerencia de autocompletar que asigna un valor
loanIdque no está en el conjunto de datos.Si ninguna de las sugerencias asigna
loanIdnúmeros que no están en el conjunto de datos, puede usar el método abreviado de teclado Ctrl+Entrar para enumerar sugerencias adicionales.Observe que las pruebas unitarias requieren acceso a los archivos de datos JSON.
El método
JsonLoanRepository.GetLoanusa un objetoJsonDatapara cargar y ahorrar datos de préstamos.Los archivos de datos JSON se encuentran en la carpeta
Library.Console\Json. Debe actualizar el archivoUnitTests.csprojpara incluir estos archivos en el proyecto de prueba.Agregue el siguiente fragmento XML al archivo
UnitTests.csproj:<ItemGroup> <None Include="..\..\src\Library.Console\Json\**\*"> <Link>Json\%(RecursiveDir)%(FileName)%(Extension)</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup>Esto garantiza que los archivos de datos JSON se copien en el directorio de salida cuando se ejecuten las pruebas.
Compruebe su trabajo
Hay varias maneras de ejecutar las pruebas unitarias para la clase JsonLoanRepository. Puede usar el Explorador de pruebas de Visual Studio Code, el terminal integrado o el comando dotnet test.
Completa los siguientes pasos para usar esta sección del ejercicio:
Asegúrese de que tiene abierto el archivo GetLoans.cs en el editor.
Compile la solución y asegúrese de que no haya errores.
Haga clic con el botón derecho en AccelerateDevGitHubCopilot y seleccione Compilar.
Observe el "botón de reproducción verde" a la izquierda de los métodos de prueba.
Abra la vista Explorador de pruebas de Visual Studio Code.
Para abrir la vista Explorador de pruebas, seleccione el icono con forma circular de la barra de actividades de la izquierda. El Explorador de pruebas se etiqueta como "Pruebas" en la interfaz de usuario.
El Explorador de pruebas es una vista de árbol que muestra todos los casos de prueba del área de trabajo. Puede ejecutar o depurar los casos de prueba y ver los resultados de las pruebas mediante el Explorador de pruebas.
Expanda UnitTests y los nodos subyacentes para buscar
GetLoanTest.Ejecute el caso de prueba JsonLoanRepository.GetLoan: Devuelve el préstamo cuando se encuentra el identificador de préstamo .
Observe que los resultados de la prueba se muestran en la vista Explorador de pruebas y en el Editor.
Debería ver una marca de verificación verde que indique la prueba superada.
Utilice el Editor para ejecutar el JsonLoanRepository.GetLoan: Devuelve null cuando no se encuentra la identificación del préstamo en caso de prueba.
Observe que los resultados de la prueba se muestran en la vista Explorador de pruebas y en el Editor.
Para ejecutar la prueba desde el Editor, seleccione el botón de reproducción verde situado a la izquierda del método de prueba.
Asegúrese de que la prueba JsonLoanRepository.GetLoan: devuelve null cuando no se encuentra el identificador de préstamo se realice correctamente.
Debería ver una marca de verificación verde a la izquierda de ambas pruebas.