TDD quando i requisiti testabili sono difficili da trovare

2

Sono in una situazione divertente. Abbiamo un modello di sviluppo che funziona per una suite software interna focalizzata sulla capacità di risposta al cliente. Per darti un'idea dell'ambiente, quando usavamo SCRUM, spesso ci impegnavamo intenzionalmente a solo il 50% del nostro carico di lavoro massimo, con una piena aspettativa che il restante 50% sarebbe stato riempito con un lavoro di risposta rapida.

La comunità di sviluppo nel mio ambiente di lavoro nel suo insieme si sta spostando maggiormente verso TDD, quindi ho interesse a capire come potrebbe essere adattato al mio flusso di lavoro. Questo renderà più facile scaldare altri dipendenti , intendo, facilitare il regolare bilanciamento delle risorse.

Tuttavia, mi trovo regolarmente di fronte a situazioni che non hanno requisiti verificabili fino al completamento della maggior parte del lavoro. A causa della natura di risposta rapida del lavoro, trovare la soluzione che è possibile fare è più importante del mantenimento di un'API arbitraria scelta all'inizio dell'attività. Non è utile per i miei clienti se posso creare la loro API dei sogni in un mese, quando devono avere un prodotto funzionante in una settimana. L'API viene davvero finalizzata solo dopo aver compreso come verrà effettivamente eseguito il codice.

In situazioni in cui i requisiti testabili sono difficili da trovare, qualcuno ha avuto successo sfruttando TDD in modo significativo, anche se non è il modo "tradizionale"?

    
posta Cort Ammon 27.04.2018 - 23:02
fonte

8 risposte

5

Se pensi di non poter testare senza requisiti, non comprendi lo scopo dei test.

I'm in a funny situation.

No, non lo sei. Questo è tipico di molti negozi che usano TDD.

To give you a sense of the environment, when we were using SCRUM, we would often intentionally commit to only 50% of our maximum workload, with a full expectation that the remaining 50% would be filled with quick response work.

Sono stato in negozi in cui è stato generoso. È un mondo diverso quando si dispone di sistemi operativi con requisiti di uptime. Scrum e TDD funzionano ancora bene se li fai bene.

However, I find myself regularly faced with situations that do not have testable requirements until the majority of the work is completed. Because of the rapid response nature of the job, finding the solution that can be done is more important than holding to an arbitrary API picked at the start of the task. It's of no use to my customer if I can build their dream API in a month, when they need to have a working product in a week. The API only really gets finalized after we understand how the code is actually going to do the task.

Chi ti ha convinto a mantenere una presa mortale su un'API indipendentemente dalle tue esigenze era tradizionale?

In situations where testable requirements are hard to come by, has anyone had success leveraging TDD in a meaningful way, even if it's not the "traditional" way?

Ho avuto successo con TDD quando l'unico requisito che avevo era "Mi chiedo cosa faccia questa cosa".

I test non sono requisiti. Potresti avere un requisito. Potresti scrivere un test che dimostra che il requisito è soddisfatto. Potresti anche menzionare quel numero di requisito nei commenti del test (o, Dio ci aiuti, nel suo nome). Belle. Ma se questo è tutto quello che stai facendo con i test, non sai cosa stai facendo. I test sono per di più. Molto di più.

Scrivo tonnellate di test. Più di quanto abbia mai fatto il check-in. Perché? Perché i test mi aiutano a leggere il codice. Scrivo test dopo test e guardo la mia comprensione di ciò che posso fare crescere e crescere. Cambio codice e cambio test, rapidamente. Perché sto imparando. I test bloccano ciò che comprendo ora. Mi ricordano cosa stavo facendo quando torno dal bagno.

Quindi sì, a volte scrivo test senza mai guardare o pensare a un documento dei requisiti.

Scarico un sacco di test man mano che la mia comprensione cresce. Trovo modi migliori per esprimere ciò che sto cercando di dire. Proprio come torno a questa risposta e la riscrivo e muovo le cose, faccio lo stesso con il mio codice e le mie prove cercando di trovare il modo migliore per esprimere un'idea. Non perché la CPU ha bisogno di me. Non perché i requisiti lo richiedano. Non perché me lo abbia detto TDD. L'inferno lo stavo facendo prima che il TDD fosse una cosa. Lo faccio per gli umani. Sto cercando il modo migliore per presentare un'idea in modo che l'inesperto principiante che viene dopo di me possa facilmente trovare la linea che devono cambiare perché il mondo è cambiato dopo che me ne sono andato. Lo faccio usando codice e test per raccontare la storia dell'idea bene.

Lo scopo dei test è aiutare le persone a leggere il codice.

