Orquesta Agentes IA que desarrollan por ti
Verificando...
30-unit-tests-review
Procedimiento: Revisi├│n de Tests Unitarios
Calidad de Codigo
1 plugin(s)
Editor
Preview
Tareas
0
Info
Titulo
Revisa la calidad de los tests unitarios. Evalúa cobertura, identifica tests frágiles, y verifica que los tests sean significativos y mantenibles.
Descripcion
Contenido Markdown
13884 caracteres
Guardar
# Procedimiento: Revisi├│n de Tests Unitarios ## Metadata - **ID**: PROC-30 - **Frecuencia**: Pre-merge a `main`/`develop`, Post-refactoring, Semanal - **Duraci├│n estimada**: 15-30 min - **Requiere**: .NET SDK 8.0, acceso al repositorio, IDE con soporte xUnit - **Dependencias**: C├│digo compilable (sin errores de build) - **Bloquea**: Merge a main si hay tests fallando ## Objetivo Asegurar que los tests unitarios reflejan el comportamiento actual del c├│digo, mantienen cobertura adecuada, y siguen los est├índares del proyecto. ## Proyectos de Tests | Proyecto | Ubicaci├│n | Contenido | |----------|-----------|-----------| | `BigCommerceApi.Tests` | `test/BigCommerceApi.Tests/` | Tests MCP tools, servicios, validadores | | `SupplierCatalog.Sync.Tests` | `test/SupplierCatalog.Sync.Tests/` | Tests pipeline Icecat, parsers, runners | ## Stack de Testing | Componente | Uso | |------------|-----| | **xUnit** | Framework de tests | | **FluentAssertions** | Aserciones legibles | | **Moq** | Mocking de dependencias | | **Coverlet** | Cobertura de c├│digo (opcional) | ## Par├ímetros de Ejecuci├│n | Par├ímetro | Valor | Opciones | |-----------|-------|----------| | **Proyecto** | ___ | `BigCommerceApi.Tests` / `SupplierCatalog.Sync.Tests` / `Todos` | | **Modo** | ___ | `Verificaci├│n` / `Revisi├│n completa` | ## Checklist Ejecutable ### 1. Verificar que el c├│digo compila ```bash cd src # Build completo sin tests dotnet build --no-restore # Si hay errores, resolver antes de continuar ``` - [ ] Build exitoso sin errores - [ ] Warnings relevantes anotados: ___ ### 2. Ejecutar todos los tests ```bash # Ejecutar todos los tests dotnet test # Con m├ís detalle dotnet test --verbosity normal # Solo un proyecto espec├¡fico dotnet test test/BigCommerceApi.Tests/BigCommerceApi.Tests.csproj dotnet test test/SupplierCatalog.Sync.Tests/SupplierCatalog.Sync.Tests.csproj # Generar reporte de resultados dotnet test --logger "trx;LogFileName=test-results.trx" ``` - [ ] Tests ejecutados - [ ] Total tests: ___ - [ ] Passed: ___ - [ ] Failed: ___ - [ ] Skipped: ___ ### 3. Analizar tests fallidos Si hay tests fallidos: ```bash # Ver detalle de fallos dotnet test --verbosity detailed 2>&1 | grep -A 20 "Failed" # Ejecutar test espec├¡fico para debug dotnet test --filter "FullyQualifiedName~NombreDelTest" # Ejecutar tests de una clase espec├¡fica dotnet test --filter "FullyQualifiedName~OrdersCreateNormalizationTests" ``` Para cada test fallido, documentar: | Test | Error | Causa | Acci├│n | |------|-------|-------|--------| | | | | | Causas comunes: | Error | Causa probable | Soluci├│n | |-------|----------------|----------| | `Assert.Equal` failed | Comportamiento cambi├│ | Actualizar test o revertir c├│digo | | `NullReferenceException` | Mock incompleto | A├▒adir setup de mock | | `System.InvalidOperationException` | Dependencia no registrada | Revisar DI en test | | Test pasa local, falla en CI | Dependencia de entorno | Hacer test determinista | - [ ] Tests fallidos analizados - [ ] Causa identificada para cada uno ### 4. Revisar tests skipped ```bash # Buscar tests con Skip grep -r "\[Fact(Skip" test/ grep -r "\[Theory(Skip" test/ grep -r "\[Skip\]" test/ # Buscar tests comentados (mala pr├íctica) grep -r "//\s*\[Fact\]" test/ grep -r "//\s*\[Theory\]" test/ ``` Para cada test skipped: | Test | Raz├│n del Skip | Fecha | Acci├│n | |------|----------------|-------|--------| | | | | Eliminar / Reactivar / Mantener con ticket | - [ ] Tests skipped revisados: ___ - [ ] Tests skipped sin justificaci├│n: ___ ### 5. Verificar cobertura de cambios recientes ```bash # Ver archivos de c├│digo modificados recientemente git diff main --name-only -- "*.cs" | grep -v Tests | grep -v docs # Para cada archivo modificado, verificar test correspondiente # Ejemplo: OrdersCreateTool.cs ÔåÆ OrdersCreateToolTests.cs ``` | Archivo Modificado | Test Correspondiente | Existe | Cubre cambio | |--------------------|---------------------|--------|--------------| | | | S├¡/No | S├¡/No/Parcial | - [ ] Cambios recientes tienen cobertura de tests ### 6. Revisar calidad de tests existentes **Checklist de calidad por test:** - [ ] Nombre descriptivo: `Method_Condition_ExpectedResult` - [ ] Una responsabilidad por test - [ ] Arrange/Act/Assert claramente separados - [ ] No depende de otros tests (aislado) - [ ] No depende de estado externo (BD, archivos, red) - [ ] Usa mocks para dependencias externas ### 7. Verificar est├índares del proyecto **Convenci├│n de nombres:** ```csharp // Correcto [Fact] public async Task InvokeAsync_WhenTransactionTypeIsString_ShouldNormalizeToInteger() // Incorrecto [Fact] public async Task Test1() [Fact] public async Task TransactionTypeTest() ``` **Estructura de test:** ```csharp [Fact] public async Task MethodName_WhenCondition_ShouldExpectedBehavior() { // Arrange (Given) var sut = new SystemUnderTest(); var input = CreateValidInput(); // Act (When) var result = await sut.DoSomethingAsync(input); // Assert (Then) result.Should().NotBeNull(); result.Value.Should().Be(expectedValue); } ``` **Uso de FluentAssertions:** ```csharp // Usar FluentAssertions result.Should().BeTrue(); result.Should().BeEquivalentTo(expected); exception.Should().BeOfType<McpToolException>(); // No usar Assert de xUnit directamente Assert.True(result); Assert.Equal(expected, result); ``` - [ ] Tests revisados siguen convenciones ### 8. Identificar tests faltantes ├üreas cr├¡ticas que DEBEN tener tests: **BigCommerceApi:** | ├ürea | Clase/M├®todo | Tiene tests | |------|--------------|-------------| | Normalizaci├│n de input | `OrdersCreateTool.NormalizeInput` | | | Validaci├│n de shipping | `ShippingAddressValidator` | | | Scopes/Auth | `McpToolInvoker.CheckScope` | | | Sales mode | `SalesCustomerService` | | | Transformaci├│n de respuesta | Mappers | | **SupplierCatalog.Sync:** | ├ürea | Clase/M├®todo | Tiene tests | |------|--------------|-------------| | JSON parsing | `IcecatJsonParser` | | | Feature extraction | `FeatureExtractor` | | | Profile generation | `ConversationProfileBuilder` | | | Scope computation | `ScopeFilterEngine` | | | Nightly runner | `NightlyRunner.RunCycleAsync` | | - [ ] Tests faltantes identificados: ___ ### 9. Ejecutar con cobertura (opcional) ```bash # Instalar reportgenerator si no est├í dotnet tool install -g dotnet-reportgenerator-globaltool # Ejecutar tests con cobertura dotnet test --collect:"XPlat Code Coverage" # Generar reporte HTML reportgenerator \ -reports:"**/coverage.cobertura.xml" \ -targetdir:"coverage-report" \ -reporttypes:Html # Abrir reporte (Windows) start coverage-report/index.html ``` Umbrales de cobertura sugeridos: | ├ürea | M├¡nimo | Objetivo | |------|--------|----------| | MCP Tools | 70% | 85% | | Services | 60% | 80% | | Parsers/Builders | 80% | 90% | | Utilities | 50% | 70% | - [ ] Cobertura actual: ___% - [ ] ├üreas bajo umbral: ___ ### 10. Corregir problemas encontrados **Para tests fallidos:** ```bash git checkout -b fix/failing-tests # Corregir test o c├│digo seg├║n an├ílisis dotnet test --filter "FullyQualifiedName~TestQueEstabFallando" git commit -m "test: fix failing tests - Fixed: [lista de tests] - Cause: [explicaci├│n] PROC-30" ``` **Para tests faltantes:** ```bash git checkout -b test/add-missing-tests # Crear archivo de test si no existe # Seguir convenci├│n: ClassNameTests.cs git commit -m "test: add tests for [├írea] - Added: [lista de tests nuevos] - Coverage: [├írea cubierta] PROC-30" ``` - [ ] Tests fallidos corregidos - [ ] Tests faltantes creados (o tickets creados) ### 11. Verificaci├│n final ```bash # Ejecutar todos los tests una ├║ltima vez dotnet test # Verificar que no hay tests skipped sin justificaci├│n dotnet test --filter "Category!=Integration" 2>&1 | tail -20 ``` - [ ] Todos los tests pasan - [ ] No hay tests skipped sin ticket asociado - [ ] PR abierto (si hubo cambios) ## Plantilla para Nuevos Tests ```csharp using FluentAssertions; using Moq; using Xunit; namespace BigCommerceApi.Tests.Mcp.Tools; public class MyToolTests { private readonly Mock<IDependency> _dependencyMock; private readonly MyTool _sut; public MyToolTests() { _dependencyMock = new Mock<IDependency>(); _sut = new MyTool(_dependencyMock.Object); } [Fact] public async Task InvokeAsync_WhenValidInput_ShouldReturnSuccess() { // Arrange var input = CreateValidInput(); _dependencyMock .Setup(x => x.DoSomethingAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())) .ReturnsAsync(new Result { Success = true }); // Act var result = await _sut.InvokeAsync("api-key", input, CancellationToken.None); // Assert result.Should().NotBeNull(); var response = result.Should().BeOfType<SuccessResponse>().Subject; response.Success.Should().BeTrue(); } [Fact] public async Task InvokeAsync_WhenInvalidInput_ShouldThrow400() { // Arrange var input = CreateInvalidInput(); // Act var act = () => _sut.InvokeAsync("api-key", input, CancellationToken.None); // Assert var exception = await act.Should().ThrowAsync<McpToolException>(); exception.Which.StatusCode.Should().Be(400); } [Theory] [InlineData("value1", 1)] [InlineData("value2", 2)] [InlineData("value3", 3)] public async Task InvokeAsync_WhenDifferentInputs_ShouldNormalizeCorrectly( string input, int expected) { // Arrange & Act & Assert // ... } private static JsonElement CreateValidInput() { return JsonSerializer.Deserialize<JsonElement>(""" { "field1": "value1", "field2": 123 } """); } private static JsonElement CreateInvalidInput() { return JsonSerializer.Deserialize<JsonElement>("{}"); } } ``` ## Troubleshooting | S├¡ntoma | Causa | Acci├│n | |---------|-------|--------| | Tests pasan local, fallan en CI | Diferencia de entorno | Verificar .NET version, timezone, locale | | Test flaky (a veces pasa) | Race condition o dependencia externa | Hacer determinista, usar mocks | | `Could not load file or assembly` | Dependencia faltante | `dotnet restore`, verificar referencias | | `No test matches the given filter` | Filtro incorrecto | Verificar nombre exacto del test | | Mock no se llama | Setup incorrecto | Verificar `It.IsAny` vs valores exactos | ## Qu├® Testear vs No Testear | Testear | No Testear | |---------|------------| | L├│gica de negocio | Getters/Setters triviales | | Validaciones | C├│digo de terceros (librer├¡as) | | Transformaciones de datos | Infraestructura (DB real, HTTP real) | | Casos edge/boundary | Configuraci├│n | | Manejo de errores | C├│digo generado | ## Resultado - **├ëxito**: - 100% tests pasan - 0 tests skipped sin justificaci├│n - Cambios recientes tienen cobertura - Convenciones seguidas - **Parcial**: - Tests pasan pero falta cobertura - Tickets creados para tests pendientes - **Fallo**: - Tests fallando ÔåÆ NO mergear hasta resolver - Build roto ÔåÆ Prioridad m├íxima ## Advertencias - **NO** comentar tests para que pasen - **NO** a├▒adir `[Skip]` sin ticket de seguimiento - **NO** mockear la clase bajo test (SUT) - **NO** hacer tests que dependan del orden de ejecuci├│n - **NO** usar `Thread.Sleep` en tests (usar async/await correctamente) ## Mensaje de Finalizaci├│n **IMPORTANTE - ACCI├ôN REQUERIDA AL FINALIZAR:** Cuando hayas completado todos los pasos de este procedimiento, DEBES ejecutar el siguiente comando usando la herramienta Bash: Ejecuta: `echo "====== PROCESO TERMINADO [$(date +%H%M%S)] ======" && echo "RESULTADO: Tests X/X passed, 0 failed, 0 skipped"` Sustituye X por el n├║mero real de tests. --- ## Output Estructurado (Nexus) Al finalizar, el agente DEBE generar un bloque JSON con el siguiente formato para que Nexus pueda procesarlo automaticamente: ```json { "result": "success", "summary": "Ejecucion de PROC-30 completada. [Descripcion breve de resultados]", "metrics": { "issues_found": 0, "issues_resolved": 0, "tests_passed": 100, "tests_failed": 0, "coverage_percent": 78, "custom": { "procedure_specific_metric": "value" } }, "backlog_items": [ { "title": "Titulo del item de seguimiento", "description": "Descripcion detallada si se requiere accion futura", "priority": "medium", "type": "improvement", "tags": ["proc-30"] } ], "next_steps": [ "Accion recomendada 1", "Accion recomendada 2" ], "warnings": [ "Advertencias encontradas durante la ejecucion" ] } ``` **Campos requeridos:** - `result`: `"success"` | `"partial"` | `"failed"` - `summary`: Resumen ejecutivo en 1-3 lineas **Metricas especificas de este procedure:** - tests_total, tests_passed, tests_failed, tests_skipped, coverage_percent **Criterios de resultado:** - `success`: Procedimiento completado sin errores criticos - `partial`: Completado con algunos problemas menores o items pendientes - `failed`: Error critico o no se pudo completar ## Historial de Ejecuciones | Fecha | Ejecutor | Proyecto | Total | Passed | Failed | Skipped | Resultado | |-------|----------|----------|-------|--------|--------|---------|-----------| | | | | | | | | |
H1
H2
H3
Bold
Italic
Code
Lista
Num
Task
Code Block
Link
Nexus Platform
Reconectando
Recuperando la conexion
Se ha interrumpido la conexion con el servidor. Estamos reconectando automaticamente.
Reconectando...
Manten esta pestana abierta, volvemos enseguida.
No hemos podido reconectar
El servidor puede estar reiniciandose o tu conexion a internet es inestable.
Reintentar
La sesion ha expirado
Recarga la pagina para iniciar una nueva sesion.
Recargar
Si no vuelve en 30 segundos, recarga la pagina.