Test Generator Server
Panoramica
Il server test-generator e' uno strumento MCP dedicato alla generazione automatica di test unitari, all'identificazione di edge case e all'analisi della copertura del codice. Rappresenta il punto di partenza per qualsiasi workflow di testing all'interno della MCP Suite, permettendo di passare da codice sorgente a skeleton di test in pochi secondi.
Il server e' stateless: non possiede alcun database ne' store interno. Riceve codice sorgente in input, lo analizza tramite parsing delle firme di funzione e restituisce output strutturato senza mantenere stato tra le invocazioni.
+--------------------------------------------------------------------+
| test-generator server |
| |
| +--------------------+ +------------------+ +-----------------+ |
| | generate-unit-tests| | find-edge-cases | |analyze-coverage | |
| | | | | | | |
| | - parse funzioni | | - null/undefined | | - estrai nomi | |
| | - genera describe | | - empty arrays | | - cerca test | |
| | - genera it blocks | | - division by 0 | | - calcola % | |
| +--------+-----------+ +--------+---------+ +-------+---------+ |
| | | | |
| v v v |
| test:generated (nessun evento) test:coverage-report |
+--------------------------------------------------------------------+
Versione: 0.1.0
Entry point: servers/test-generator/src/index.ts
Dipendenze: @mcp-suite/core, @mcp-suite/event-bus
Tabella dei Tool
Dettaglio dei Tool
generate-unit-tests
Il tool esegue il parsing del codice sorgente cercando due pattern di dichiarazione:
- Funzioni classiche:
export (async) function name(params) - Arrow function:
export const name = (async) (params) =>
Per ogni funzione trovata genera un blocco describe/it con tre test predefiniti:
- Verifica che la funzione esista e sia callable
- Test con input valido (placeholder per asserzioni specifiche)
- Placeholder per edge case (null, undefined, boundary values)
// Esempio di input
const code = `
export function calculateTotal(items: Item[], tax: number): number {
return items.reduce((sum, item) => sum + item.price, 0) * (1 + tax);
}
export const formatCurrency = (amount: number): string => {
return new Intl.NumberFormat('it-IT', { style: 'currency', currency: 'EUR' }).format(amount);
};
`;
// Invocazione
{ tool: "generate-unit-tests", code, framework: "vitest" }
Output generato:
import { describe, it, expect } from 'vitest';
// import { calculateTotal, formatCurrency } from './source';
describe('calculateTotal', () => {
it('should exist and be callable', () => {
expect(calculateTotal).toBeDefined();
expect(typeof calculateTotal).toBe('function');
});
it('should return expected result with valid input', () => {
const result = calculateTotal(/* items */, /* tax */);
expect(result).toBeDefined();
// TODO: Add specific assertions
});
it('should handle edge cases', () => {
// TODO: Test with null/undefined inputs
// TODO: Test with empty values
// TODO: Test with boundary values
});
});
find-edge-cases
Esegue un'analisi statica del codice per identificare potenziali edge case. I controlli eseguiti sono:
L'output include un riepilogo con totale edge case trovati, distribuzione per severita' e dettaglio per ogni caso identificato.
analyze-coverage
Confronta il codice sorgente con il codice dei test per determinare quali funzioni hanno copertura. Il processo e':
- Estrazione nomi funzione dal sorgente (funzioni, arrow function, metodi di classe)
- Ricerca riferimenti nei test: blocchi
describe(), blocchiit()/test(), chiamate dirette alla funzione - Calcolo percentuale:
(funzioni coperte / totale funzioni) * 100
Sorgente Test
+------------------+ +------------------+
| function add() | ------> | describe('add') | COPERTA
| function sub() | ------> | test('sub ...') | COPERTA
| function mul() | --X | | SCOPERTA
| function div() | --X | | SCOPERTA
+------------------+ +------------------+
Coverage: 2/4 = 50%
Architettura
Il server segue un'architettura completamente stateless:
index.ts
|
+-- server.ts (createTestGeneratorServer)
|
+-- tools/generate-unit-tests.ts --> parseFunctions() + generateTestCode()
+-- tools/find-edge-cases.ts --> analyzeEdgeCases()
+-- tools/analyze-coverage.ts --> extractFunctionNames() + findTestReferences()
Non esiste alcun servizio o store. Ogni tool riceve l'input, lo elabora in memoria e restituisce il risultato. Questa scelta progettuale garantisce:
- Nessuna dipendenza da database: zero configurazione necessaria
- Idempotenza: lo stesso input produce sempre lo stesso output
- Scalabilita': nessun stato condiviso, nessun lock
Integrazione Event Bus
Eventi pubblicati
Eventi sottoscritti
Nessuno. Il server e' un puro produttore di eventi.
Interazioni con altri Server
+-------------------+ test:generated +-------------------+
| test-generator | --------------------------> | standup-notes |
| | | (futuro: auto-log)|
| | test:coverage-report +-------------------+
| | --------------------------> | agile-metrics |
+-------------------+ | (futuro: metriche)|
+-------------------+
- agile-metrics: potrebbe in futuro sottoscrivere
test:coverage-reportper includere metriche di copertura nelle analisi di sprint - standup-notes: potrebbe registrare automaticamente i test generati come attivita' completata
Esempi di Utilizzo
Generare test per un modulo
{
"tool": "generate-unit-tests",
"arguments": {
"code": "export function validateEmail(email: string): boolean { ... }",
"language": "typescript",
"framework": "vitest"
}
}
Trovare edge case in una funzione asincrona
{
"tool": "find-edge-cases",
"arguments": {
"code": "export async function fetchUser(id: string) { const res = await fetch(`/api/users/${id}`); return res.json(); }"
}
}
Risultato atteso: edge case per null/undefined, empty-string, async-rejection,
async-timeout.
Analizzare la copertura
{
"tool": "analyze-coverage",
"arguments": {
"sourceCode": "export function add(a, b) { return a + b; }\nexport function sub(a, b) { return a - b; }",
"testCode": "describe('add', () => { it('should add', () => { expect(add(1,2)).toBe(3); }); });"
}
}
Risultato: coveragePercentage: 50, uncoveredFunctions: ["sub"].
Sviluppi Futuri
- Supporto multi-linguaggio: estendere il parsing a Python, Go, Rust
- Generazione test avanzati: integrare i suggerimenti di
find-edge-casesdirettamente nei test generati dagenerate-unit-tests - Integrazione con file system: leggere direttamente file sorgente e test da percorsi su disco, invece di richiedere il codice come stringa
- Template personalizzabili: permettere all'utente di definire template custom per
i blocchi
describe/it - Metriche storiche: persistere i report di copertura per tracciare l'evoluzione nel tempo
- Supporto property-based testing: generare test basati su proprieta' con librerie
come
fast-check