Mostrano cosa fa, di cosa ha bisogno, quanto codice devi leggere per capire cosa sta succedendo, ma non ti dicono quello che ti serve. Le tue esigenze cambieranno quando i test non saranno stati toccati. Sta a te decidere se il codice fa quello che ti serve. Non i test.

Quando trovi alcuni requisiti puoi scrivere altri test per loro. Puoi mostrarli al proprietario del tuo prodotto. Puoi persino metterli in un posto speciale in modo che tu possa distinguerli da quelli che scrivi per aiutarti a leggere il codice. Questo è BDD.

Quindi non lamentarti del fatto che non puoi scrivere test perché i tuoi requisiti sono nell'aria. Questo descrive più della metà di tutto ciò che ho fatto usando TDD. Qualsiasi codice che scrivi può essere messo sotto test. Quel test è "Penso che il codice farà questo, vediamo se lo fa". Questo dice ai futuri programmatori (incluso me) cosa stavo pensando. Ma decidere se è necessario non è il lavoro di test. Questo è tuo. Se cambi idea, è il momento di apportare modifiche. Cambia il test e poi cambia il codice. Questo è TDD.

    
risposta data 29.04.2018 - 01:25
fonte
3

I find myself regularly faced with situations that do not have testable requirements until the majority of the work is completed.

Direi che è impossibile finire qualsiasi porzione di un pezzo di lavoro se non si hanno requisiti verificabili per questo, perché c'è una possibilità letteralmente zero percento che sarà ciò che il il cliente vuole Detto questo, i requisiti potrebbero non essere unit testabili, ma questa è una buona cosa - in qualsiasi lavoro di alto livello desideri che i requisiti siano di alto livello in modo da avere la flessibilità durante l'implementazione. Se i requisiti fossero testabili dell'unità, torneresti immediatamente a un flusso di lavoro a cascata, dove tutto è puntato in anticipo e ti ritroverai con qualcosa di difficile da sviluppare e terribile da usare (perché su il front design non tiene conto di eventuali sorprese o apprende di più sul problema mentre ci lavori sopra.

