Parliamone
// sviluppo_software.testing_quality_assurance

Testing, Quality Assurance & Technical Debt Reduction

Il codice che nessuno osa toccare non è un asset: è una bomba a orologeria. Inizia a disinnescarla adesso, un test alla volta.

Software Architecture Cloud & DevOps

Il problema in breve

Molte PMI italiane hanno software applicativo sviluppato tra il 2005 e il 2015 che oggi fa girare il business, ma su cui nessuno interviene volentieri. Non perché non ci siano cose da migliorare, anzi, ma perché ogni modifica rischia di rompere qualcosa d’altro in modo imprevedibile. Il test manuale prima di ogni rilascio richiede giorni, il deployment viene fatto di notte o nel weekend per limitare l’impatto di un eventuale problema, e l’ultimo rilascio importante risale a mesi fa. Nel frattempo, i clienti chiedono nuove funzionalità, i competitor le rilasciano, e il team tecnico passa più tempo a gestire i problemi introdotti dalle ultime modifiche che a sviluppare cose nuove. Il debito tecnico non è solo un problema di qualità del codice: è un freno alla velocità di business che si aggrava ogni mese che passa, perché ogni modifica fatta senza test aumenta l’entropia del sistema e riduce ulteriormente la finestra di intervento sicuro.

La sfida

Il debito tecnico nelle applicazioni legacy delle PMI italiane si manifesta in pattern ricorrenti che sono il risultato di anni di sviluppo sotto pressione, senza una strategia di qualità consapevole. La copertura di test è tipicamente nulla o inferiore al 5% delle linee di codice per le applicazioni nate prima del 2015: non perché i team fossero negligenti, ma perché la cultura del testing automatico non era mainstream nelle PMI italiane e gli strumenti erano meno accessibili. La conseguenza è una base di codice in cui le relazioni tra i componenti non sono esplicite (nessuna interfaccia, dipendenze dirette su implementazioni concrete, uso estensivo di variabili globali e stato condiviso) e in cui l’impatto di una modifica è impossibile da prevedere senza eseguire l’intera suite di test manuali.

L’assenza di CI/CD trasforma ogni rilascio in un evento ad alto rischio. Il deployment manuale, copiare file su un server, eseguire script di migrazione database a mano, verificare la correttezza dell’applicazione con test manuali, introduce variabilità e dipendenza dal singolo sviluppatore che conosce la procedura. In assenza di ambienti di staging equivalenti alla produzione, i problemi emergono direttamente in produzione. Il rollback, quando necessario, richiede intervento manuale e causa downtime. Questo quadro porta a frequenze di rilascio molto basse (mensile o trimestrale), che a loro volta aumentano la dimensione dei rilasci (molte modifiche accumulate), che a loro volta aumentano il rischio di ogni singolo rilascio: un circolo vizioso che porta alla paralisi operativa.

Sul piano della misurazione, il debito tecnico nella maggior parte delle PMI italiane non è mai stato quantificato. Non si sa quante righe di codice duplicato esistono (tipicamente il 15-25% della codebase in assenza di refactoring), qual è la complessità ciclomatica media dei metodi critici (spesso superiore a 20-30 nelle funzioni core, contro un target generalmente accettato di ≤10, con 15 come soglia di allerta), qual è il coupling tra i moduli (spesso altissimo, con dipendenze circolari che rendono impossibile testare un componente isolato), né qual è il ratio tra codice di produzione e codice di test (idealmente 1:1 o superiore, nella realtà spesso 100:0). Senza metriche baseline, non è possibile misurare il progresso del refactoring né costruire un business case per giustificare l’investimento nella qualità.

La soluzione

Fase 01

Technical Debt Assessment

