Il TDD funziona davvero per progetti complessi?

52

Sto facendo questa domanda riguardo ai problemi che ho riscontrato durante i progetti TDD. Ho notato le seguenti sfide durante la creazione dei test unitari.

  • Generazione e gestione di dati fittizi

È difficile e irrealistico mantenere grandi dati falsi. È ancora più difficile quando la struttura del database subisce modifiche.

  • Test della GUI

Anche con MVVM e la capacità di testare la GUI, ci vuole un sacco di codice per riprodurre lo scenario della GUI.

  • Verifica l'attività

Ho esperienza che TDD funziona bene se lo si limita a una semplice logica aziendale. Tuttavia, la complessa logica aziendale è difficile da testare poiché il numero di combinazioni di test (spazio di test) è molto ampio.

  • Contraddizione nei requisiti

In realtà è difficile catturare tutti i requisiti in fase di analisi e progettazione. Molte volte i requisiti di una nota portano alla contraddizione perché il progetto è complesso. La contraddizione si trova in ritardo nella fase di implementazione. TDD richiede che i requisiti siano corretti al 100%. In tali casi ci si potrebbe aspettare che i requisiti conflittuali vengano catturati durante la creazione di test. Ma il problema è che questo non è il caso in scenari complessi.

Ho letto questa domanda: Perché TDD funziona?

TDD funziona davvero per progetti aziendali complessi o è praticamente limitato al tipo di progetto?

    
posta Amir Rezaei 31.01.2011 - 12:26
fonte

14 risposte

52

It’s hard and unrealistic to maintain large mock data. It’s is even harder when database structure undergoes changes.

False.

Il test delle unità non richiede dati di simulazione "grandi". Richiede abbastanza dati falsi per testare gli scenari e nient'altro.

Inoltre, i programmatori veramente pigri chiedono agli esperti in materia di creare semplici fogli di calcolo dei vari casi di test. Solo un semplice foglio di calcolo.

Quindi il programmatore pigro scrive un semplice script per trasformare le righe del foglio di calcolo in casi di test unitari. È piuttosto semplice, davvero.

Quando il prodotto si evolve, i fogli di calcolo dei casi di test vengono aggiornati e vengono generati nuovi test unitari. Fallo tutto il tempo. Funziona davvero.

Even with MVVM and ability to test GUI, it’s takes a lot of code to reproduce the GUI scenario.

Che cosa? "Riprodurre"?

Il punto di TDD è progettare cose per Testability (Test Drive Development). Se la GUI è così complessa, deve essere ridisegnata per essere più semplice e più controllabile. Più semplice significa anche più veloce, più manutenibile e più flessibile. Ma per lo più semplice significa più testabile.

I have experience that TDD works well if you limit it to simple business logic. However complex business logic is hard to test since the number of combination of test (test space) is very large.

Può essere vero.

Tuttavia, chiedere agli esperti in materia di fornire i casi di test di base in una forma semplice (come un foglio di calcolo) aiuta davvero.

I fogli di calcolo possono diventare piuttosto grandi. Ma va bene, dal momento che ho usato un semplice script Python per trasformare i fogli di calcolo in casi di test.

E. Ho dovuto scrivere manualmente alcuni casi di test perché i fogli di lavoro erano incompleti.

Tuttavia. Quando gli utenti hanno segnalato "bug", ho semplicemente chiesto quale test case nel foglio di calcolo era sbagliato.

In quel momento, gli esperti in materia avrebbero corretto il foglio di calcolo o avrebbero aggiunto degli esempi per spiegare cosa avrebbe dovuto accadere. Le segnalazioni di bug possono - in molti casi - essere chiaramente definite come un problema di test case. In effetti, dalla mia esperienza, definire l'errore come un caso di test rotto rende la discussione molto, molto più semplice.

Invece di ascoltare gli esperti cercano di spiegare un processo aziendale super-complesso, gli esperti devono produrre esempi concreti del processo.

TDD requires that requirements are 100% correct. In such cases one could expect that conflicting requirements would be captured during creating of tests. But the problem is that this isn’t the case in complex scenario.

