Metodologia: scrivere test unitari per un altro sviluppatore


28

Stavo pensando allo sviluppo del software e alla scrittura di unit test. Ho avuto la seguente idea:

Supponiamo di avere coppie di sviluppatori. Ogni coppia è responsabile di una parte del codice. Uno della coppia implementa una funzione (scrittura del codice) e il secondo scrive un'unità di test per essa. I test sono scritti dopo il codice. Nella mia idea si aiutano a vicenda, ma funzionano piuttosto separatamente. Idealmente dovrebbero lavorare su due funzioni di dimensioni simili e poi scambiarsi per la preparazione del test.

Penso che questa idea abbia alcuni aspetti positivi:

  • i test sono scritti da qualcuno che può vedere di più sull'implementazione,
  • il lavoro dovrebbe essere reso un po 'più veloce della programmazione in coppia (due funzioni contemporaneamente),
  • sia i test che il codice ne hanno una persona responsabile,
  • il codice è testato da almeno due persone e
  • forse la ricerca di errori nel codice scritto da una persona che sta testando il tuo codice darebbe una motivazione speciale per scrivere codice migliore ed evitare di tagliare gli angoli.

Forse è anche una buona idea aggiungere un altro sviluppatore per la revisione del codice tra lo sviluppo del codice e dei test.

Quali sono gli svantaggi di questa idea? È già descritto come una metodologia sconosciuta a me e utilizzata nello sviluppo del software?

PS. Non sono un project manager professionista, ma so qualcosa sui processi di sviluppo del progetto e conosco le poche metodologie più popolari, ma questa idea non mi sembra familiare.


17
Stai solo descrivendo il QA a valle a livello di unità. Se hai coppie di persone che lavorano su qualcosa, hai provato l'effettiva programmazione di coppie con TDD?
jonrsharpe,

9
Funzionerebbe meglio se lo scrittore test eseguisse prima i test (scrivere il codice scheletro) e l'altro implementasse la funzionalità. Il primo avrebbe il controllo del progetto e l'altro avrebbe fatto il sollevamento pesante. Ciò potrebbe funzionare bene se il primo sa cosa sta facendo e al secondo non dispiace seguire sempre il suo esempio. Non conosco un nome per questo modo di cooperare. Direi .. reclamalo! Inizia a chiamare questo sviluppo Franiis.
Martin Maat,

14
Questa critica non ha senso e il tuo suggerimento non risolve quel problema.
jonrsharpe,

5
@franiis Ho visto colleghi scrivere assert truecome test e chiamarlo un giorno perché ogni test stava superando. Mancava un passaggio importante: i test dovrebbero prima fallire e dovrebbero essere fatti passare cambiando il codice, non i test.
Eric Duminil il

6
@franiis TDD è costruito attorno all'iterazione. Scrivi test fallito. Scrivi il codice che rende il test verde. Refactor. Scrivi un test fallito. Scrivi il codice che rende il test verde. Refactor. Sembra che ti manchi la parte "ripeti finché non hai dei test che coprono tutti i tuoi requisiti". Ma il problema più grande che sembra avere è che i "test" sono visti come qualcosa che devi avere perché qualcuno lo ha detto, piuttosto che i test sono uno strumento utile per gli sviluppatori . Se non riesci a convincere le persone a preoccuparsi della qualità (e della correttezza) del loro codice, questo è il tuo problema, ed è qui che dovresti iniziare.
Luaan,

Risposte:


30

L'approccio generale di usare le coppie per dividere lo sforzo di scrivere il codice di produzione e scrivere i test unitari associati non è raro. Mi sono persino associato personalmente in questo modo prima con un discreto successo. Tuttavia, una linea rigorosa tra la persona che scrive il codice di produzione e la persona che scrive il codice di prova potrebbe non necessariamente produrre risultati.

Quando ho usato un approccio simile, la coppia inizia parlando e ottenendo una comprensione condivisa del problema. Se stai usando TDD, potresti iniziare prima con alcuni test di base. Se non stai usando TDD, forse inizierai con la definizione del metodo. Da qui, entrambi i membri della coppia lavorano sia sul codice di produzione che sul codice di prova, con una persona focalizzata su ciascun aspetto, ma parlando dei modi per migliorare il codice di produzione e il codice di prova dietro di esso.

