Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Claude Code ed esecuzione dei test

Successi e (parziali) fallimenti di Claude Code nel corso del test di un'API REST, senza scrivere una sola riga di codice
Successi e (parziali) fallimenti di Claude Code nel corso del test di un'API REST, senza scrivere una sola riga di codice
Link copiato negli appunti

Proseguendo nel nostro discorso dedicato al testing delle API REST con l'AI, per l'endpoint POST /orders, Claude Code ha prodotto un file di test che copriva il ciclo completo.

I test generati da Claude Code per l'endpoint degli ordini

Nello specifico, riporto i casi più significativi perché mostrano il livello di dettaglio che è stato raggiunto:

// __tests__/integration/orders.test.ts
import { app, request } from './setup';
import { generateAuthToken } from '../helpers/auth';
describe('POST /orders', () => {
  it('crea un ordine con dati validi e restituisce 201', async () => {
    const token = generateAuthToken({ userId: 'user-123', role: 'customer' });
    const response = await request(app)
      .post('/orders')
      .set('Authorization', `Bearer ${token}`)
      .send({
        customerId: 'c1a2b3c4-d5e6-7890-abcd-ef1234567890',
        items: [{ productId: 'prod-001', quantity: 2 }]
      });
    expect(response.status).toBe(201);
    expect(response.body).toMatchObject({
      id: expect.any(String),
      customerId: 'c1a2b3c4-d5e6-7890-abcd-ef1234567890',
      status: 'pending',
      items: expect.arrayContaining([
        expect.objectContaining({ productId: 'prod-001', quantity: 2 })
      ])
    });
  });
  it('restituisce 400 se items è un array vuoto', async () => {
    const token = generateAuthToken({ userId: 'user-123', role: 'customer' });
    const response = await request(app)
      .post('/orders')
      .set('Authorization', `Bearer ${token}`)
      .send({
        customerId: 'c1a2b3c4-d5e6-7890-abcd-ef1234567890',
        items: []
      });
    expect(response.status).toBe(400);
  });
  it('restituisce 401 senza Authorization header', async () => {
    const response = await request(app)
      .post('/orders')
      .send({
        customerId: 'c1a2b3c4-d5e6-7890-abcd-ef1234567890',
        items: [{ productId: 'prod-001', quantity: 1 }]
      });
    expect(response.status).toBe(401);
  });
  it('restituisce 422 se productId non esiste nel catalogo', async () => {
    const token = generateAuthToken({ userId: 'user-123', role: 'customer' });
    const response = await request(app)
      .post('/orders')
      .set('Authorization', `Bearer ${token}`)
      .send({
        customerId: 'c1a2b3c4-d5e6-7890-abcd-ef1234567890',
        items: [{ productId: 'prod-non-esistente', quantity: 1 }]
      });
    expect(response.status).toBe(422);
  });
});

La qualità di questi test è genuinamente buona. Le asserzioni sono specifiche senza essere fragili, con toMatchObject invece di toEqual per il response body, expect.any(String) per l'ID generato dal server. I casi di errore coprono le distinzioni semantiche della specifica. Il test del 422 per il productId inesistente dimostra che l'agente ha compreso la differenza tra validazione sintattica e validazione semantica, che nella specifica era implicita nella distinzione tra i codici 400 e 422.

L'esecuzione: dove l'agente ha trovato i primi muri

Generare i test era la parte più prevedibile del progetto. L'esecuzione ha rivelato i problemi reali, ed è qui che l'esperimento è diventato più interessante da analizzare.

Al primo jest --testPathPattern=integration, tre test su ventisette sono falliti. Claude Code ha letto l'output di Jest, ha interpretato gli errori, e ha proposto le correzioni, tutto senza intervento manuale. Ma il modo in cui ha gestito i tre fallimenti era qualitativamente diverso da caso a caso, e quella differenza dice qualcosa di importante sull'autonomia effettiva dell'agente.

Il caso risolto correttamente: il formato UUID

Il primo fallimento era un 400 restituito invece del 201 atteso nel test happy path. Claude Code ha letto lo stack trace, ha notato che il middleware di validazione stava rifiutando il customerId, ha aperto il codice del validatore, e ha scoperto che l'implementazione usava una regex per UUID versione 4 mentre il valore nel test era un UUID versione 1. Ha corretto il valore nel file di fixture e il test è passato al secondo tentativo.

Questo è il tipo di diagnosi che un agente gestisce nel modo migliore: c'è un errore esplicito, c'è una causa tracciabile nell'output e la correzione è localizzata e non ambigua.

Il caso risolto parzialmente da Claude Code: l'helper di autenticazione

Il secondo fallimento era più interessante. Claude Code aveva generato un helper generateAuthToken che usava jsonwebtoken per creare un token firmato, ma aveva ipotizzato che il segreto JWT fosse nella variabile d'ambiente JWT_SECRET.

In realtà il progetto usava una chiave asimmetrica RS256 con un certificato caricato dal filesystem. L'agente ha identificato correttamente il problema leggendo il codice del middleware di autenticazione, ha trovato il percorso del certificato di test, e ha riscritto l'helper correttamente. Ma nel farlo ha anche modificato il file .env.test per aggiungere il percorso del certificato come variabile d'ambiente.

Una modifica non richiesta, fuori dal perimetro del task dichiarato, e potenzialmente problematica su un ambiente CI che gestisce le variabili d'ambiente diversamente.

È un esempio del pattern che vale la pena tenere a mente: l'agente risolve il problema immediato ma produce effetti collaterali su file che non erano nel perimetro della modifica. Non è un comportamento malevolo — è semplicemente il risultato di un ragionamento locale che non ha una visione completa delle conseguenze sistemiche di ogni modifica.

Se vuoi aggiornamenti su Claude Code ed esecuzione dei test inserisci la tua email nel box qui sotto:

Compilando il presente form acconsento a ricevere le informazioni relative ai servizi di cui alla presente pagina ai sensi dell'informativa sulla privacy.

Ti consigliamo anche