Non usare TDD impone assolutamente che i requisiti siano corretti al 100%. Alcuni sostengono che TDD può tollerare requisiti incompleti e mutevoli, in cui un approccio non TDD non può funzionare con requisiti incompleti.

Se non usi TDD, la contraddizione si trova in ritardo nella fase di implementazione.

Se usi TDD, la contraddizione viene trovata precedente quando il codice supera alcuni test e fallisce altri test. In effetti, TDD ti dà una prova di una contraddizione in precedenza nel processo, molto prima dell'implementazione (e degli argomenti durante il test di accettazione degli utenti).

Hai un codice che supera alcuni test e fallisce altri. Osservi solo quei test e trovi la contraddizione. Funziona davvero, molto bene nella pratica perché ora gli utenti devono discutere della contraddizione e produrre esempi concreti e coerenti del comportamento desiderato.

    
risposta data 31.01.2011 - 13:57
fonte
27

La mia prima esposizione a TDD stava lavorando ai componenti middleware per un telefono cellulare basato su Linux. Questo alla fine si è trasformato in milioni di righe di codice sorgente, che a loro volta hanno chiamato circa 9 gigabyte di codice sorgente per vari componenti open-source.

Tutti gli autori di componenti dovevano proporre sia un'API che un set di test unitari e li hanno sottoposti a revisione del progetto da parte di un comitato di pari livello. Nessuno si aspettava la perfezione nei test, ma tutte le funzioni esposte pubblicamente dovevano avere almeno un test, e una volta che un componente veniva sottoposto al controllo del codice sorgente, tutti i test unitari dovevano sempre passare (anche se lo facevano perché il componente stava segnalando falsamente ha funzionato bene).

Senza dubbio dovuto almeno in parte al TDD e un'insistenza che tutti i test unitari passino sempre, la versione 1.0 è arrivata in anticipo, sotto budget e con una stabilità sorprendente.

Dopo la versione 1.0, poiché le aziende volevano poter cambiare rapidamente l'ambito a causa delle richieste dei clienti, ci hanno detto di smettere di fare TDD e rimosso il requisito che i test delle unità passassero. Era stupefacente quanto rapidamente la qualità andasse giù nel bagno, e poi il programma lo seguiva.

    
risposta data 01.02.2011 - 06:20
fonte
18

Direi che più il progetto è complesso, maggiore sarà il beneficio derivante da TDD. I principali vantaggi sono gli effetti collaterali di come TDD ti costringerà a scrivere il codice in blocchi molto più piccoli e molto più indipendenti. I vantaggi principali sono:

a) Hai ottenuto una validazione molto più precoce del tuo design perché il tuo ciclo di feedback è molto più stretto a causa dei test sin da subito.

b) Puoi cambiare bit e frammenti e vedere come reagisce il sistema perché hai costruito una trapunta di copertura del test per tutto il tempo.

c) Il codice finito sarà molto meglio di conseguenza.

    
risposta data 31.01.2011 - 15:33
fonte
10

TDD funziona davvero per progetti complessi?
Sì. Non tutti i progetti, quindi, mi hanno detto che funzionano bene con TDD, ma la maggior parte delle applicazioni aziendali va bene, e scommetto che quelli che non funzionano bene quando sono scritti in puro TDD possono essere scritti in modo ATDD senza grossi problemi.

Generazione e mantenimento dei dati di simulazione
Mantienilo piccolo e solo quello di cui hai bisogno e questo non è il problema spaventoso che sembra. Non fraintendermi, è un dolore. Ma vale la pena.

Test della GUI
Prova MVVM e assicurati che possa essere testato senza la vista. Non ho trovato questo più difficile di testare un altro po 'di logica aziendale. Testare la vista nel codice non lo faccio, tutto quello che stai testando, a questo punto, è la logica vincolante, che si spera verrà catturata rapidamente quando esegui un rapido test manuale.

Verifica dell'attività
Non trovato per essere un problema. Un sacco di piccoli test. Come ho detto sopra, alcuni casi (i risolutori di puzzle di Sudoku sembrano essere popolari) sono apparentemente difficili da fare per il TDD.