Non vedo il vantaggio di dare a ciascuna coppia due caratteristiche. Quello che finiresti è qualcosa che ricorda TDD per alcune funzionalità e qualcosa che non lo fa per altre funzionalità. Perdi la concentrazione. Non si ottengono i vantaggi della revisione tra pari in tempo reale. Non si ottiene nessuno dei principali vantaggi dell'associazione.

La pratica della programmazione di coppia non riguarda la velocità, ma la qualità. Quindi provare a usare una tecnica modificata guidata andando più veloce va contro natura. Costruendo software di qualità superiore tramite revisione di codici paralleli e sviluppo di test, si risparmia tempo a valle poiché ci sono almeno due persone a conoscenza di ogni modifica e si stanno eliminando (o riducendo) i cicli di attesa per la revisione e il test dei pari.


Grazie, la mia idea presuppone che entrambe le funzionalità siano sviluppate allo stesso modo (ma gli sviluppatori si scambiano ruoli) - solo per chiarire, non per difendere il senso di quel concetto. Mi piace la tua risposta e la tua attenzione alla velocità rispetto alla qualità.
franiis, il

Nella mia esperienza, i costi di rilavorazione superano i benefici di questo approccio. Preferirei che una coppia si scambiasse questi compiti usando il "ping-pong" o un altro metodo.
Neontapir,

3
La pratica della programmazione di coppia non riguarda la velocità, ma la qualità. Pair TDD riguarda la qualità, che porta velocità di completamento, che porta a costi di sviluppo inferiori. È solo il nostro settore che apprende ciò che i muratori hanno conosciuto per i millenial: il tuo muro sarà costruito meglio in meno tempo, con meno sforzo e meno costi se perdi un po 'di tempo a impostare prima una linea di corda e una regola di muratore, quindi posare i mattoni, se poni il mattone e cerchi di adattarti in seguito con livella e mazza. E ottenere aiuto con le cose.
Laurent LA RIZZA,

@LaurentLARIZZA Sembra corretto. Suppongo che un modo migliore per dire che sarebbe "La pratica della programmazione di coppia non riguarda la velocità nel presente, ma la qualità e la velocità nel futuro". È sicuramente una pratica lungimirante trovare problemi prima, migliorare la robustezza del lavoro e condividere le conoscenze per abbattere i silos. Tutti questi hanno un costo ora che spesso pagherà ricompense in futuro.
Thomas Owens

@ThomasOwens: Beh, il costo della qualità è solo percepito, non reale. Una volta superato il test (e aver riordinato il codice), lo scenario descritto dal test viene eseguito e protetto e si ottiene la certezza che funzioni come previsto. È fatto e puoi andare avanti. Se vai avanti senza la certezza che il codice funzioni, hai appena accettato un debito che dovrai eseguire i controlli in seguito. Costo dei debiti, non assenza di debiti. Voglio dire, il "futuro" di cui parli è non appena il tuo primo test viene superato.
Laurent LA RIZZA,

37

Il problema principale con la tua idea è che non puoi semplicemente scrivere test per qualsiasi codice. Il codice deve essere testabile.

Cioè devi essere in grado di iniettare beffe, separare il bit che vuoi testare, accedere allo stato che è cambiato e deve essere confermato ecc.

Se non sei fortunato o non scrivi prima il test, è probabile che scrivere il test significhi riscrivere un po 'il codice. Che, se non sei la persona che scrive il codice in primo luogo, significa ritardi, riunioni, refactoring ecc.


Grazie. ma la critica comune al TDD è che il codice è talvolta / spesso scritto per rendere i test "verdi" - no per essere buoni. Se i test non verificano alcuni aspetti del codice, potrebbe essere omesso nel codice. Scrivere test in seguito potrebbe essere di aiuto (accetto che dopo la scrittura del codice possano essere necessarie alcune modifiche, ma gli sviluppatori dovrebbero imparare a scrivere codice più testabile in futuro).
franiis,

1
@franiè certo, il problema principale non è che tu scriva i test dopo, è la combinazione di farlo e non essere la stessa persona che ha scritto il codice.
Ewan,

ma se l'utilizzo, ad esempio, della programmazione di coppia richiederebbe meno tempo. Se due sviluppatori lavorano su un terminale, non possono in alcun modo lavorare contemporaneamente su due funzionalità, e la mia idea dovrebbe consentirlo (anche in ambito limitato). Le riunioni per il micro-team di 2 persone non dovrebbero essere un onere reale.
franiis,

