Questo è un problema difficile. Molti dei "metodi" in un'applicazione Web accettano una richiesta HTTP come input e producono output HTML con l'effetto collaterale dell'uso del database e dell'aggiornamento di qualche tipo di stato della sessione da qualche parte. Questo è uno scenario peggiore per i test unitari.
L'HTML è difficile perché vuoi davvero isolare i dati che provengono in modo specifico da un determinato metodo, al contrario della piastra della caldaia e dell'impalcatura del layout, che è comune a ogni pagina. Quella lastra della caldaia potrebbe cambiare in una nuova combinazione di colori o qualcos'altro indipendentemente dalla logica della tua applicazione che potrebbe potenzialmente interrompere tutti i tuoi test. Il database è particolarmente difficile perché spesso è necessario impostare una buona quantità di dati prima di poter testare in modo significativo qualsiasi cosa eccetto la schermata di accesso.
Penso che l'approccio migliore sia utilizzare molti tipi diversi di test e dividi e vinci.
- Per le piccole applicazioni, un piano di test di regressione manuale è un buon punto di partenza.
- Quando crei componenti veramente indipendenti, scrivi JUnit per testarli.
- Se si utilizzano servlet, è necessario fornire una richiesta HTTP falsa o parametri falsi e ottenere direttamente l'output dal servlet. L'XHTML ben formattato verrà analizzato abbastanza facilmente con espressioni regolari. È possibile utilizzare tecniche di test unitario sui dati precaricati nel database.
- Configura i test di integrazione con gli strumenti di test dell'unità (qualcuno mi licenzierà per questo). Fai un test che costruisca una serie di dati di test nel database usando le schermate del sistema (come nel punto precedente) più o meno come farebbe un utente del sistema. Tutti i test dipenderanno dalla suite di test di base che imposta i dati per gli altri test. Quando il tuo test di regressione diventa troppo grande, questa è un'ottima alternativa al test manuale.
- Potresti riuscire a utilizzare un database in memoria con uno strumento come Hibernate invece di impostare un clone completo del database di produzione e mascherare i dati.
- Utilizza qualcosa come selenio per eseguire il test da un browser.
- Imposta il tuo servlet principale fino alla pagina quando viene generata un'eccezione e rimuovi tutte le istruzioni catch dal codice (eccetto quelle che effettivamente fanno qualcosa di significativo con l'eccezione, come recuperare da esso). Questo non è un test, ma incoraggia test molto buoni.
- Spesso scopro che il test più utile si verifica quando il tester spiega come funziona il sistema per un principiante assoluto. Troviamo i bug più significativi quando si creano piccoli segmenti di aiuto video per nuove funzionalità. Ma posso fare dei buoni test quando spiego e dimostro i dettagli di come il sistema funziona per un amico immaginario interessato.
Penso che se avessi usato un approccio a più livelli per creare la tua applicazione con molti livelli indipendenti, avresti avuto un tempo molto più facile da testare. Potrebbe essere necessario un team di programmatori di grandi dimensioni per fare tutto con specialisti per il database, il livello di servizio "back-end" sulla parte superiore del database, il livello della business logic e il livello di vista. In tale scenario, puoi utilizzare le tradizionali tecniche di test unitario con la logica di business e in parte con gli altri livelli, ma la vista sarà sempre un orso.
Modifica: ci stavo pensando. Finché posso ricordare che MVC è stato applicato alle applicazioni web, c'è stato un dibattito su cosa significhi. Per la cronaca, penso che Ruby / Rails abbia capito bene - quel modello significa davvero Data Model. Mi piace questa interpretazione perché è più compatibile con la creazione di un livello di servizio nell'applicazione. Di recente ho letto la piattaforma di Steve Yegge Rant che mi ha davvero aperto gli occhi. Rendi il servizio il tuo modello di dati e mangia il tuo cibo per cani. In questo modo qualcun altro può trasformare la tua creazione in qualcosa che non hai mai immaginato. La ragione per cui l'ho portato qui (oltre al fatto che non riesco a smettere di pensarci) è che avere divisioni nel codice rende più facile testare.
Guarda, non sono nell'accampamento di livello-make-everything-better. Devo produrre e produrre molte funzioni senza molto aiuto per vivere. Sto solo dicendo che se il tuo progetto è abbastanza maturo da non cambiare più il database, valuta la possibilità di trasformare il tuo incubo ORM in un livello di servizio per le ragioni di Steve Yegge, ma anche perché l'interfaccia aggiuntiva dovrebbe rendere molto più facile e più efficace.