TDD richiede che i requisiti siano corretti al 100% No non lo fa. Da dove hai preso questa idea? Tutte le pratiche Agile accettano che i requisiti cambino. Devi sapere cosa stai facendo prima di farlo, ma non è lo stesso che richiede che i requisiti siano al 100%. Il TDD è una pratica comune in Scrum, dove i requisiti (User Story) sono, per definizione, non completi al 100%.

    
risposta data 31.01.2011 - 13:54
fonte
9

Innanzitutto, ritengo che il tuo problema riguardi in generale il test unitario rispetto al TDD, dal momento che non vedo nulla di specifico del TDD (test-first + ciclo red-green-refactor) in quello che dici.

It’s hard and unrealistic to maintain large mock data.

Che cosa intendi per dati falsi? Si suppone che un mocking contenga a malapena qualsiasi dato, cioè non ci sono campi diversi da uno o due necessari nel test, e nessuna dipendenza diversa dal sistema sotto test. L'impostazione di un'aspettativa fittizia o di un valore di ritorno può essere eseguita in un'unica riga, quindi niente di terribile.

It’s is even harder when database structure undergoes changes.

Se si intende che il database subisce modifiche senza che siano state apportate le opportune modifiche al modello dell'oggetto, i test di unità sono qui proprio per avvisare di ciò. Altrimenti, le modifiche al modello devono essere riflesse nei test di unità, ovviamente, ma con le indicazioni di compilazione è una cosa facile da fare.

Even with MVVM and ability to test GUI, it takes a lot of code to reproduce the GUI scenario.

Hai ragione, l'unità di test della GUI (View) non è facile, e molte persone stanno facendo bene senza di essa (inoltre, testare la GUI non fa parte di TDD). Al contrario, un'unità di test del controller / Presenter / ViewModel / qualunque livello intermedio è altamente raccomandato, in realtà è uno dei motivi principali per cui sono modelli come MVC o MVVM.

I have experience that TDD works well if you limit it to simple business logic. However complex business logic is hard to test since the number of combinations of tests (test space) is very large.

Se la logica aziendale è complessa, è normale che i test delle unità siano difficili da progettare. Spetta a te renderli il più possibile atomici, testando ciascuno una sola responsabilità dell'oggetto in prova. I test unitari sono tanto più necessari in un ambiente complesso perché forniscono una rete di sicurezza che garantisce che non si infrangono le regole oi requisiti aziendali quando si apportano modifiche al codice.

TDD requires that requirements are 100% correct.

Assolutamente no. Il software di successo richiede che i requisiti siano corretti al 100%;) I test unitari riflettono solo quale sia la tua visione dei requisiti al momento; se la visione è difettosa, anche il tuo codice e il tuo software saranno, test unitari o meno ... Ed è qui che brillano i test unitari: con titoli di test abbastanza espliciti, le decisioni di progettazione e l'interpretazione dei requisiti diventano trasparenti, il che rende più facile puntare il dito su ciò che deve essere cambiato la prossima volta che il cliente dice "questa regola aziendale non è così Mi piacerebbe ".

    
risposta data 31.01.2011 - 18:54
fonte
6

Devo ridere quando sento qualcuno lamentarsi del fatto che la ragione per cui non possono usare TDD per testare la loro applicazione è perché la loro applicazione è così complicata. Qual è l'alternativa? Le scimmie di prova martellano su acri di tastiere? Lascia che gli utenti siano i tester? Cos'altro? Certo, è difficile e complesso. Pensi che Intel non testerà le loro chip fino a quando non spediranno? In che modo "head-in-the-sand" è così?

    
risposta data 01.02.2011 - 05:30
fonte
4
> Does TDD really work for complex projects?

Dalla mia esperienza: Sì per Unittests (test di moduli / funzionalità in isolamento) perché questi per lo più non ho i problemi che hai menzionato: (Gui, Mvvm, Business-Modell). Non ne ho mai avuto più 3 mock / stub per riempire completamente un unestest (ma forse il tuo dominio richiede più).

Tuttavia, io sono non shure se TDD potrebbe risolvere i problemi che hai menzionato sull'integrazione o test end-to-end con test in stile BDD.

