Ni zero tests ni cobertura total, el testing just pel teu projecte
13/02/2026
Hi ha equips que no testegen res i resen a cada desplegament. I hi ha equips que busquen el 100% de cobertura i no lliuren a temps. Tots dos tenen un problema de testing. La pregunta no és si cal testejar, sinó quant, on i per què.
El teu equip té un projecte de producció. Cada cop que toqueu alguna cosa, algú pregunta: "hem provat això?". La resposta sol ser un silenci incòmode o un “crec que sí”. I quan les coses es trenquen —que es trenquen—, la conversa sempre és la mateixa: “necessitem més tests”.
Però “més tests” no és una estratègia de testing. És una reacció emocional a un bug en producció. I sol portar un de dos extrems: o l'equip segueix sense testejar (perquè ningú no té temps), o algú decideix que s'ha de cobrir tot i l'equip passa més temps escrivint tests que codi de producte.
La pregunta que hauries d'estar fent-te no és “quants tests tenim?”. És "estem testejant el que importa?". I la resposta a aquesta pregunta canvia segons el teu projecte, el teu equip i la fase en què ets.
El mite de la cobertura al 100%
Hi ha una idea persistent a la indústria: que un bon projecte té una cobertura de tests propera al 100%. És una mètrica fàcil de mesurar, fàcil de posar a un dashboard i fàcil de convertir en objectiu. I és una de les pitjors mètriques per decidir si el teu test és suficient.
Un projecte pot tenir un 95% de cobertura i trencar-se a producció cada setmana. Com? Perquè la cobertura mesura que una línia de codi s'executa durant un test, no que el test verifica alguna cosa útil. Un test que crida a una funció però no comprova el resultat suma cobertura sense aportar confiança.
Martin Fowler ho explica bé: la cobertura et diu quin codi no està testejat, però no et diu si el codi testejat està ben testejat. És un indicador de buits, no de qualitat. Si el vostre equip s'obsessiona amb el número, acabarà escrivint tests per cobrir línies trivials (getters, setters, constructors) mentre ignora la lògica de negoci complexa que és on viuen els bugs de debò.
La cobertura és útil com a brúixola. Si en tens un 15%, probablement hi ha zones crítiques sense protegir. Si en tens un 85%, perseguir el 100% probablement no val l'esforç. Però fer-la servir com a objectiu és com mesurar la salut d'una empresa només pel nombre d'empleats.
La piràmide de testing (i per què importa l'ordre)
Si hi ha un model que ha sobreviscut al pas del temps, és la piràmide de testing. La idea és simple: molts tests unitaris a la base, menys tests d'integració al medi, i pocs tests end-to-end al cim.
Tests unitaris verifiquen peces petites de lògica de manera aïllada. En un backend Django, un test unitari comprova que una funció calcula bé un preu amb descompte o un serializer valida correctament les dades d'entrada. Són ràpids d'escriure, ràpids d'executar i barats de mantenir. Un projecte Django ben testejat pot executar centenars de tests unitaris amb pytest en segons.
Tests dintegració verifiquen que diverses peces funcionen juntes. Que la vista de Django torna el JSON correcte quan rebeu una petició, que l'ORM genera la query esperada, que l'API respon amb el codi d'estat adequat. Són més lents que els unitaris i requereixen més infraestructura (base de dades de test, per exemple), però detecten problemes que els unitaris no hi veuen.
Tests end-to-end simulen el flux complet de lusuari. En una app Flutter, això significa que el test obre l'app, navega per pantalles, omple un formulari i verifica que el resultat és correcte. Són els més lents, els més fràgils i els més cars de mantenir. Però quan passen, donen una confiança que cap altre tipus de test no pot donar.
La piràmide funciona perquè et diu on invertir. Si el teu equip té recursos limitats —i tot equip en té—, inverteix primer a la base. Molts tests unitaris bons són més valuosos que uns quants tests end-to-end fràgils.
Quant de testing necessites segons la fase del teu projecte
Aquí és on la majoria de guies fallen: tracten el testing com una cosa estàtica. "El teu projecte necessita X% de cobertura." Però la quantitat de testing que té sentit depèn d'on ets.
Fase de validació (MVP, prototip). Si estàs validant una idea amb un producte mínim viable, testejar-ho tot és un error de prioritat. El producte pot pivotar la setmana que ve, i aquests tests que vas escriure per a un flux que ja no existeix són temps perdut. En aquesta fase, els tests imprescindibles són pocs: que l'app arrenca, que el flux principal funciona i que els pagaments (si n'hi ha) no fallen. Tota la resta pot esperar.
Fase de creixement. El teu producte té usuaris, genera valor i l'equip afegeix funcionalitats. Aquí és on el testing comença a pagar dividends reals. Cada nova feature hauria de portar tests de la lògica de negoci que introdueix. Els bugs que apareixen en producció haurien de generar un test de regressió abans d'arreglar-se (primer escrius el test que reprodueix el bug, després ho corregeixes). L'objectiu no és cobrir tot: és protegir el que ja funciona mentre construeixes el que és nou.
Fase de maduresa. El vostre producte és estable, té una base d'usuaris consolidada i els canvis tendeixen a ser incrementals. Aquí la inversió en testing se centra en els fluxos crítics de negoci: el checkout, el registre, la integració amb serveis externs. Un test end-to-end que verifica el flux de compra complet val més que cinquanta tests unitaris de funcions auxiliars.
Fase d'escala. Múltiples equips treballen sobre la mateixa base de codi. Els tests passen de ser una ferramenta de qualitat a ser una ferramenta de coordinació. Si l'equip A canvia una API interna i els tests de l'equip B fallen, el pipeline de CI/CD el detecta abans que arribi a producció. En aquesta fase, la inversió en tests d'integració i contractes és on hi ha el retorn més gran.
La regla del 80/20 aplicada al testing
Si haguessis de triar què testejar amb recursos limitats, el principi de Pareto és sorprenentment útil. El 80% dels bugs en producció ve de 20% del codi. I aquest 20% sol ser predictible.
Lògica de negoci amb condicionals complexos. Si una funció té tres ifs niats amb diferents camins possibles, és candidata a test. Si és un getter que torna un camp, probablement no.
Integracions amb serveis externs. Passarel·les de pagament, APIs de tercers, serveis de correu electrònic. Qualsevol punt on el teu codi parla amb un altre sistema és una font probable de fallades. Els tests aquí no necessiten trucar al servei real (usa mocks), però sí verificar que el teu codi maneja bé les respostes esperades i els errors.
Transformacions de dades. Funcions que reben dades en un format i les tornen en un altre són candidates naturals a tests unitaris. Un serializer de Django que transforma un objecte en JSON per a l'API, un parser que processa un CSV d'importació, una funció que calcula un preu amb descomptes acumulats.
Fluxos crítics dusuari. Allò que l'usuari fa més (login, compra, registre, cerca) mereix almenys un test d'integració que verifiqui el flux complet. No cal simular el navegador: a Django, el test client us permet fer peticions HTTP al servidor de test i verificar respostes sense sortir de pytest.
El que probablement no necessiteu testejar: codi de presentació pur (estils, layouts), configuracions trivials, migracions de base de dades i codi generat automàticament. No pas perquè no puguin fallar, sinó perquè el cost de mantenir aquests tests supera el benefici que aporten.
Tests que resten en comptes de sumar
No tots els tests fan el teu projecte més fiable. Alguns ho fan més lent, més fràgil i més difícil de canviar. Reconéixer-los és tan important com escriure els bons.
Tests fràgils. Un test que falla cada cop que canvieu un detall d'implementació (l'ordre d'un JSON, el text exacte d'un missatge, la posició d'un element a la pantalla) genera soroll. L'equip comença a ignorar les fallades del pipeline perquè “segur que és aquest test que sempre falla”. Quan un test fràgil falla de debò, ningú no li fa cas.
Tests lents sense justificació. Un test unitari que triga més dun segon té un problema. Un suite de tests que triga 20 minuts a passar fa que l'equip eviti executar-los a local i depengui exclusivament del CI. Això alenteix el cicle de feedback i frena el desenvolupament. En un projecte Django, si els tests triguen més d'un parell de minuts, revisa si estàs usant la base de dades on podries fer servir mocks.
Tests duplicats. Tres tests que verifiquen el mateix de tres maneres diferents no et donen tres vegades més confiança. Et donen un test de confiança i dos de manteniment. Si canvieu la lògica, heu d'actualitzar tres tests en comptes d'un.
Tests que testegen el framework. Verificar que Django torna un 404 quan la URL no existeix és testejar Django, no el teu codi. Verifica la teva lògica, no la del framework. L'equip de Django ja té els seus propis tests per fer-ho.
El senyal que la teva suite de tests té problemes no és que els tests fallin. És que l'equip no hi confia. Si algú diu “això segur que és un fals positiu”, tens un problema més greu que un bug en producció.
El testing com a inversió, no com a obligació
Hi ha una manera útil de pensar en el testing: com a pòlissa d'assegurança. Pagues un cost ara (temps de desenvolupament) per evitar un cost més gran després (bugs en producció, rollbacks, usuaris enfadats, pèrdua d'ingressos).
Com tota assegurança, té sentit proporcionar la inversió al risc. No assegures la teva bicicleta amb la mateixa pòlissa que casa teva. No testegeu un formulari de contacte amb la mateixa exhaustivitat que un sistema de pagaments.
Segons l' informe DORA State of DevOps , els equips amb pràctiques de testing sòlides despleguen amb més freqüència i tenen taxes de fallada més baixes. No perquè tinguin més tests, sinó perquè els tests que tenen són als llocs correctes. El testing ben dirigit permet moure's més ràpid, no més lent.
Si el teu equip sent que els tests l'alenteixen, el problema no és el testing. És que esteu testejant les coses equivocades, al lloc equivocat o amb eines que no encaixen.
Per on començar si avui no tens gairebé res
Si el teu projecte té pocs o cap test, la temptació és “fer un esprint de testing” per posar-se al dia. No ho facis. Això genera tests mediocres escrits amb pressa que ningú no mantindrà.
En lloc d'això adopta una regla simple: cada bug que arriba a producció genera un test abans d'arreglar-se. Primer reprodueixes la fallada amb un test automatitzat. Després ho corregeixes. Així, la teva suite de tests creix de forma orgànica, enfocada exactament als problemes reals del teu projecte.
Comença pels fluxos que et fan més por tocar. Aquestes parts del codi on tot l'equip diu "cura amb això". És aquí on un parell de tests d'integració canvien la vida. En un projecte de Django amb Wagtail, pot ser el flux de publicació de contingut. En una app Flutter, el flux de login o el de compra inapp.
Integra els tests a la teva pipeline de CI des del primer dia. Un test que només s'executa en local no existeix a la pràctica. Quan els tests s'executen a cada push, l'equip els pren de debò.
I el més important: no mesures el teu progrés en percentatge de cobertura. Mesura'l en confiança. El teu equip desplega un divendres a la tarda sense nervis? Si la resposta és sí, probablement el teu test és suficient. Si la resposta és no, ja saps on començar.