25
@franiis: "Se i test non verificano alcuni aspetti del codice, potrebbe essere omesso nel codice." - Questo è il punto. I test sono una codifica dei requisiti sotto forma di esempi eseguibili. Se non esiste un test per esso, allora non è necessario per esso e non dovrebbe esserci codice per esso .
Jörg W Mittag,

3
L'altro lato di ciò che ha detto @ JörgWMittag sarebbe: se i tuoi test "non mettono alla prova alcuni importanti del codice", allora devi correggere i tuoi test. Questo sarà vero nel tuo sistema come nel TDD tradizionale.
BTA

15

Il problema principale che vedo qui, a livello di unità, quando scrivo codice, voglio compilarlo, eseguirlo e rimuovere immediatamente i bug più evidenti, anche quando il codice è incompleto e so che l'unità, la caratteristica o la funzione è implementato solo parzialmente. E per eseguire il codice di un'unità, ho bisogno di un pezzo di programma che chiama l'implementazione, di solito un test unitario o almeno un test unitario parziale. Questo non è necessariamente "stile TDD dal libro", tale test può essere scritto dopo o prima del codice in esame.

Quando una versione della mia unità è "funzionalità completa" e libera da tutti i bug che posso trovare in questo modo da sola, allora ha senso consegnarla a una seconda persona e lasciarla scrivere ulteriori test di unità o rivedere il mio codice . Ma per me non ha senso consegnarlo non appena il compilatore non mostra avvisi, è decisamente troppo presto nel caso in cui so che dovevo spiegare in dettaglio il tester cose che non funzionano "ancora", o funzioneranno diversamente tra due ore da quando sto ancora lavorando a quel pezzo di codice. Le spese generali di comunicazione necessarie per questo a quel livello di dettaglio non sarebbero bilanciate dai benefici.

Quindi sì, avere un secondo sviluppatore che scrive ulteriori unit test ha senso, ma non per scrivere esclusivamente i unit test .


7

Sembrerebbe esserci la possibilità che si verifichi una delle seguenti situazioni, tutte indesiderabili:

Confusione

Come sottolineato da Ewan, il CUT potrebbe dover essere modificato per renderlo testabile. Il motivo della modifica non è sempre ovvio per lo sviluppatore (e può causare disaccordo) ed è esattamente il motivo per cui i test vengono scritti per primi.

contesa

Lo sviluppatore A potrebbe aver completato il proprio codice e volerlo testare. Lo sviluppatore B potrebbe anche essere in fase di sviluppo e quindi potrebbe essere reticente parcheggiare il proprio codice per partecipare ai test unitari.

Cambio di contesto

Anche se lo sviluppatore B è disposto a bloccare il loro sviluppo per testare il codice scritto dallo sviluppatore A , il cambiamento di attività ha un costo.


È stato accettato per decenni che il raddoppio del potere umano non dimezza i tempi di sviluppo. Considerando i fattori che ho delineato sopra, è difficile vedere come questo accordo migliorerebbe le cose.


4

Se usato in congiunzione con la programmazione di coppie e TDD, questo è chiamato Ping Pong Pattern :

  • A scrive un nuovo test e vede che fallisce.
  • B implementa il codice necessario per superare il test.
  • B scrive il test successivo e vede che fallisce.
  • A implementa il codice necessario per superare il test.

E così via. Il refactoring viene eseguito ogniqualvolta si presenti l'esigenza di chi guida.

Ma sembra che tu proponga che entrambi i programmatori codifichino con computer diversi. Farlo separatamente richiederebbe una specifica di livello molto basso. Questo va contro le metodologie agili. Ogni cambiamento dovrebbe essere coordinato. In TDD stai facendo il desing di basso livello al volo e non è un problema. Presumo che il tuo approccio richiederebbe di avere un qualche tipo di scheletri già codificati.

Ad ogni modo: puoi imparare molto testando nuovi modi di fare le cose anche se non sono efficienti al 100%. Puoi testarlo e condividere la tua esperienza di vita reale


3

Sto arrivando tardi a questa festa, ma penso di avere qualcosa da aggiungere.

È già descritto come una metodologia sconosciuta a me e utilizzata nello sviluppo del software?

Stai descrivendo Peer Testing .

Supponiamo di avere coppie di sviluppatori.

Ah, buon vecchio programma di coppia .

Ogni coppia è responsabile di una parte del codice. Uno della coppia implementa una funzione (scrittura del codice) e il secondo scrive un'unità di test per essa. I test sono scritti dopo il codice. Nella mia idea si aiutano a vicenda, ma funzionano piuttosto separatamente.