Ma almeno alcuni problemi possono essere ridotti .

> However complex business logic is hard to test since the number 
> of combinations of tests (test space) is very large.

Questo è vero se si desidera eseguire una copertura completa al livello del test di integrazione o test end-to-end. Potrebbe essere più semplice eseguire la copertura completa a livello di unittore.

Esempio: controllo delle autorizzazioni utente complesse

Test della funzione IsAllowedToEditCusterData() su un livello di test di integrazione         richiederebbe di chiedere diversi         oggetti per informazioni su utente, dominio, cliente, ambiente .....

Deridere queste parti         è abbastanza difficile. Questo è particolarmente vero se IsAllowedToEditCusterData() deve sapere         questi diversi oggetti.

Su un Unittest-Level avresti la funzione IsAllowedToEditCusterData() che prende ad esempio 20 parametri che contengono tutto ciò che la funzione deve sapere. Da IsAllowedToEditCusterData() non ha bisogno di sapere quali campi a user , a domain , a customer , .... questo è facile da testare.

Quando ho dovuto implementare IsAllowedToEditCusterData() ho avuto due sovraccarichi di esso:

Un sovraccarico che non fa altro che ottenere quei 20 parametri e poi chiamare il sovraccarico con i 20 parametri che prende le decisioni.

(il mio IsAllowedToEditCusterData() aveva solo 5 parametri e avevo bisogno di 32 diverse combinazioni per testarlo completamente)

Esempio

// method used by businesslogic
// difficuilt to test because you have to construct
// many dependant objects for the test
public boolean IsAllowedToEditCusterData() {
    Employee employee = getCurrentEmployee();
    Department employeeDepartment = employee.getDepartment();
    Customer customer = getCustomer();
    Shop shop = customer.getShop();

    // many more objects where the permittions depend on

    return IsAllowedToEditCusterData(
            employee.getAge(),
            employeeDepartment.getName(),
            shop.getName(),
            ...
        );
}

// method used by junittests
// much more easy to test because only primitives
// and no internal state is needed
public static boolean IsAllowedToEditCusterData(
        int employeeAge,
        String employeeDepartmentName,
        String shopName,
        ... ) 
{
    boolean isAllowed; 
    // logic goes here

    return isAllowed;
}
    
risposta data 31.01.2011 - 18:54
fonte
3

Ho trovato che TDD (e test unitari in generale) sono praticamente impossibili per un motivo correlato: algoritmi complessi, nuovi e / o fuzzy. Il problema che mi imbatto maggiormente nei prototipi di ricerca che scrivo è che non ho idea di quale sia la risposta giusta se non eseguendo il mio codice. È troppo complicato per capire a mano ragionevolmente qualcosa se non casi ridicolmente banali. Questo è particolarmente vero se l'algoritmo coinvolge euristica, approssimazioni o non determinismo. Cerco ancora di testare la funzionalità di livello inferiore da cui questo codice dipende e usa assiduamente come controlli di integrità. Il mio metodo di test di ultima istanza è quello di scrivere due diverse implementazioni, idealmente in due lingue diverse utilizzando due diversi set di librerie e confrontare i risultati.

    
risposta data 14.04.2011 - 03:53
fonte
2

La triste risposta è che niente funziona davvero per progetti di grandi dimensioni!

