Obre la darrera pull request en què l'assistent va escriure els tests. Busca al codi que proven una comparació qualsevol —un >, un >=, un ==— i canvia-la per la contrària. No toquis els tests. Executa la suite.
Si continua en verd, ja saps què mesura la vostra cobertura.
L'experiment costa deu minuts, no necessita instal·lar res i té una propietat que gairebé cap dada de qualitat no té: no admet discussió sobre la metodologia, perquè ho ha vist tothom a la mateixa pantalla. I és la versió artesanal d'una tècnica amb quaranta anys de literatura al darrere, el mutation testing, que és de què va aquesta peça.
El punt no és que els tests generats siguin dolents. És que s'estan llegint com si responguessin a una pregunta que no responen. Ja hem parlat de què passa amb la revisió quan l'autor deixa d'existir com a interlocutor i de les dependències que entren disfressades d'una línia. Els tests són la tercera cosa que arriba a la mateixa pull request i la que porta millor disfressa, perquè arriba amb un número que puja.
Quatre condicions, i la cobertura només en comprova la primera
Perquè una errada en una línia de codi acabi apareixent com un test en vermell s'han de complir quatre coses seguides. La formulació és clàssica en la literatura de testing i Parsai i Demeyer la resumeixen així en el seu estudi industrial: la línia defectuosa s'ha d'executar; ha d'alterar l'estat del programa; aquesta alteració s'ha de propagar fins a la sortida; i el test ha d'observar aquesta sortida i decidir que està malament.
Quatre baules. La cobertura mesura la primera. Només la primera.
| Condició | Què ha de passar | On falla un test generat a partir del codi |
|---|---|---|
| Execució | La línia defectuosa s'executa durant el test | Gairebé mai. És justament el que el model fa bé: arribar a totes les branques. Aquí és on puja el número. |
| Infecció | L'execució deixa l'estat del programa en un valor diferent del correcte | De vegades. Depèn de si les dades d'entrada escollides toquen el límit on el defecte canvia alguna cosa, i els valors generats tendeixen al cas central. |
| Propagació | Aquest estat incorrecte arriba fins a una sortida observable | De vegades. Els tests molt unitaris amb dobles per tot arreu tallen la propagació abans que en surti res. |
| Revelació | El test observa la sortida i decideix que està malament | Aquí és on es trenca. L'asserció es va escriure mirant la sortida que el codi produeix avui. Si aquesta sortida és incorrecta, l'asserció la dona per bona. |
Les quatre condicions, en la formulació que recullen Parsai i Demeyer. La tercera columna és lectura pròpia sobre el comportament típic d'un test derivat del codi.
Dit així s'entén per què el número pot pujar sense que la xarxa millori. Un test que executa una línia i no comprova res rellevant sobre el que aquella línia va produir compta igual per a la cobertura que un que sí que ho comprova. L'eina de cobertura no ho distingeix: no està dissenyada per distingir-ho. La documentació de PIT ho diu sense embuts — la cobertura de línies «mesura només quin codi executen els teus tests. No comprova que els teus tests siguin capaços de detectar errades al codi executat».
L'oracle hereta allò d'on neix
La part d'un test que decideix si una cosa està bé o malament té nom propi a la literatura: l'oracle. És l'asserció, i és l'única part que fa feina de verificació; tota la resta és muntatge. La pregunta útil, doncs, no és qui va escriure el test, sinó d'on va sortir el seu oracle.
Aquí hi ha la troballa que ordena tota la resta. Bodicoat, Jahangirova i Terragni obren el seu estudi de gener del 2026 constatant que les tècniques existents de generació de tests «generen principalment oracles de regressió que es prediquen sobre el comportament implementat de la classe sota prova» i que, per tant, «no aborden el problema de l'oracle: la dificultat de distingir el comportament correcte de l'incorrecte».
Un oracle de regressió és una afirmació sobre l'estat actual. Diu: això fa avui això. És enormement útil —és el que t'avisa que un refactor ha canviat alguna cosa sense voler— però és una foto, no un judici. Si el codi tenia una errada el dia que es va generar el test, el test la fotografia juntament amb tota la resta i la protegeix a partir d'aleshores. La suite deixa de ser una xarxa i passa a ser un mirall: confirma que el codi continua sent el que era.
Hi ha una frustració molt repetida que encaixa aquí i que gairebé sempre s'explica en un altre context. A l'enquesta de Stack Overflow del 2025, amb més de 49.000 respostes, la queixa número u sobre les eines d'IA —el 66%, molt per davant de la segona— són «les solucions d'IA que estan gairebé bé, però no del tot». En un fragment de lògica, «gairebé bé» es veu: falla, o fa alguna cosa estranya, i algú s'ho mira. En una asserció, «gairebé bé» és verd. Un oracle equivocat no es comporta com un error: es comporta com una confirmació.
Meta va publicar l'embut sencer, i és la dada més honesta que hi ha
Convé mirar el millor cas documentat abans d'opinar sobre el cas mitjà. Meta va descriure el 2024 la seva eina TestGen-LLM, que no genera tests des de zero sinó que millora tests existents escrits per humans i —això és el rellevant— només accepta els que superen una cadena de filtres que garanteixen una millora mesurable sobre la suite original. La motivació declarada d'aquests filtres és eliminar els problemes derivats de l'al·lucinació del model.
A l'avaluació sobre els productes Reels i Stories d'Instagram, l'embut va quedar així: el 75% dels casos generats compilava, el 57% passava de manera fiable i el 25% augmentava la cobertura. Als test-a-thons d'Instagram i Facebook van millorar l'11,5% de totes les classes on es va aplicar, i els enginyers de Meta van acceptar el 73% de les recomanacions per a producció.
Un de cada quatre. Amb un equip que sap què fa, un filtre automàtic al davant i l'escala de Meta al darrere. Aquest número és el terra realista de la conversa, i és una bona notícia: significa que amb filtre això funciona, i el 73% d'acceptació humana ho confirma.
Però val la pena llegir els tres filtres pel que pregunten. Compila? Passa de manera estable? Augmenta la cobertura? Són tres preguntes raonables i cap de les tres no és detectaria aquest test una errada?. El filtre més estricte publicat per la indústria s'atura, per disseny, a la primera de les quatre baules. No és un descuit de Meta —la cobertura és mesurable, automàtica i barata, i és infinitament millor que acceptar el que digui el model— però marca on és avui el sostre de l'enfocament.
Per què la cobertura no havia de servir per a això, i se sap des del 2014
El treball de referència és de Laura Inozemtseva i Reid Holmes, presentat a la International Conference on Software Engineering del 2014. Van generar 31.000 suites de test sobre cinc sistemes Java reals —Apache POI, Closure Compiler, HSQLDB, JFreeChart i Joda Time, de fins a 724.089 línies de codi—, en van mesurar la cobertura de sentències, de decisions i de condició modificada, i en van avaluar l'eficàcia real injectant errades amb mutation testing.
Tres conclusions, i les tres continuen incòmodes dotze anys després. La correlació entre cobertura i eficàcia és de baixa a moderada quan es controla el nombre de casos de la suite. La força d'aquesta relació varia entre sistemes, de manera que no és segur assumir-la en el teu. I les formes més sofisticades de cobertura no aporten més informació que la simple, tot i costar més de mesurar i de satisfer.
La frase amb què tanquen és la que hauria d'estar enganxada a qualsevol tauler de qualitat: la cobertura, tot i ser útil per identificar parts poc testades d'un programa, no s'hauria de fer servir com a objectiu de qualitat, perquè no és un bon indicador de l'eficàcia d'una suite. Els sistemes que van estudiar anaven del 27% de cobertura de sentències a HSQLDB al 91% a Joda Time, i el número tot sol no ordenava les suites per capacitat de detecció.
Res d'això no és nou ni té a veure amb la IA. El que ha canviat és el volum: quan escriure tests costava temps humà, la cobertura creixia a poc a poc i més o menys en proporció al pensament invertit. Aquest acoblament accidental entre el número i l'esforç era el que feia que la mètrica semblés que funcionava. Generar tests en massa ho trenca, i deixa la mètrica a la vista tal com és.
La mesura que sí que es mou
El mutation testing respon exactament la pregunta que la cobertura no respon. El procediment, en la formulació de PIT: se sembren errades automàticament al codi i s'executen els tests; si els tests fallen, el mutant està mort; si passen, el mutant sobreviu. La proporció de mutants morts és el mutation score, i és una mesura de la capacitat de detecció, no de la superfície recorreguda.
La documentació de Stryker ho il·lustra amb el cas que més s'assembla al del principi d'aquest article: una comprovació d'edat. Si en canviar la condició cap test no es posa vermell, probablement falti un test que comprovi explícitament el límit. El mutant supervivent no és una mètrica abstracta: és un test que falta, amb nom i cognoms, assenyalat amb el dit.
La propietat important és que aquest número no es pot inflar amb tests que executen codi sense comprovar res. Un test sense assercions útils puja la cobertura i no mata ni un sol mutant. És, per construcció, immune al mode d'errada que porta la generació massiva.
| Cobertura | Mutation score | |
|---|---|---|
| Què pregunta | Quin codi executen els meus tests? | Detectarien els meus tests un canvi en aquest codi? |
| Baules que cobreix | La primera | Les quatre, per construcció |
| Es pot inflar amb | Tests sense assercions útils | Res equivalent |
| Cost de mesurar | Segons; ja és al vostre CI | Alt: una passada completa és feina de cap de setmana |
| Soroll propi | Baix | Mutants equivalents: del 0,4% al 35% segons el projecte |
| Per a què fer-la servir | Mapa de buits | Nota de l'examen, sobre el codi que importa |
El rang de mutants equivalents prové dels cinc sistemes mesurats per Inozemtseva i Holmes: 0,4% a HSQLDB, 35% a Apache POI.
El que costa de debò, dit sense adorns
El mutation testing no s'ha adoptat massivament per una raó sòlida: és car. Parsai i Demeyer es van proposar mesurar exactament això sobre quatre sistemes open source i un d'industrial, i van investigar les tres objeccions habituals: que és difícil d'integrar al sistema de construcció, que la cobertura de branques ja és «prou bona» i que la sobrecàrrega de temps és inassumible.
Els números del cas industrial: 12.825 mutants per a 38.000 línies de codi. Van definir com a acceptable una feina que càpiga entre el divendres a les 18h i el dilluns a les 8h —62 hores— perquè els resultats estiguin llestos abans de la reunió de sprint. Quan la passada completa no hi cap, apliquen mostreig de mutants reduint-los al 34,7%, i citen treball previ segons el qual mostres de fins al 50% continuen donant resultats fiables. La seva conclusió és que la cobertura de mutació revela debilitats addicionals que la cobertura de branques no veu, amb una sobrecàrrega assumible.
Hi ha dos avisos honestos per treure'n. El primer és que això no és gratis i no va a cada commit: la manera de ficar-ho en un cicle curt és mutar només les classes que toca el diff. El segon el diuen els mateixos autors i va contra la intuïció còmoda: no van trobar prou evidència per confirmar que la cobertura de branques sigui un bon estimador de la cobertura de mutació en sistemes complicats. És a dir, tampoc no val fer servir la cobertura com a aproximació barata al número que sí que importa.
I el soroll propi de la tècnica és real: els mutants equivalents —canvis sintàctics que no alteren el comportament i que per tant cap test no pot detectar— anaven del 0,4% al 35% segons el projecte en l'estudi d'Inozemtseva i Holmes. Distingir-los exigeix inspecció manual. Qui vengui el mutation score com una mètrica neta i automàtica està venent una altra cosa.
La palanca no és el model: és l'entrada
Si l'oracle hereta allò d'on neix, hi ha una intervenció evident abans de tocar res més: canviar de què neix. En comptes de donar-li al model la implementació i demanar-li tests, donar-li el que el codi havia de fer.
Ma i Eisty ho van provar el juliol del 2026 de la manera més neta possible: generar oracles a partir únicament de requisits en llenguatge natural, sense accés al codi font ni a exemples d'entrada, i enfrontar-los a deu bugs reals del projecte Lang de Defects4J amb cinc models diferents. El resultat que importa és de direcció: els oracles generats s'alineen més amb el requisit que amb el comportament implementat del sistema.
És un estudi petit —deu bugs, cinc models, un sol projecte— i s'ha de tractar com un senyal, no com una demostració tancada. Però apunta al mateix que la pràctica: el model no té manera de saber que una sortida està malament si l'única cosa que li has ensenyat és aquesta sortida. Dona-li el criteri i el podrà contrastar; dona-li el resultat i només el podrà copiar.
Això és exactament l'argument del Spec-Driven Development aplicat al costat que gairebé ningú no mira. Quan existeix una especificació escrita, versionada i llegible per l'agent, no només serveix per generar el codi: és l'únic material del qual pot sortir un test que jutgi en comptes de descriure. El mateix que l'enginyeria de context resol per a la generació, ho resol per a la verificació — i pel mateix motiu, perquè el problema mai no va ser l'habilitat del model sinó el que tenia al davant.
És la mateixa lògica que ja apliquem en avaluar sistemes d'IA: un golden set val perquè les respostes correctes les va fixar algú amb criteri abans de veure el que el sistema produïa, i per això pot dir si una cosa funciona millor en lloc de només si va canviar. Un test és un golden set d'una funció. Si el generes mirant la sortida, has construït el conjunt d'avaluació a partir de les respostes de l'examinand.
L'ordre en què això s'arregla
Tres decisions, i l'ordre importa més que cap d'elles per separat.
Primer, mesurar una vegada. Una classe, l'experiment del principi, deu minuts. No per tenir una dada representativa, sinó per convertir una discussió d'opinions en una observació compartida. Mentre la conversa sigui «jo crec que els nostres tests són fluixos», no es mou res; així que és «vaig canviar aquest signe i la suite va passar», es mou sola.
Segon, separar les dues feines. La suite generada es queda on és i fa el que sap fer: detectar canvis no intencionats, que per refactoritzar amb IA és justament el que cal. A sobre d'això, un conjunt petit de tests escrits a partir del criteri —els límits, les regles de negoci, el que l'especificació diu que ha de passar— que és el que jutja. No competeixen: un és el mirall i l'altre és la xarxa, i calen tots dos.
Tercer, canviar l'objectiu. Si al tauler hi ha un llindar de cobertura, treure'l del codi on viu la lògica de negoci i substituir-lo per mutation score sobre el diff. La cobertura es queda com el que Inozemtseva i Holmes van dir que era: un mapa per trobar el que ningú no toca. Un llindar de cobertura sobre una suite generada és l'única combinació que garanteix el pitjor resultat possible — el número puja per construcció i no informa de res.
Res d'això no exigeix una eina nova la primera setmana. Exigeix deixar de llegir un número com si respongués a una pregunta que mai no va respondre, i això ja canvia què es demana en la següent conversa sobre qualitat i què es posa al tauler de mètriques de l'equip. Un assistent que escriu tests és una bona notícia: multiplica la feina de bastida, que era l'avorrida. Només cal deixar de demanar-li que a més sigui el jutge, perquè per a això necessita una cosa que només teniu vosaltres — saber què se li va demanar al codi abans que existís.
La qualitat del codi a l'era de l'AI coding s'ha discutit sobretot mirant el codi. Val la pena mirar també el que el vigila: si la suite va créixer al mateix ritme que el codi i cap de les dues coses no la va escriure algú que sabés què havia de passar, el senyal verd de cada matí fa un temps que no significa el que us penseu que significa.
Preguntes freqüents
Aleshores la cobertura no serveix per a res?
Serveix per al que sempre ha servit: trobar el codi que cap test no toca. Això és informació real i barata d'obtenir. El que no fa és dir-te si els tests que sí que toquen el codi hi detectarien una errada, perquè només mesura la primera de les quatre condicions que s'han de complir perquè una errada es reveli. Inozemtseva i Holmes ho van deixar escrit el 2014 després de generar 31.000 suites sobre cinc sistemes Java de fins a 724.089 línies: la correlació entre cobertura i eficàcia és de baixa a moderada quan es controla el nombre de casos, i la conclusió que en treuen és que la cobertura és útil per identificar parts poc testades però no s'hauria de fer servir com a objectiu de qualitat. La diferència pràctica: fes-la servir com a mapa de buits, no com a nota de l'examen.
El mutation testing no és massa lent per a la integració contínua?
Per passar-lo sencer a cada commit, sí. Parsai i Demeyer ho van mesurar sobre un sistema industrial real: 12.825 mutants per a 38.000 línies de codi, amb un pressupost de temps definit com el forat entre el divendres a les 18h i el dilluns a les 8h. És una feina de cap de setmana, no de pull request. La manera de ficar-ho en un cicle curt és no passar-lo sencer: mutar només les classes que toca el diff, i fer servir mostreig de mutants quan ni així hi cap —els mateixos autors redueixen la mostra al 34,7% conservant la informació, i citen treballs on mostres del 50% continuen donant resultats fiables. La versió de deu minuts és fer-ho a mà sobre una classe, que és com convé començar abans de muntar res.
Si el model escriu el test a partir de l'especificació, no acaba igual d'esbiaixat?
Esbiaixat cap a una altra cosa, i aquí hi ha tota la diferència. Un test derivat del codi només pot afirmar el que el codi fa; si el codi està malament, el test consagra l'error. Un test derivat de l'especificació afirma el que es va demanar, i quan tots dos discrepen apareix l'errada. Ma i Eisty ho van mesurar sobre deu bugs reals de Defects4J generant oracles únicament des de requisits en llenguatge natural, sense codi a la vista: els oracles s'alineen més amb el requisit que amb el comportament implementat. És un estudi petit —deu bugs, cinc models— i convé tractar-lo com a direcció, no com a prova tancada. Però la direcció és la que importa: l'oracle hereta allò d'on neix.
Val la pena que la IA escrigui tests, doncs?
Sí, amb un filtre al davant i sense esperar que el filtre sigui la cobertura. La dada honesta la va publicar Meta amb TestGen-LLM: sobre Reels i Stories d'Instagram, el 75% dels casos generats compilava, el 57% passava de manera fiable i el 25% augmentava la cobertura. Un de cada quatre arribava al final d'un embut dissenyat per gent que sap què fa, i tot i així els tres filtres pregunten si el test compila, si és estable i si executa codi nou — cap no pregunta si detectaria una errada. Amb aquest matís posat, el resultat de camp és bo: van millorar l'11,5% de les classes on es va aplicar i els enginyers de Meta van acceptar el 73% de les recomanacions per a producció.
Què faig amb la suite generada que ja tenim?
No la llencis: mesura-la abans de decidir. La suite generada gairebé sempre aporta alguna cosa real —cobreix camins que ningú no havia tocat i documenta el comportament actual, que per refactoritzar val— i el seu problema no és que sigui falsa, sinó que s'està llegint com si fos una altra cosa. L'ordre que funciona és mesurar el mutation score de dues o tres classes amb lògica de negoci de debò, veure quins mutants sobreviuen, i escriure a mà només els tests que maten aquests supervivents. Acostumen a ser pocs i acostumen a ser els de les condicions límit. El que no s'ha de fer és fixar un objectiu de cobertura per a la suite generada: puja el número sense moure la capacitat de detecció, que és exactament l'errada que es volia corregir.
Per on començo aquesta setmana sense muntar cap programa?
Per l'experiment de deu minuts sobre una sola classe. S'escull la classe amb més lògica de negoci del darrer trimestre, es canvia una comparació al codi —un signe, una condició límit— sense tocar els tests, i s'executa la suite. Si continua verda, ja tens la conversa: no cal cap eina ni cap pressupost per tenir-la, i el resultat no admet discussió metodològica perquè ho ha vist tothom a la mateixa pantalla. A partir d'aquí, la decisió de si val la pena instal·lar PIT o Stryker deixa de ser teòrica. L'error és començar comprant l'eina: la dada que mou un equip és el mutant que va sobreviure al seu propi codi.
Fonts citades
- Inozemtseva, L. i Holmes, R. — Coverage Is Not Strongly Correlated with Test Suite Effectiveness (ICSE 2014, University of Waterloo; 31.000 suites sobre cinc sistemes Java de fins a 724.089 línies; correlació de baixa a moderada controlant la mida; mutants equivalents del 0,4% al 35%)
- Alshahwan, N., Chheda, J., Finegenova, A., Gokkaya, B., Harman, M., Harper, I., Marginean, A., Sengupta, S. i Wang, E. — Automated Unit Test Improvement using Large Language Models at Meta (febrer del 2024; Reels i Stories d'Instagram: 75% compila, 57% passa de manera fiable, 25% augmenta cobertura; 11,5% de classes millorades i 73% de recomanacions acceptades)
- Bodicoat, A., Jahangirova, G. i Terragni, V. — Understanding LLM-Driven Test Oracle Generation (9 de gener del 2026; les tècniques existents generen oracles de regressió sobre el comportament implementat i no aborden el problema de l'oracle)
- Parsai, A. i Demeyer, S. — Comparing Mutation Coverage Against Branch Coverage in an Industrial Setting (Flanders Make i Universiteit Antwerpen; quatre sistemes open source i un d'industrial; 12.825 mutants per a 38.000 línies, finestra de 62 hores, mostreig al 34,7%)
- Ma, T. i Eisty, N. U. — From Business Requirements to Test Assertions: Evaluating LLM-Generated Oracles on Real Bugs (11 de juliol del 2026; deu bugs del projecte Lang de Defects4J i cinc models; els oracles generats des de requisits s'alineen més amb el requisit que amb el comportament implementat)
- PIT — Real world mutation testing (documentació oficial; la cobertura de línies «mesura només quin codi executen els teus tests. No comprova que els teus tests siguin capaços de detectar errades al codi executat»)
- Stryker — Stryker Mutator documentation (StrykerJS, Stryker.NET i Stryker4s; definició de mutant mort i supervivent i l'exemple de la condició límit)
- Stack Overflow — 2025 Developer Survey · AI (més de 49.000 respostes; «les solucions d'IA que estan gairebé bé, però no del tot» és la primera frustració, amb el 66%)

Jordi García és Tech Lead a onext. Treballa a portar la IA a producció governada en equips de desenvolupament i de producte —amb Spec-Driven Development, enginyeria de context i verificació humana a cada pas— i signa els insights tècnics d'onext sobre mètode, qualitat i cost de la IA aplicada.
LinkedIn →