Questa non è la programmazione di coppia.

Idealmente dovrebbero lavorare su due funzioni di dimensioni simili e poi scambiarsi per la preparazione del test.

Questo è sicuramente Peer Testing. Ecco un documento ACM al riguardo . L'ho fatto. Ho lavorato laddove era una parte formale del processo di Peer Review . È utile, ma certamente non è pensato per essere la prima linea di test, e certamente non è la classica programmazione di coppia.

Un altro nome per questo è Whitebox Testing . Sebbene quella definizione non si occupi di chi sta facendo i test tanto quanto del fatto che il tester riesce a vedere il funzionamento interno della cosa che sta testando, al contrario dei test della Black Box in cui vedono solo cosa succede e cosa esce. La scatola nera è in genere ciò che fa il QA.

La prima linea di test è saldamente nelle mani del programmatore. In caso contrario, mi stai chiedendo di non testare il mio codice, cosa che mi rifiuto categoricamente di fare. Ho testato il mio codice da quando avevo 10 anni. Allora non avrei potuto eseguire test con unità di test elaborate ma il mio codice è stato testato. È stato testato ogni volta che l'ho eseguito.

Quello che mi aspetto da un peer tester sono i test che si aggiungono ai miei test. Test che chiariscono abbondantemente i problemi riscontrati dal peer con il codice quando lo hanno esaminato. Esprimendo questi problemi con un test automatizzato, è più facile capire cosa significano. Infatti, ho avuto conversazioni tecniche con colleghi che non riuscivano a capire il punto che stavo sollevando e poi ho capito che il modo migliore per mostrare loro il problema era scrivere un test unitario. Questo è Peer Testing.

Ora, se vuoi darmi dei test scritti prima di scrivere il mio codice bene. Niente come un documento di requisiti così formale da compilare.


Grazie per la risposta e per avermi indicato Peer Testing (ne leggerò).
franiis,

1

Ho fatto DDT (test guidato dallo sviluppo, ovvero test dopo codice), coppia programmazione e TDD refactore rosso-verde per diversi anni ciascuno. Per rispondere alle tue affermazioni punto per punto:

i test sono scritti da qualcuno che può vedere di più sull'implementazione

La persona che scrive i test deve conoscere l'implementazione il più intimamente possibile, per scrivere test con una buona copertura senza test eccessivi. L'esempio classico di questo è il test con tre input quando due dimostrerebbero ciò che si sta tentando di testare. Sebbene possano acquisire familiarità superficiale con il codice leggendolo, non saranno in grado di capire esattamente cosa ha attraversato lo sviluppatore originale per arrivare allo stato corrente. Quindi avranno una comprensione non ottimale del codice.

il lavoro dovrebbe essere reso un po 'più veloce della programmazione in coppia (due funzioni contemporaneamente)

Non capisco perché lo dici. Mentre qualcuno sta scrivendo dei test non sta lavorando a nuove funzionalità. Non puoi raddoppiare magicamente la capacità lavorativa di qualcuno dando loro due diversi tipi di lavoro. Nella mia esperienza, scrivere i test è generalmente più difficile che scrivere il codice di produzione, quindi sicuramente non si può lavorare in modo produttivo e responsabile sui test di alcuni codici mentre si scrive un'altra funzione.

sia i test che il codice ne sono responsabili

Innanzitutto, i test sono codice. Per il codice di test aziendale è quasi importante quanto il codice di produzione, perché consente all'azienda di cambiare il software senza paura. In secondo luogo, questo non è diverso da una persona che scrive i test e il codice di produzione, o anche una coppia che scrive entrambi.

il codice è testato da almeno due persone

No, viene testato solo dalla persona che scrive il test. A meno che tu non voglia usare ancora più tempo per i test, nel qual caso perché fermarsi alle due?

forse la ricerca di errori nel codice scritto da una persona che sta testando il tuo codice darebbe una motivazione speciale per scrivere codice migliore ed evitare di tagliare gli angoli.

Gli sviluppatori (anche quelli senior) hanno idee molto diverse su cosa costituisca un codice "buono". Il taglio di una persona è il modo perfettamente valido di un'altra per arrivare al codice di lavoro al più presto. Questa è una ricetta per la colpa e per il gioco del sistema.

TDD red-green-refactor (in realtà scrive un singolo test prima di scrivere codice di produzione, eseguirlo, vederlo fallire, modificare solo il codice di produzione , eseguire nuovamente il test, vederlo avere successo, quindi refactoring e non saltare o scambiare nessuno dei questi passaggi) e le revisioni del codice funzionano.