Il punto di partenza è un Technical Debt Assessment che produce una fotografia quantitativa della codebase esistente. L’analisi statica con strumenti come SonarQube (per Java, C#, Python, JavaScript) o NDepend (per .NET) misura le metriche chiave: code coverage, duplicazione, complessità ciclomatica, coupling afferente ed efferente, violazioni di stile e di sicurezza. Il risultato è una Technical Debt Ratio, il rapporto tra il costo stimato di remediation delle violazioni e il costo stimato per riscrivere l’intera applicazione da zero (entrambi calcolati dallo strumento in base a parametri configurabili), e una mappa delle aree critiche ordinate per rischio e per impatto sul business. L’assessment include anche una revisione architetturale manuale: i tool automatici non rilevano l’anti-pattern dell’oggetto God Class con 5.000 righe di codice, né la stored procedure con 800 righe che contiene metà della business logic dell’applicazione.

Fase 02

Test Strategy e Testing Pyramid

La test strategy viene progettata seguendo il modello della Testing Pyramid: la base è costituita dagli unit test (veloci, isolati, che testano singole funzioni o metodi), il livello intermedio dagli integration test (che verificano l’interazione tra componenti: API, database, messaggistica), e la sommità dai test end-to-end (che simulano il comportamento utente su flussi critici). La proporzione indicativa è 70% unit test, 20% integration test, 10% E2E test. Questa proporzione è l’obiettivo a regime, non il punto di partenza per una codebase legacy. Su una codebase con copertura zero, l’ordine di introduzione dei test è necessariamente invertito: si applicano i test di caratterizzazione (Feathers, Working Effectively with Legacy Code) sul confine esterno del sistema, API, CLI o UI, che documentano il comportamento attuale prima di qualsiasi refactoring. Questi test diventano la rete di sicurezza che rileva ogni regressione nel comportamento esterno durante il refactoring interno incrementale. Solo man mano che il refactoring rende il codice testabile a livello di singola unità, la proporzione si avvicina progressivamente alla piramide target.

Fase 03

CI/CD Pipeline Incrementale

La CI/CD pipeline viene costruita in fasi incrementali. La prima fase (pipeline di base) automatizza build, esecuzione dei test esistenti e analisi statica ad ogni commit: anche con zero test, avere una pipeline attiva che misura le metriche e blocca i commit con violazioni critiche è il primo passo. La seconda fase aggiunge il deployment automatico sull’ambiente di staging, con verifica automatica della salute dell’applicazione post-deploy (health check, smoke test). La terza fase introduce il deployment automatico in produzione con feature flag e strategie di rilascio progressive (blue/green deployment o canary release) che permettono di esporre la nuova versione a una percentuale crescente di traffico prima del rilascio completo, con rollback automatico in caso di degradazione delle metriche. L’obiettivo finale è ridurre il lead time dal commit al deploy in produzione da giorni a ore, con fiducia. La strategia di test data management è parte integrante dell’approccio: per i test di integrazione su sistemi con dati sensibili, si definisce un processo di anonimizzazione e subset dei dati di produzione, conforme al GDPR, per popolare gli ambienti di test.

Tecnologie chiave

Automated Testing Frameworks

Ecosistema di strumenti per unit test, integration test e test end-to-end su stack tecnologici diversi, con esecuzione parallela, reporting strutturato e integrazione nativa nelle pipeline CI/CD.

Approfondisci

CI/CD Pipelines

Automazione del ciclo build-test-deploy con GitHub Actions, GitLab CI o Jenkins, per rilasci frequenti, ripetibili e reversibili con qualità verificata ad ogni step.

Approfondisci

Static Code Analysis

Analisi automatica del codice sorgente per rilevare bug, vulnerabilità di sicurezza, codice duplicato e violazioni architetturali senza eseguire l’applicazione.

Approfondisci

Code Quality Metrics

Misurazione continua di coverage, complessità ciclomatica, coupling, duplicazione e technical debt ratio con trend storici per guidare le decisioni di refactoring basandosi su dati.

Approfondisci

Refactoring Patterns

Catalogo di trasformazioni strutturali del codice (Extract Method, Replace Conditional with Polymorphism, Introduce Seam, Introduce Parameter Object) per ridurre il debito tecnico in modo incrementale e sicuro.

Approfondisci

Risultati e benefici

Aumento della code coverage (linea) da 0-5% a 40-60% entro 6-9 mesi su progetti con strategia di test attiva, con priorità sui moduli ad alto rischio e alta frequenza di modifica

Riduzione del 50-70% del tempo dedicato al test manuale pre-rilascio: la pipeline automatica esegue in 10-20 minuti quello che richiedeva 2-3 giorni di test manuale

Aumento della frequenza di rilascio da mensile/trimestrale a settimanale o più frequente, con dimensione dei singoli rilasci proporzionalmente ridotta e rischio corrispondentemente inferiore

Riduzione del 40-60% dei bug in produzione segnalati dagli utenti entro 12 mesi, concentrata in particolare sui moduli con maggiore copertura di test

Riduzione del 30-45% della complessità ciclomatica media sui moduli refactorizzati, con corrispondente riduzione del costo di manutenzione e del tempo di onboarding per nuovi sviluppatori

Lead time dal commit al deploy su staging ridotto da giorni a 2-4 ore; il deploy in produzione, con approvazione manuale o automatica secondo la strategia scelta, avviene entro la stessa giornata su pipeline mature

Technical Debt Ratio misurato e in riduzione: la quantificazione del debito tecnico rende finalmente possibile costruire un business case per gli interventi di qualità verso il management

Use case

Software gestionale: applicazione .NET con zero test e deploy manuale trimestrale

Una software house italiana (fatturato €5M, 28 dipendenti) sviluppa e mantiene un gestionale verticale per il settore logistico, installato presso 40 clienti. L’applicazione, 180.000 righe di C# .NET Framework 4.6, nata nel 2011, ha zero test automatici. Ogni rilascio richiede 3 giorni di test manuale da parte di 2 sviluppatori senior, un weekend di deploy manuale presso i clienti, e genera in media 8-12 bug in produzione nei 15 giorni successivi. Il SonarQube assessment rivela 2.400 code smell, 180 bug rilevati staticamente, 34 vulnerabilità di sicurezza e una complessità ciclomatica media di 18 sui metodi del modulo core. La strategia adotta i test di caratterizzazione sull’API del gestionale: 340 test di integrazione che documentano il comportamento attuale vengono scritti in 6 settimane, senza modificare il codice applicativo. La pipeline GitHub Actions esegue build e test in 18 minuti. In 9 mesi, la coverage sale al 48%, la frequenza di rilascio passa da trimestrale a mensile, i bug post-rilascio scendono da 10 a 2 per release. Il tempo di test manuale pre-rilascio scende da 3 giorni a 4 ore di verifica focalizzata sulle aree non coperte.

Testing QA gestionale .NET zero test deploy manuale trimestrale

Manifatturiero: MES custom con logica critica in stored procedure

Un’azienda metalmeccanica (fatturato €55M, 150 dipendenti) gestisce la produzione con un MES sviluppato internamente nel 2009 in ASP.NET WebForms con logica di calcolo dei costi e della pianificazione distribuita tra 120 stored procedure SQL Server. Il sistema non ha test, il deploy richiede un fermo produzione di 4 ore il sabato notte, e l’ultimo intervento significativo risale a 18 mesi fa a causa della paura di regressioni. L’analisi individua le 15 stored procedure critiche (pianificazione, calcolo costi, gestione distinte base) che gestiscono il 70% del valore business. Per queste, vengono scritti test di integrazione che eseguono la stored procedure su un database di test popolato con dati reali anonimizzati e verificano gli output. Il refactoring inizia dai moduli più isolati: estrazione della business logic di pianificazione dalla stored procedure a un servizio C# testabile, con la stored procedure che diventa un thin wrapper. In 12 mesi, la coverage sui moduli critici raggiunge il 55%, i fermi produzione per deploy applicativi si eliminano (deploy automatico su staging, verifica automatica, promozione in produzione con blue/green deployment, i rilasci che richiedono modifiche ai layer di integrazione con i sistemi di campo mantengono una finestra coordinata con la produzione), e il team torna ad accelerare lo sviluppo di nuove funzionalità.

Testing QA MES manifatturiero stored procedure legacy refactoring

E-commerce: piattaforma di vendita online con test manuali e deploy ad alto rischio

Una PMI della moda (fatturato €18M, 45 dipendenti) gestisce un e-commerce su Magento 2 personalizzato con 80 moduli custom sviluppati nel corso di 5 anni. Il sito gestisce 150.000 transazioni all’anno. Non ci sono test automatici sui moduli custom, il deploy richiede una finestra notturna di 2 ore con potenziale impatto sulle vendite, e ogni modifica ai moduli di checkout, la parte più sensibile, viene rimandata per settimane per paura di rompere il flusso di pagamento. Il testing pyramid parte dagli unit test sui servizi PHP dei moduli custom (PHPUnit), con integration test sui flussi critici (carrello, checkout, pagamento, conferma ordine) tramite API testing con Postman/Newman, e E2E test su Playwright sui 5 percorsi utente più critici (acquisto singolo prodotto, checkout con coupon, acquisto con indirizzo di spedizione alternativo, login e recupero ordine, checkout mobile). La pipeline GitLab CI esegue i test in 22 minuti su ogni PR. Il deploy usa una strategia blue/green su AWS con health check automatico: in caso di errore sul nuovo ambiente, il traffico viene rediretto all’ambiente precedente in meno di 60 secondi. Il downtime da deploy passa da 120 minuti (con relativa perdita di vendite stimata in €800-1.200 per evento) a zero per i deploy che non richiedono migrazioni bloccanti del database, per le migrazioni schema, la finestra si riduce ai soli secondi necessari per l’operazione DDL.

Testing QA e-commerce Magento 2 moduli custom pipeline CI/CD blue/green

Vuoi sapere quante ore stai perdendo ogni mese per il debito tecnico?

Richiedi un Technical Debt Assessment: analizziamo la tua codebase con strumenti di analisi statica e revisione architetturale per consegnarti metriche concrete, una mappa delle aree critiche e un piano di testing e refactoring con stima del ROI.

Tweaks

Light mode
Atmospheric (glass)
Client logos
Terminal hero