refacil-sdd-ai 1.0.8 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/apply/SKILL.md +28 -1
- package/skills/propose/SKILL.md +4 -2
- package/skills/setup/SKILL.md +51 -18
- package/skills/test/SKILL.md +49 -60
- package/skills/test/testing-patterns.md +42 -129
package/package.json
CHANGED
package/skills/apply/SKILL.md
CHANGED
|
@@ -20,6 +20,31 @@ Este comando envuelve la funcionalidad de OpenSpec apply y agrega las convencion
|
|
|
20
20
|
|
|
21
21
|
## Instrucciones
|
|
22
22
|
|
|
23
|
+
### Paso 0: Verificar que existan artefactos SDD
|
|
24
|
+
|
|
25
|
+
Busca carpetas en `openspec/changes/` que contengan los artefactos requeridos: `proposal.md`, `specs.md`, `design.md`, `tasks.md`.
|
|
26
|
+
|
|
27
|
+
- **Si `openspec/changes/` no existe o esta vacia**: Informa al usuario:
|
|
28
|
+
```
|
|
29
|
+
No hay cambios propuestos. Antes de implementar necesitas definir los artefactos SDD.
|
|
30
|
+
Ejecuta: /refacil:propose "descripcion del cambio"
|
|
31
|
+
```
|
|
32
|
+
**Detente.**
|
|
33
|
+
|
|
34
|
+
- **Si hay carpetas pero les faltan artefactos** (falta proposal.md, specs.md, design.md o tasks.md): Informa al usuario:
|
|
35
|
+
```
|
|
36
|
+
El cambio en openspec/changes/[nombre]/ esta incompleto.
|
|
37
|
+
Faltan: [lista de artefactos faltantes]
|
|
38
|
+
Ejecuta: /refacil:propose para completar los artefactos antes de implementar.
|
|
39
|
+
```
|
|
40
|
+
**Detente.**
|
|
41
|
+
|
|
42
|
+
- **Si hay multiples cambios activos**: Lista las carpetas y pregunta cual implementar.
|
|
43
|
+
|
|
44
|
+
- **Si los 4 artefactos existen**: Continua al siguiente paso.
|
|
45
|
+
|
|
46
|
+
**IMPORTANTE**: Este comando NUNCA genera artefactos SDD. Si no existen, el usuario debe usar `/refacil:propose`. La separacion entre planificacion e implementacion es fundamental en la metodologia SDD-AI.
|
|
47
|
+
|
|
23
48
|
### Paso 1: Validar rama de trabajo
|
|
24
49
|
|
|
25
50
|
Ejecuta `git branch --show-current` para obtener la rama actual.
|
|
@@ -90,5 +115,7 @@ Al terminar la implementacion de OpenSpec, agrega este resumen:
|
|
|
90
115
|
|
|
91
116
|
## Reglas
|
|
92
117
|
|
|
118
|
+
- NUNCA implementar codigo sin los 4 artefactos SDD completos (proposal.md, specs.md, design.md, tasks.md)
|
|
119
|
+
- NUNCA generar artefactos SDD desde este comando — eso es responsabilidad exclusiva de `/refacil:propose`
|
|
93
120
|
- SIEMPRE leer los artefactos completos antes de escribir codigo
|
|
94
|
-
- Si `openspec/changes/` no tiene cambios activos, informar y
|
|
121
|
+
- Si `openspec/changes/` no tiene cambios activos o estan incompletos, informar y redirigir a `/refacil:propose`
|
package/skills/propose/SKILL.md
CHANGED
|
@@ -82,6 +82,8 @@ Siguiente paso: ejecuta /refacil:apply para implementar las tasks.
|
|
|
82
82
|
|
|
83
83
|
## Reglas
|
|
84
84
|
|
|
85
|
-
-
|
|
86
|
-
-
|
|
85
|
+
- **NUNCA escribir, modificar o generar codigo fuente** en esta fase — solo artefactos SDD (proposal.md, specs.md, design.md, tasks.md)
|
|
86
|
+
- Aunque el usuario pase una descripcion completa y detallada en $ARGUMENTS, la salida es EXCLUSIVAMENTE artefactos de planificacion
|
|
87
|
+
- Si el usuario pide que tambien implemente, responder: "La implementacion se hace con `/refacil:apply` despues de aprobar los artefactos."
|
|
88
|
+
- Siempre explorar el codebase ANTES de generar artefactos (para que el design sea realista)
|
|
87
89
|
- Los criterios de aceptacion deben ser especificos y testeables
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -33,19 +33,31 @@ Ejecuta `openspec --version 2>&1`.
|
|
|
33
33
|
- Verificar permisos (puede necesitar `sudo` en Linux/Mac)
|
|
34
34
|
- Verificar que npm global bin esta en el PATH
|
|
35
35
|
|
|
36
|
-
### Paso 3:
|
|
36
|
+
### Paso 3: Configurar perfil OpenSpec con todos los workflows
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Antes de inicializar, configura el perfil global para garantizar que se instalen TODOS los workflows requeridos:
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
```bash
|
|
41
|
+
openspec config set profile custom
|
|
42
|
+
openspec config set workflows "explore,new,continue,apply,ff,sync,archive,bulk-archive,verify,onboard"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Verifica que la configuracion quedo correcta:
|
|
46
|
+
```bash
|
|
47
|
+
openspec config list
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Debe mostrar `profile: custom` y los 10 workflows listados.
|
|
51
|
+
|
|
52
|
+
### Paso 4: Inicializar OpenSpec en el repo
|
|
53
|
+
- ejecuta:
|
|
42
54
|
```bash
|
|
43
55
|
openspec init --tools claude,cursor
|
|
44
56
|
```
|
|
45
57
|
|
|
46
58
|
**IMPORTANTE**: `openspec init` tambien instala sus propios comandos (`opsx:*`) en `.claude/` y `.cursor/`. Esto es normal y esperado. Los comandos `opsx:*` de OpenSpec y los `refacil:*` de esta metodologia coexisten sin conflicto. Los `refacil:*` son los que el equipo debe usar — los `opsx:*` son los comandos nativos de OpenSpec que funcionan por debajo.
|
|
47
59
|
|
|
48
|
-
### Paso
|
|
60
|
+
### Paso 5: Configurar OpenSpec
|
|
49
61
|
|
|
50
62
|
Verifica si existe `openspec/config.yaml`.
|
|
51
63
|
|
|
@@ -60,13 +72,13 @@ language: spanish
|
|
|
60
72
|
|
|
61
73
|
**Si ya existe**, verifica que tenga `language: spanish`. Si no lo tiene, sugiere agregarlo.
|
|
62
74
|
|
|
63
|
-
### Paso
|
|
75
|
+
### Paso 6: Generar AGENTS.md
|
|
64
76
|
|
|
65
77
|
**Este es el paso mas importante.** Analiza el repositorio automaticamente para generar un `AGENTS.md` personalizado.
|
|
66
78
|
|
|
67
79
|
Verifica si ya existe `AGENTS.md` en la raiz. Si existe, pregunta al usuario si quiere regenerarlo. Si no quiere, salta este paso.
|
|
68
80
|
|
|
69
|
-
####
|
|
81
|
+
#### 6.1 Analizar el repositorio
|
|
70
82
|
|
|
71
83
|
Lee estos archivos si existen (no falles si alguno no existe, simplemente omitelo):
|
|
72
84
|
- `package.json` — nombre, scripts, dependencias (tech stack)
|
|
@@ -80,7 +92,7 @@ Lee estos archivos si existen (no falles si alguno no existe, simplemente omitel
|
|
|
80
92
|
- `Dockerfile` o `docker-compose.yml` — info de deployment
|
|
81
93
|
- `.env.example` — variables de entorno
|
|
82
94
|
|
|
83
|
-
####
|
|
95
|
+
#### 6.2 Generar el AGENTS.md
|
|
84
96
|
|
|
85
97
|
Con la informacion recopilada, genera un archivo `AGENTS.md` completo. El contenido debe ser en espanol con terminos tecnicos en ingles.
|
|
86
98
|
|
|
@@ -107,7 +119,7 @@ Secciones obligatorias:
|
|
|
107
119
|
- "Nunca hacer": anti-patrones especificos para el stack
|
|
108
120
|
- "Preguntar primero": cambios de alto impacto que requieren confirmacion
|
|
109
121
|
|
|
110
|
-
####
|
|
122
|
+
#### 6.3 Fallback si el analisis falla
|
|
111
123
|
|
|
112
124
|
Si por cualquier razon no puedes generar un AGENTS.md completo (archivos no legibles, repo vacio, error inesperado), genera un AGENTS.md minimo con esta estructura:
|
|
113
125
|
|
|
@@ -147,13 +159,32 @@ TODO: Completar con las convenciones del equipo
|
|
|
147
159
|
|
|
148
160
|
Informa al usuario que el AGENTS.md fue generado con secciones TODO que debe completar manualmente o ejecutando `/refacil:setup` de nuevo.
|
|
149
161
|
|
|
150
|
-
####
|
|
162
|
+
#### 6.4 Mostrar al usuario
|
|
151
163
|
|
|
152
164
|
Muestra el AGENTS.md generado completo. Pregunta si quiere ajustar algo antes de guardarlo.
|
|
153
165
|
|
|
154
166
|
Si el usuario aprueba (o no tiene cambios), escribe el archivo en la raiz del proyecto.
|
|
155
167
|
|
|
156
|
-
### Paso
|
|
168
|
+
### Paso 7: Verificar skills
|
|
169
|
+
|
|
170
|
+
#### 7.1 Verificar skills de OpenSpec
|
|
171
|
+
|
|
172
|
+
Verifica que existan las 10 carpetas de skills de OpenSpec en `.claude/skills/`:
|
|
173
|
+
- `openspec-apply-change`
|
|
174
|
+
- `openspec-archive-change`
|
|
175
|
+
- `openspec-bulk-archive-change`
|
|
176
|
+
- `openspec-continue-change`
|
|
177
|
+
- `openspec-explore`
|
|
178
|
+
- `openspec-ff-change`
|
|
179
|
+
- `openspec-new-change`
|
|
180
|
+
- `openspec-onboard`
|
|
181
|
+
- `openspec-sync-specs`
|
|
182
|
+
- `openspec-verify-change`
|
|
183
|
+
|
|
184
|
+
- Si las 10 existen: "Skills OpenSpec: 10/10 instaladas OK"
|
|
185
|
+
- Si faltan algunas: informa cuales faltan. Sugiere ejecutar de nuevo `openspec init --tools claude,cursor` o verificar el perfil con `openspec config list`.
|
|
186
|
+
|
|
187
|
+
#### 7.2 Verificar skills de Refacil
|
|
157
188
|
|
|
158
189
|
Verifica que existan las carpetas `.claude/skills/refacil-*` y/o `.cursor/skills/refacil-*`.
|
|
159
190
|
|
|
@@ -172,16 +203,18 @@ Verifica que existan las carpetas `.claude/skills/refacil-*` y/o `.cursor/skills
|
|
|
172
203
|
Luego reinicia esta sesion de Claude Code / Cursor.
|
|
173
204
|
```
|
|
174
205
|
|
|
175
|
-
### Paso
|
|
206
|
+
### Paso 8: Resumen final
|
|
176
207
|
|
|
177
208
|
```
|
|
178
209
|
=== refacil:setup completado ===
|
|
179
|
-
Node.js:
|
|
180
|
-
OpenSpec:
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
210
|
+
Node.js: [version] OK
|
|
211
|
+
OpenSpec: [version] OK
|
|
212
|
+
Perfil workflows: custom (10 workflows) OK
|
|
213
|
+
openspec/: Inicializado OK
|
|
214
|
+
config.yaml: Configurado OK
|
|
215
|
+
AGENTS.md: Generado OK
|
|
216
|
+
Skills OpenSpec: 10/10 instaladas OK
|
|
217
|
+
Skills Refacil: [N] instaladas OK
|
|
185
218
|
|
|
186
219
|
IMPORTANTE: Si acabas de instalar las skills por primera vez,
|
|
187
220
|
debes REINICIAR la sesion de Claude Code o Cursor para que
|
package/skills/test/SKILL.md
CHANGED
|
@@ -1,18 +1,47 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: refacil:test
|
|
3
|
-
description: Generar tests unitarios basados en los artefactos de OpenSpec o para archivos especificos —
|
|
3
|
+
description: Generar tests unitarios basados en los artefactos de OpenSpec o para archivos especificos — detecta automaticamente el stack y patrones del proyecto
|
|
4
4
|
user-invocable: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# refacil:test — Generacion de Tests Unitarios
|
|
8
8
|
|
|
9
|
-
Eres un asistente de testing que genera pruebas unitarias de alta calidad.
|
|
9
|
+
Eres un asistente de testing que genera pruebas unitarias de alta calidad, adaptandose al stack tecnologico del proyecto.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Antes de empezar
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
### Verificar prerequisitos
|
|
14
|
+
|
|
15
|
+
1. **OpenSpec instalado**: Ejecuta `openspec --version 2>&1`. Si el comando falla o no se reconoce, informa al usuario: "OpenSpec no esta instalado. Ejecuta `/refacil:setup` para instalarlo y configurar el repositorio." y **detente**.
|
|
16
|
+
|
|
17
|
+
2. **OpenSpec inicializado**: Verifica que exista la carpeta `openspec/` en la raiz del proyecto. Si no existe, informa al usuario: "OpenSpec no esta inicializado en este repositorio. Ejecuta `/refacil:setup` para configurarlo." y **detente**.
|
|
18
|
+
|
|
19
|
+
3. **AGENTS.md**: Si existe `AGENTS.md` en la raiz del proyecto, leelo para entender las convenciones, arquitectura y patrones. Si NO existe, informa al usuario: "No se encontro AGENTS.md. Ejecuta `/refacil:setup` para generarlo." y **detente**.
|
|
20
|
+
|
|
21
|
+
### Detectar stack tecnologico
|
|
22
|
+
|
|
23
|
+
**IMPORTANTE**: Este skill NO asume ningun stack. Antes de generar tests, detecta automaticamente:
|
|
24
|
+
|
|
25
|
+
1. **Lenguaje**: Lee `package.json`, `pom.xml`, `build.gradle`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `Gemfile`, o los archivos fuente para determinar el lenguaje principal.
|
|
26
|
+
|
|
27
|
+
2. **Framework de testing**: Busca la configuracion de tests existente:
|
|
28
|
+
- JavaScript/TypeScript: `jest.config.*`, `vitest.config.*`, `.mocharc.*`, `karma.conf.*`, seccion `jest` en `package.json`
|
|
29
|
+
- Python: `pytest.ini`, `pyproject.toml` (seccion `[tool.pytest]`), `setup.cfg`
|
|
30
|
+
- Java/Kotlin: `pom.xml` (JUnit/Mockito), `build.gradle` (dependencias de test)
|
|
31
|
+
- Go: archivos `_test.go` existentes
|
|
32
|
+
- Rust: archivos con `#[cfg(test)]`
|
|
33
|
+
- Otro: busca archivos de test existentes para inferir patron
|
|
34
|
+
|
|
35
|
+
3. **Patrones existentes**: Busca tests existentes en el proyecto (`*.spec.*`, `*.test.*`, `test_*`, `*_test.*`) y analiza:
|
|
36
|
+
- Estructura de archivos (donde se ubican los tests)
|
|
37
|
+
- Convencion de nombrado
|
|
38
|
+
- Como se hacen los mocks/stubs
|
|
39
|
+
- Framework de assertions usado
|
|
40
|
+
- Setup/teardown patterns
|
|
41
|
+
|
|
42
|
+
4. **Script de ejecucion**: Identifica como se ejecutan los tests (`npm test`, `pytest`, `go test`, `cargo test`, `mvn test`, etc.)
|
|
43
|
+
|
|
44
|
+
Si existe [testing-patterns.md](testing-patterns.md) en esta misma carpeta de skill, usalo como **referencia adicional**, pero **siempre prioriza los patrones reales detectados en el proyecto**. Si los patrones del proyecto difieren de testing-patterns.md, sigue los del proyecto.
|
|
16
45
|
|
|
17
46
|
## Instrucciones
|
|
18
47
|
|
|
@@ -27,18 +56,18 @@ Si el usuario ejecuta `/refacil:test` sin argumentos:
|
|
|
27
56
|
- `design.md` — Identificar componentes y archivos creados/modificados
|
|
28
57
|
- `tasks.md` — Identificar archivos implementados
|
|
29
58
|
|
|
30
|
-
3. **Para cada archivo creado/modificado**, genera un
|
|
59
|
+
3. **Para cada archivo creado/modificado**, genera un test file:
|
|
31
60
|
|
|
32
|
-
a. **Analiza el archivo** — Entiende que hace, sus metodos publicos, dependencias
|
|
61
|
+
a. **Analiza el archivo** — Entiende que hace, sus metodos/funciones publicos, dependencias
|
|
33
62
|
b. **Mapea criterios** — Cada CA-XX y CR-XX del spec = al menos 1 test
|
|
34
|
-
c. **Agrega edge cases** — null,
|
|
35
|
-
d. **Genera el test** — Siguiendo los patrones
|
|
63
|
+
c. **Agrega edge cases** — null/nil/None, valores limite, errores
|
|
64
|
+
d. **Genera el test** — Siguiendo los patrones detectados del proyecto (lenguaje, framework, estructura, nombrado)
|
|
36
65
|
|
|
37
|
-
4. **Ejecutar tests**: Corre
|
|
66
|
+
4. **Ejecutar tests**: Corre el comando de tests del proyecto y verifica que pasen.
|
|
38
67
|
|
|
39
68
|
5. **Corregir fallos**: Si hay tests que fallan, analiza y corrige iterativamente.
|
|
40
69
|
|
|
41
|
-
6. **Reportar coverage**:
|
|
70
|
+
6. **Reportar coverage**: Si el proyecto tiene script de coverage, ejecutalo y reporta:
|
|
42
71
|
```
|
|
43
72
|
=== Reporte de Tests ===
|
|
44
73
|
Tests generados: [N] archivos
|
|
@@ -52,62 +81,22 @@ Si el usuario ejecuta `/refacil:test` sin argumentos:
|
|
|
52
81
|
|
|
53
82
|
### Modo 2: Tests para archivo especifico (con argumento)
|
|
54
83
|
|
|
55
|
-
Si el usuario pasa un archivo: `/refacil:test src/mi-
|
|
84
|
+
Si el usuario pasa un archivo: `/refacil:test src/mi-archivo.ext`
|
|
56
85
|
|
|
57
86
|
1. **Lee el archivo** especificado ($ARGUMENTS)
|
|
58
|
-
2. **Analiza** sus metodos publicos, dependencias, logica
|
|
59
|
-
3. **Genera** el
|
|
87
|
+
2. **Analiza** sus metodos/funciones publicos, dependencias, logica
|
|
88
|
+
3. **Genera** el test file correspondiente siguiendo las convenciones del proyecto
|
|
60
89
|
4. **Ejecuta** y corrige hasta que pasen
|
|
61
90
|
|
|
62
|
-
## Estructura de un test
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
// archivo.spec.ts
|
|
66
|
-
import { Test, TestingModule } from '@nestjs/testing';
|
|
67
|
-
|
|
68
|
-
describe('NombreClase', () => {
|
|
69
|
-
let service: NombreClase;
|
|
70
|
-
|
|
71
|
-
beforeEach(async () => {
|
|
72
|
-
jest.clearAllMocks();
|
|
73
|
-
const module: TestingModule = await Test.createTestingModule({
|
|
74
|
-
providers: [
|
|
75
|
-
NombreClase,
|
|
76
|
-
{ provide: 'DependenciaPort', useValue: mockDependencia },
|
|
77
|
-
],
|
|
78
|
-
}).compile();
|
|
79
|
-
service = module.get<NombreClase>(NombreClase);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
describe('nombreMetodo', () => {
|
|
83
|
-
// Criterios de aceptacion
|
|
84
|
-
it('should [resultado] when [condicion] (CA-01)', async () => {
|
|
85
|
-
// Arrange - Mockear dependencias
|
|
86
|
-
// Act - Ejecutar metodo
|
|
87
|
-
// Assert - Verificar resultado
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Criterios de rechazo
|
|
91
|
-
it('should throw [error] when [condicion invalida] (CR-01)', async () => {
|
|
92
|
-
// Arrange - Preparar escenario de error
|
|
93
|
-
// Act & Assert - Verificar que falla controladamente
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Edge cases
|
|
97
|
-
it('should handle null input gracefully', async () => {
|
|
98
|
-
// ...
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
```
|
|
103
|
-
|
|
104
91
|
## Reglas
|
|
105
92
|
|
|
93
|
+
- **NUNCA hardcodear un stack** — siempre detectar del proyecto real
|
|
106
94
|
- Cada criterio de aceptacion (CA-XX) debe tener al menos 1 test
|
|
107
95
|
- Cada criterio de rechazo (CR-XX) debe tener al menos 1 test
|
|
108
96
|
- Coverage minimo del 80% en archivos nuevos
|
|
109
97
|
- Los tests deben ser independientes entre si
|
|
110
98
|
- Mocks minimos y necesarios — no mockear lo que se puede testear directo
|
|
111
|
-
- Nombres descriptivos
|
|
112
|
-
- Usar los alias de rutas del proyecto
|
|
113
|
-
- Los tests deben pasar con
|
|
99
|
+
- Nombres descriptivos segun la convencion del proyecto
|
|
100
|
+
- Usar los alias de rutas/imports del proyecto
|
|
101
|
+
- Los tests deben pasar con el comando de test del proyecto sin errores
|
|
102
|
+
- Ubicar los tests donde el proyecto los espera (misma carpeta, carpeta `test/`, `__tests__/`, etc.)
|
|
@@ -1,150 +1,63 @@
|
|
|
1
|
-
# Patrones de Testing
|
|
1
|
+
# Patrones de Testing — Referencia
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
archivo.ts → archivo.spec.ts (en la misma carpeta)
|
|
7
|
-
mi-servicio.ts → mi-servicio.spec.ts
|
|
8
|
-
product.mapper.ts → product.mapper.spec.ts
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## Patron para servicios NestJS
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
import { Test, TestingModule } from '@nestjs/testing';
|
|
15
|
-
import { MiServicio } from './mi-servicio';
|
|
16
|
-
|
|
17
|
-
// Mocks declarados fuera del describe
|
|
18
|
-
const mockDependencia = {
|
|
19
|
-
metodo1: jest.fn(),
|
|
20
|
-
metodo2: jest.fn(),
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
describe('MiServicio', () => {
|
|
24
|
-
let service: MiServicio;
|
|
25
|
-
|
|
26
|
-
beforeEach(async () => {
|
|
27
|
-
jest.clearAllMocks();
|
|
28
|
-
|
|
29
|
-
const module: TestingModule = await Test.createTestingModule({
|
|
30
|
-
providers: [
|
|
31
|
-
MiServicio,
|
|
32
|
-
{ provide: 'DEPENDENCIA_PORT', useValue: mockDependencia },
|
|
33
|
-
],
|
|
34
|
-
}).compile();
|
|
35
|
-
|
|
36
|
-
service = module.get<MiServicio>(MiServicio);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe('metodoPublico', () => {
|
|
40
|
-
it('should [resultado esperado] when [condicion]', async () => {
|
|
41
|
-
// Arrange
|
|
42
|
-
mockDependencia.metodo1.mockResolvedValue({ /* datos */ });
|
|
43
|
-
|
|
44
|
-
// Act
|
|
45
|
-
const result = await service.metodoPublico(/* params */);
|
|
46
|
-
|
|
47
|
-
// Assert
|
|
48
|
-
expect(result).toEqual(/* esperado */);
|
|
49
|
-
expect(mockDependencia.metodo1).toHaveBeenCalledWith(/* params */);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
```
|
|
3
|
+
> **NOTA**: Este archivo es una referencia generica. Los tests generados deben seguir
|
|
4
|
+
> los patrones reales del proyecto (detectados automaticamente). Si el proyecto ya tiene
|
|
5
|
+
> tests, esos patrones tienen prioridad sobre los de este archivo.
|
|
54
6
|
|
|
55
|
-
##
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
import { miFuncion } from './mi-util';
|
|
59
|
-
|
|
60
|
-
describe('miFuncion', () => {
|
|
61
|
-
it('should [resultado] with valid input', () => {
|
|
62
|
-
expect(miFuncion('input')).toBe('expected');
|
|
63
|
-
});
|
|
7
|
+
## Estructura de archivos de test
|
|
64
8
|
|
|
65
|
-
|
|
66
|
-
expect(miFuncion(null)).toBeNull();
|
|
67
|
-
});
|
|
9
|
+
La ubicacion de los tests depende del proyecto. Patrones comunes:
|
|
68
10
|
|
|
69
|
-
it('should handle edge case [X]', () => {
|
|
70
|
-
expect(miFuncion('')).toBe('default');
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
11
|
```
|
|
12
|
+
# Mismo directorio (comun en JS/TS, Go, Rust)
|
|
13
|
+
archivo.ts → archivo.spec.ts / archivo.test.ts
|
|
14
|
+
archivo.go → archivo_test.go
|
|
74
15
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
import { MiMapper } from './mi.mapper';
|
|
79
|
-
|
|
80
|
-
describe('MiMapper', () => {
|
|
81
|
-
describe('toDomain', () => {
|
|
82
|
-
it('should map ORM entity to domain entity', () => {
|
|
83
|
-
const ormEntity = { id: '123', name: 'test', status: 'ACTIVE' };
|
|
84
|
-
const result = MiMapper.toDomain(ormEntity);
|
|
85
|
-
|
|
86
|
-
expect(result.id).toBe('123');
|
|
87
|
-
expect(result.name).toBe('test');
|
|
88
|
-
expect(result.status).toBe('ACTIVE');
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe('toOrm', () => {
|
|
93
|
-
it('should map domain entity to ORM entity', () => {
|
|
94
|
-
// ...
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
});
|
|
16
|
+
# Directorio separado (comun en Java, Python, algunos JS/TS)
|
|
17
|
+
src/servicio.java → test/servicio_test.java
|
|
18
|
+
src/modulo.py → tests/test_modulo.py
|
|
98
19
|
```
|
|
99
20
|
|
|
100
|
-
##
|
|
21
|
+
## Principios universales
|
|
101
22
|
|
|
102
|
-
|
|
103
|
-
const mockGrpcClient = {
|
|
104
|
-
getService: jest.fn().mockReturnValue({
|
|
105
|
-
metodoGrpc: jest.fn().mockReturnValue(
|
|
106
|
-
of({ data: 'response' }) // Observable
|
|
107
|
-
),
|
|
108
|
-
}),
|
|
109
|
-
};
|
|
23
|
+
### Arrange-Act-Assert (AAA)
|
|
110
24
|
```
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
```typescript
|
|
115
|
-
const mockQueue = {
|
|
116
|
-
add: jest.fn().mockResolvedValue({ id: 'job-1' }),
|
|
117
|
-
getJob: jest.fn(),
|
|
118
|
-
process: jest.fn(),
|
|
119
|
-
};
|
|
25
|
+
// Arrange — preparar datos y mocks
|
|
26
|
+
// Act — ejecutar la operacion
|
|
27
|
+
// Assert — verificar resultado
|
|
120
28
|
```
|
|
121
29
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
const mockLogger = {
|
|
126
|
-
log: jest.fn(),
|
|
127
|
-
error: jest.fn(),
|
|
128
|
-
warn: jest.fn(),
|
|
129
|
-
debug: jest.fn(),
|
|
130
|
-
};
|
|
30
|
+
### Naming conventions
|
|
131
31
|
```
|
|
32
|
+
# Formato recomendado (adaptar al idioma/framework):
|
|
33
|
+
should [verbo] [resultado] when [condicion]
|
|
132
34
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
it('should return product request when valid id is provided', () => {});
|
|
138
|
-
it('should throw NotFoundException when product does not exist', () => {});
|
|
139
|
-
it('should update status to SOLD when payment is confirmed', () => {});
|
|
140
|
-
it('should create refund when sale fails after successful topup', () => {});
|
|
35
|
+
# Ejemplos:
|
|
36
|
+
"should return product when valid id is provided"
|
|
37
|
+
"should throw error when input is empty"
|
|
38
|
+
"should update status when payment is confirmed"
|
|
141
39
|
```
|
|
142
40
|
|
|
143
41
|
## Anti-patrones a evitar
|
|
144
42
|
|
|
145
|
-
- NO testear propiedades
|
|
43
|
+
- NO testear propiedades/metodos privados directamente
|
|
146
44
|
- NO testear implementacion interna (orden de llamadas) a menos que sea critico
|
|
147
|
-
- NO crear tests sin assertions
|
|
45
|
+
- NO crear tests sin assertions
|
|
148
46
|
- NO crear tests que dependan del orden de ejecucion
|
|
149
|
-
- NO mockear todo — solo los limites del sistema
|
|
47
|
+
- NO mockear todo — solo los limites del sistema (DB, APIs externas, filesystem)
|
|
150
48
|
- NO crear tests fragiles que se rompen con cambios cosmeticos
|
|
49
|
+
- NO duplicar la logica del codigo en el test (el test debe verificar comportamiento, no reimplementar)
|
|
50
|
+
|
|
51
|
+
## Mocks y Stubs
|
|
52
|
+
|
|
53
|
+
Mockear solo lo que esta fuera del control del test:
|
|
54
|
+
- Llamadas a bases de datos
|
|
55
|
+
- APIs externas / servicios HTTP
|
|
56
|
+
- Sistema de archivos (si aplica)
|
|
57
|
+
- Colas de mensajes
|
|
58
|
+
- Loggers (cuando interfieren con output)
|
|
59
|
+
|
|
60
|
+
No mockear:
|
|
61
|
+
- Funciones puras del propio modulo
|
|
62
|
+
- DTOs, mappers, utilidades sin side effects
|
|
63
|
+
- Constantes o configuracion estatica
|