Sarebbe più veloce (presumibilmente) perché non hai due persone che fanno lo "stesso lavoro": ognuno fa le proprie cose e poi si scambia a metà strada.
Jacob Raihle,

@JacobRaihle L'accoppiamento non è due persone che si sviluppano fianco a fianco senza comunicazione. Sarebbero due persone che fanno lo stesso lavoro. L'associazione è davvero efficiente perché due persone stanno collaborando a un lavoro. Nella mia esperienza lo sviluppo è più rapido di quello dei singoli programmatori (ovvero, le coppie eseguono il lavoro due volte più velocemente), il software risultante è di qualità molto più elevata e la conoscenza è stata condivisa.
l0b0

Sto cercando di spiegare la logica alla base del "lavoro dovrebbe essere reso un po 'più veloce", che sembrava confondervi. L'abbinamento di solito è più lento nella mia esperienza, anche se penso ancora che ne valga la pena (preferibile sia al lavoro individuale che ai test di OP consegnati). Se è più veloce per te, tanto meglio.
Jacob Raihle,

1

Penso che questa idea abbia alcuni aspetti positivi:

Li attraversiamo uno per uno.

i test sono scritti da qualcuno che può vedere di più sull'implementazione,

Quindi, vuoi dire che il primo sviluppatore ha trascorso del tempo a scrivere un po 'di implementazione, che non è sicuro che funzioni. Quindi, arriva un altro sviluppatore e scrive test, basando il suo ragionamento sul codice che nessuno sa se sia corretto e sperando che apporti un vantaggio tattico rispetto alla scrittura di test solo per quanto riguarda ciò che il codice dovrebbe fare. Se l'implementazione non è corretta, la mia opinione sarà che non aiuti a scrivere test.

il lavoro dovrebbe essere reso un po 'più veloce della programmazione in coppia (due funzioni contemporaneamente)

Una volta che entrambi gli sviluppatori hanno terminato il loro sviluppo iniziale, nessuno sa se nessuno dei loro codici è corretto. Questo resta ancora da verificare, nessuno può spuntare nessuno come fatto, e nessuno può prevedere quando saranno fatti. Confronta questo con TDD: scrivi prima il test, poi fallisci il test, quindi passa con il codice. Questo è il codice che supporta sempre più scenari. Questo è il movimento in avanti.

Se li fai progredire in parallelo, il codice che potrebbe essere riutilizzato in entrambe le funzionalità verrà scritto due volte e costa due volte di più.

sia i test che il codice ne hanno una persona responsabile,

Cerca la proprietà del codice collettivo, come proposto da XP. Avrai ancora più persone responsabili del codice. Se il tuo obiettivo è condividere le conoscenze tra gli sviluppatori, perché stai cercando di separarle?

il codice è testato da almeno due persone

Anche con coppia TDD. Durante l'associazione, entrambe le persone devono concordare che il codice scritto è adeguato o non scriverlo. Se questo si traduce in una rissa, alcune persone nella squadra hanno un problema di ego fuori posto.

forse la ricerca di errori nel codice scritto da una persona che sta testando il tuo codice darebbe una motivazione speciale per scrivere codice migliore ed evitare di tagliare gli angoli.

La ricerca di errori implica che a un certo punto hai tollerato che entrassero. Se sono entrati, sono stati inosservati. Rifiutare di scrivere prima i test è dare la licenza agli errori per entrare.

L'angolo di taglio potrebbe non essere intenzionale. Ecco a cosa serve la programmazione di coppie. Ogni membro della coppia dovrebbe essere istruito con il dovere di non lasciare che l'altro tagli gli angoli, perché bene, lo facciamo tutti. Ciò richiede di lasciare il tuo orgoglio nell'armadio e riprenderlo quando lasci l'ufficio. Se ti aspetti che la tua gente sia immancabilmente rigorosa, non stai prendendo in considerazione la situazione comune e ti prepari per il fallimento.

XP afferma esplicitamente che tutte le pratiche di XP sono fatte per rafforzarsi a vicenda coprendo i reciproci difetti. Non dovresti ascoltare le critiche a nessuna pratica di XP separata dalle altre. Nessuna pratica è perfetta, TDD non è perfetto, la programmazione delle coppie non è perfetta, la proprietà del codice collettivo non è perfetta, ma si coprono tutti l'un l'altro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.