TDD è buono come qualsiasi altro e migliore della maggior parte, ma TDD da solo non garantisce il successo in un grande progetto. Aumenterà comunque le tue possibilità di successo. Soprattutto se usato in combinazione con altre discipline di gestione del progetto (verifica dei requisiti, casi d'uso, matrice di tracciabilità dei requisiti, codice walkthroughs ecc. Ecc.).

    
risposta data 25.05.2013 - 06:42
fonte
1

Ricorda che i test unitari sono specifiche applicate . Questo è particolarmente utile in progetti complessi. Se il tuo vecchio code-base non ha test per eseguirne il backup, nessuno oserà cambiare nulla perché avrà paura di rompere qualsiasi cosa.

"Wtf. Perché questo ramo di codice è ancora lì? Non lo so, forse qualcuno ne ha bisogno, meglio lasciarlo lì che sconvolgere chiunque ..." Nel tempo i progetti complessi diventano una spazzatura.

Con i test, chiunque può dire con sicurezza "Ho apportato cambiamenti drastici, ma tutti i test sono ancora in corso." Per definizione, non ha rotto nulla. Questo porta a progetti più agili che possono evolversi. Forse uno dei motivi per cui abbiamo ancora bisogno di persone per mantenere COBOL è perché il test non è stato popolare da allora: P

    
risposta data 31.01.2011 - 18:24
fonte
1

Ho visto un grande progetto complesso fallire completamente quando TDD è stato utilizzato esclusivamente, cioè senza almeno la configurazione in un debugger / IDE. I dati e / o i test falsi si sono rivelati insufficienti. I dati reali dei client Beta erano sensibili e non potevano essere copiati o registrati. Quindi, il team di sviluppo non ha mai potuto correggere i bug fatali che si sono manifestati quando puntati su dati reali e l'intero progetto è stato scartato, tutti hanno sparato, il tutto.

Il modo per risolvere questo problema sarebbe stato quello di accenderlo in un debugger sul sito del client, vivere contro i dati reali, scorrere il codice, con punti di interruzione, variabili di orologio, memoria degli orologi, ecc. Tuttavia, questa squadra, che pensava che il loro codice fosse adatto per adornare le più belle torri d'avorio, per un periodo di quasi un anno non aveva mai attivato l'app. Mi ha sconvolto.

Quindi, come tutto, l'equilibrio è la chiave. TDD può essere buono ma non fare affidamento esclusivamente su di esso.

    
risposta data 31.01.2013 - 14:49
fonte
0

Penso di sì, vedi Test Driven Development funziona davvero

In 2008, Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat, and Laurie Williams wrote a paper called “Realizing quality improvement through test driven development: results and experiences of four industrial teams“ (PDF link). The abstract:

Test-driven development (TDD) is a software development practice that has been used sporadically for decades. With this practice, a software engineer cycles minute-by-minute between writing failing unit tests and writing implementation code to pass those tests. Test-driven development has recently re-emerged as a critical enabling practice of agile software development methodologies. However, little empirical evidence supports or refutes the utility of this practice in an industrial context. Case studies were conducted with three development teams at Microsoft and one at IBM that have adopted TDD. The results of the case studies indicate that the pre-release defect density of the four products decreased between 40% and 90% relative to similar projects that did not use the TDD practice. Subjectively, the teams experienced a 15–35% increase in initial development time after adopting TDD.

     

Nel 2012, le pratiche di sviluppo di Ruby on Rails assumono TDD. Personalmente mi affido a strumenti come rspec per scrivere test e mock, factory_girl per la creazione di oggetti, capybara per l'automazione del browser, simplecov per la copertura del codice e protezione per l'automazione di questi test.

     

Come risultato dell'utilizzo di questa metodologia e di questi strumenti, tendo a concordare soggettivamente con Nagappan et al ...

    
risposta data 26.01.2012 - 19:28
fonte
0

Se la combinazione di budget, requisiti e abilità di squadra si trovano nel quadrante dello spazio-progetto "abbandona la speranza a tutti voi che entrate qui", quindi per definizione è assolutamente probabile che il progetto fallirà.

Forse i requisiti sono complessi e volatili, l'infrastruttura instabile, il team junior e con un alto turnover, o l'architetto è un idiota.

In un progetto TDD, il sintomo di questo errore imminente è che i test non possono essere scritti in programma; ci provi, solo per scoprire che "ci vorrà questo a lungo, e abbiamo questo ".

Altri approcci mostreranno sintomi diversi quando falliscono; più comunemente la consegna di un sistema che non funziona. Politica e contratti determineranno se sia preferibile.

    
risposta data 06.03.2014 - 23:11
fonte
-1

TDD potrebbe sembrare un dolore immediato, ma a lungo termine sarebbe il tuo migliore amico, fidati di me TDD renderà davvero l'applicazione mantenibile e sicura a lungo termine.

    
risposta data 01.02.2011 - 19:42
fonte

Leggi altre domande sui tag