Ora, una volta soddisfatti i requisiti di alto livello, è compito tuo scoprire quale sarà il prossimo passo. Se qualche parte del lavoro è rischiosa, vorrai farlo prima. Calcola un test di alto livello (accettazione o persino livello di viaggio) che, una volta superato, dimostra che il rischio è stato risolto (ad esempio, la tua API restituisce una versione crittografata dell'input in meno di 5 ms). Per implementare questo obiettivo verificabile, scoprirai l'integrazione e quindi i pezzi di lavoro verificabili a livello di unità, scriverli per loro e continuare nella modalità TDD standard. Una volta che tutti i test di livello di unità e integrazione passeranno, anche il test di livello superiore dovrebbe passare, e hai un requisito fatto e ben testato.

    
risposta data 27.04.2018 - 23:45
fonte
2

Se hai bisogno di fare alcuni esperimenti e prototipazione per scoprire i requisiti corretti e un'implementazione funzionante, un approccio "prova per primo" ai test automatici potrebbe non funzionare correttamente.

Tuttavia, scrivere test unitari e altri tipi di test automatici in seguito funzionerà comunque. Certo, questo non è "TDD by the book", ma l'impatto sul design del tuo codice sarà in genere quasi lo stesso di quello che avevi scritto prima.

    
risposta data 28.04.2018 - 23:18
fonte
0

Se scrivi dei test perché hai dei requisiti, mi sembra sbagliato. Durante il processo di sviluppo della mia applicazione scrivo anche molti test perché mi aiutano a testare il mio codice in un ambiente piccolo e definito. Senza questo approccio dovrei eseguire l'intera applicazione che richiede molto tempo.

    
risposta data 29.04.2018 - 02:25
fonte
0

Ci sono informazioni decenti in queste risposte, ma non vedo molte informazioni veramente utili. Non sono un esperto di test ma il modo in cui capisco TDD in poche parole è che segui questo processo:

  • Scrivi un test
  • Assicurati che fallisca per il giusto motivo
  • Scrivi codice per passare il test

'Testing' è un argomento abbastanza ampio, ma penso che puoi applicare facilmente quanto sopra ai test unitari e anche ai test di accettazione.

Nel caso dei test unitari, i requisiti non contano davvero sull'IMO perché non esistono test unitari per dimostrare che il codice soddisfa uno o più requisiti. I test unitari sono scritti per dimostrare che il tuo codice funziona come volevi che funzionasse. Questo è tutto. Se ho un metodo add (), dovrei testare che aggiunge correttamente. Potrebbe essere il caso che ho davvero bisogno di un metodo di moltiplicazione. Non è qualcosa di cui ti preoccupi nei test unitari. Pertanto, una mancanza o requisiti non dovrebbero essere un ostacolo al test unitario. Fa parte del processo di codifica.

Per quanto riguarda i test di accettazione, un approccio abbastanza "test-driven" sta scrivendo i requisiti come test eseguibili. La consegna dei requisiti è quindi "fai funzionare questi test". È molto bello se riesci a portare avanti il processo, ma il tempo per scrivere questi test è significativo e può diventare uno sforzo di sviluppo a pieno titolo. Non sto dicendo che non ne valga la pena. Se riesci a farlo funzionare, i benefici sono enormi. Potrebbe essere difficile anche se stai giocando a "find a rock":

[you] here's a rock

[them] not that rock.

Trascorrerai molto tempo a scrivere e riscrivere gli script di test. Puoi ancora farlo, ma potrebbe essere costoso. In sostanza, fai una supposizione su ciò che dovresti consegnare e mettilo nei test. Scrivi il codice per far funzionare quel test e quando i "decisori" ti dicono che non hanno qualcos'altro, modifichi i test, risciacqua e ripeti.

Se non stai facendo test dell'unità TDD, è molto più facile ottenere le cose in questo modo ma ho la sensazione che tu stia parlando di qualcosa di più come test di accettazione qui.

    
risposta data 30.04.2018 - 17:45
fonte
0

Puoi cambiare la cultura? Sembra che sarà necessario per sviluppare iterativamente l'UAT e perfezionare i requisiti durante lo sviluppo del codice.

Dipende dall'organizzazione e da come l'organizzazione determina la definizione di fatto. Fai notare che se vogliono aumentare la loro qualità del software, è necessario che cambino il modo in cui sviluppatori e clienti interagiscono.

Nelle società più funzionanti per le quali ho lavorato, il perfezionamento dei requisiti dipendeva dallo staff tecnico senior e dagli analisti aziendali.

    
risposta data 30.04.2018 - 18:21
fonte
0

È difficile determinare esattamente cosa intendi, ma ho lavorato in un posto che ha insistito sul fatto che non potevano fornire requisiti testabili, presumo che tu abbia un significato simile.

In questo ambiente, il mio problema era più "Non so esattamente cosa mi chiedono di costruire", motivo per cui è stato molto difficile scrivere test per questo. I requisiti erano vaghi e ognuno di noi era solo una sorta di confusione verso un obiettivo in continua evoluzione ogni giorno.

Hanno anche definito questo "reattivo", ma ora so che era solo una manifestazione di dilettantismo e confusione.

In praticamente tutti i team di programmazione orientati agli oggetti, dovresti sapere cosa stai costruendo in anticipo. Dovresti sempre iniziare con un requisito in base al quale puoi almeno scrivere un test unitario, anche se non puoi scrivere l'implementazione.

Se qualcuno ti chiede di fare qualcosa, puoi scrivere un test. È così semplice. Se non riesci ad immaginare un modo per scrivere il test unitario, non ti viene davvero richiesto un requisito. Se tutto ciò che hai conosciuto è uno di quei datori di lavoro che "confondono" (cosa non comune) potrebbe essere difficile da comprendere, ma i requisiti in un sistema ben congegnato orientato agli oggetti dovrebbero quasi sempre equivalere a un particolare comportamento da un oggetto particolare dato un particolare insieme di input (la S del principio SOLID), ed è contro quell'oggetto che puoi scrivere il tuo test.

Se farlo sembra del tutto impossibile, si tratta di un odore di processo, enorme.

    
risposta data 29.04.2018 - 17:32
fonte
-1

Ci sono sempre dei requisiti, altrimenti non avresti motivo di scrivere codice.

Alcune volte ti vengono dati questi requisiti, a volte come programmatori devi soddisfare i requisiti usando la tua comprensione degli scopi dell'organizzazione per cui lavori. In pratica è generalmente una miscela dei due.

Dovunque arrivino i requisiti, se sono abbastanza specifici da permetterti di scrivere del codice, dovresti anche essere in grado di usarli per scrivere test, se lo desideri.

In qualche modo i test sono particolarmente importanti se hai soddisfatto alcuni dei requisiti e probabilmente hai bisogno di cambiarli, poiché i test potrebbero essere l'unica documentazione di quei requisiti e sono un luogo in cui mostrare eventuali modifiche requisiti che potrebbero verificarsi dopo aver ricevuto feedback su una versione del codice.

    
risposta data 30.04.2018 - 14:32
fonte

Leggi altre domande sui tag