Codice test copia e incolla: quanto è grave?


12

Il mio lavoro attuale è principalmente quello di scrivere codice di test GUI per varie applicazioni su cui lavoriamo. Tuttavia, trovo che tendo a copiare e incollare molto codice all'interno dei test. La ragione di ciò è che le aree che sto testando tendono ad essere abbastanza simili da richiedere ripetizioni ma non abbastanza simili da incapsulare il codice in metodi o oggetti. Trovo che quando provo ad usare classi o metodi in modo più esteso, i test diventano più ingombranti da mantenere e talvolta addirittura difficili da scrivere in primo luogo.

Invece, di solito copio un grosso pezzo di codice di test da una sezione e lo incollo in un'altra, e apporto le modifiche minori di cui ho bisogno. Non uso modi più strutturati di codifica, come l'uso di più principi o funzioni OO.

Gli altri programmatori si sentono così quando scrivono il codice di prova? Ovviamente voglio seguire i principi DRY e YAGNI, ma trovo che il codice di test (codice di test automatizzato per i test GUI) può rendere questi principi difficili da seguire. O ho solo bisogno di più pratiche di codifica e di un migliore sistema generale di fare le cose?

EDIT: lo strumento che sto usando è SilkTest, che è in un linguaggio proprietario chiamato 4Test. Inoltre, questi test sono principalmente per le applicazioni desktop Windows, ma ho anche testato le app Web utilizzando questa configurazione.


Quale strumento di test stai usando? È possibile che il framework di test non supporti i tipi di test che stai scrivendo. Il cut-n-paste di più di 3 righe è generalmente pessimo, ma se sei in grado di aggiungere chiaramente più valore a lungo termine automatizzando un test della GUI piuttosto che eseguendolo ogni volta, allora qualsiasi cosa tu stia facendo è probabilmente dannatamente dannata bene.
GlenPeterson,

Inoltre, che lingua è questa? Si può avere qualcosa a disposizione di quella proprio non popping in mente, che consentirebbe il riutilizzo (come le funzioni di prima classe). D'altra parte, i test sono supposti essere tenuti semplice, di tenerlo in meno di probabilità di avere insetti stessi ...
Izkata

3
In tutto ciò che ho scritto, il codice di prova non è escluso dal refactoring.
Simon Whitehead,

Risposte:


23

I casi di test incollati e quindi modificati vanno spesso bene.

I test dovrebbero avere il minor numero possibile di dipendenze esterne ed essere il più semplice possibile. I casi di test tendono a cambiare nel tempo e casi di test in precedenza quasi identici possono improvvisamente divergere. L'aggiornamento di un caso di test senza doversi preoccupare di risolvere altri casi è una buona cosa.

Ovviamente, il codice del boilerplate che è identico in molti casi di test e che deve cambiare di concerto può e deve essere preso in considerazione.


1
Questo è principalmente come mi sento. Il codice di test quasi identico è ok in molti casi, ma il codice di test identico ripetuto è una brutta notizia.
joshin4colours,

12

La ripetizione è la radice di tutti i mali

È giusto! La ripetizione è la radice di tutti i mali . Probabilmente era Knuth a dire nel suo libro "L'ottimizzazione prematura è la radice di tutti i mali", ma penso che sia ripetizione.

Ogni volta che guardi un programma o ne scrivi uno e scopri qualche tipo di ripetizione: rimuovilo! Uccidilo immediatamente ... qualunque cosa, ma sbarazzartene !

Ogni volta che ho introdotto una sorta di ripetizione e ho dovuto correggere un bug, ho dimenticato di riparare la replica ... (Donald Knuth) Quindi, ogni volta che c'è una ripetizione, rimuovila nel miglior modo possibile, non hackerare !

Pensa a un design pulito e snello (come incapsulare i tuoi blocchi di codice ripetuti nelle classi di supporto) e scrivi alcuni test prima di cambiare qualcosa (solo per essere sicuro di non aver rotto qualcosa). Questo vale per qualsiasi parte di codice scritta e i codici di test non fanno eccezione.

Ecco una buona lettura di Code Horror che mi ispira: una proposta modesta per la copia e incolla della scuola di riutilizzo del codice .


"Ogni volta che ho introdotto una sorta di ripetizione e ho dovuto correggere un bug, ho dimenticato di riparare la replica ..." esattamente. Inoltre, se c & p e ti dimentichi di adattare il testo copiato al tuo contesto attuale, ciò farà molto male. Il codice di prova con errori non sembra la situazione ottimale, ora lo fa?
Marktani,

sì, ho preso le stazioni da Knuth :)
Yusubov,

9
Ti sei ripetuto: ti sei ripetuto dicendo "La ripetizione è la radice di tutti i mali" nel titolo e nella frase introduttiva.
Thomas Eding,

Sì, l'ho fatto intenzionalmente per sottolineare l'importanza e sei il benvenuto a modificare la parte :)
Yusubov,

1
Thomas Eding, anche tu ti sei ripetuto. Ti sei ripetuto anche =)
marktani il

7

È ancora piuttosto brutto da tagliare e incollare. Ci sono alcuni problemi

I tuoi test potrebbero essere fragili, perché sei vulnerabile a qualcosa che richiede una modifica in tutto quel codice di copia e incolla. Dovrai riscrivere tutti i test?

Se non è possibile incapsulare la logica in metodi di supporto esterni ai test, non è possibile scrivere test di tali metodi di supporto stessi. Scrivere test sui metodi di prova è di solito difficile da rendere utile, poiché è necessario rompere il codice per testare il test. Ma si può unità metodi di prova di supporto.

Potrebbe rendere i test meno leggibili. Un grande blocco di codice copiato può essere più difficile da leggere rispetto a una chiamata al metodo helper con un nome descrittivo.

Tutto quello che ho elencato è qualcosa che potrebbe essere un problema. Se si trova nessuno di loro in realtà sono un problema poi, naturalmente, va bene.


> una chiamata al metodo helper con un nome descrittivo. Non è questo il problema che i test unitari stanno diventando programmi in sé - cosa che si intende evitare. Che cosa succede se alcuni test falliscono - è il codice che è rotto o gli aiutanti del test?
dwjohnston,

4

Ero d'accordo con te. Ma poi, nel tempo, ho scoperto che ogni cambiamento che ho apportato (in particolare i cambiamenti DI nei test unitari) ha richiesto numerosi test per cambiare e questo è stato complicato. Ora mi iscrivo alla scuola di DRY, anche quando scrivo dei test.

Per i test della GUI, potresti voler esaminare il modello PageObject per ridurre il codice ripetuto.


2

Consiglierei di raccogliere i modelli XUnit. Avevo lo stesso identico problema fino a quando non ho iniziato a sfruttare quel libro. La madre oggetto modello suona come se fosse il più utile per il tuo scenario.

Come qualcun altro ha menzionato, incapsulare correttamente questo codice di installazione potrebbe essere oneroso, ma doverlo cambiare in tutti i luoghi che copi e incolli lo è ancora di più.


+1 per il Object Mother patterncodice di inizializzazione comune.
k3b,

2

Le persone dovrebbero cercare di limitare la ripetizione quando possono - sì. Ma il profitto dipende dalla situazione. Ciò potrebbe tornare al dibattito sulle "migliori pratiche". Ma la domanda è: cosa è meglio per te in questa situazione. Ci sono eccezioni ad ogni regola.

Un paio di cose che vorrei chiedere sono: 1) Quanto è probabile che questa funzionalità testata nell'UAT cambi? Se è improbabile che cambi, allora ci sono meno possibilità che dovrai aggiornare ciascuno dei tuoi set di codice. 2) Se si verifica una modifica in UAT, avrà sempre un impatto su ogni set del codice copiato o potrebbe avere un impatto solo su uno o due set? Se potrebbe essere isolato e richiedere solo una modifica a un set, potrebbe essere utile separare le cose. 3) Quanto sarà complesso il metodo iniziale se provi e gestisci tutti gli scenari? Stai aggiungendo molti if / else / loop nidificati? Se inizi a fare troppe ramificazioni, potresti finire con un codice difficile da comprendere. Sarebbe più semplice effettuare l'aggiornamento in ciascuno dei testi copiati piuttosto che rivisitare tutta la logica di ramificazione?

Se sei bloccato copia / incolla / modifica penso che vorresti aggiungere commenti come 'Questo è copiato nel metodo xyz'. In questo modo ti verrà ricordato di aggiornare tutte le versioni incollate del codice. Oppure (proveniente da un altro utente SilkTest) potresti aggiungere un file inc separato che si concentrerebbe solo su questo codice ripetuto. In questo modo hai tutte le varianti in un unico posto e potresti facilmente vedere i diversi metodi che richiederebbero un aggiornamento.


0

Una grande procedura

Un pensiero: sembra che tu stia cercando di evitare il codice taglia e incolla creando metodi come:

testScreen(title, fieldList, linkList, param1, param2, param3,...) {
    test that the layout at the top of the screen is correct
    test if PageTitle == title?
    for each field in fieldList:
        check that it appears in order on the screen
    for each field in linkList:
        check that it appears in order on the screen
    test if param1 is whatever...
    test if param2 is whatever...
    etc.
    test that the bottom of the screen is correct
}

Molte piccole procedure (toolkit)

Hai considerato anche l'approccio opposto? Invece di passare un milione di parametri a una grande procedura testScreen (), magari crea il tuo framework o kit di strumenti di piccole procedure di aiuto che tiri fuori quando ne hai bisogno. Piace:

testScreenTop()
verifyLinks(list)
testScreenBottom()

Continui a tagliare e incollare queste procedure in ogni schermata, ma stai tagliando e incollando blocchi di codice più piccoli e ritagliando pezzi di comunanza che non vengono tagliati e incollati (il contenuto di ogni piccola procedura).

Taglia e incolla

L'unica volta in cui il codice tagliato e incollato non mi ha morso è stato quando il codice è stato gettato via prima che dovessi cambiarlo. La mia più grande preoccupazione con i test dell'interfaccia utente è la velocità con cui diventano obsoleti. Se ti accorgi di buttare via tutto il codice prima di cambiarlo, allora forse hai trovato una nicchia in cui tagliare e incollare va bene! Inoltre, non è così male quando non c'è codice a valle del codice taglia e incolla (ad esempio nell'interfaccia utente di un'applicazione). Se stai incollando più di 3 righe, guarderei davvero a fare qualcosa al riguardo. Almeno prendi provvedimenti per minimizzarlo!

Test automatizzati dell'interfaccia utente

Cavolo, se puoi provare una maggiore produttività con i test UI automatizzati rispetto ai test manuali usando qualsiasi tecnica (il costo di scrittura / mantenimento dei test automatizzati è inferiore rispetto ai test manuali ogni volta, ma la qualità è la stessa) Penso che dovresti scrivere un documento. Lo leggerei! Ora riesco a vedere il titolo "Taglia e incolla Code a Net Win per i test dell'interfaccia utente!"


0

Non è poi così male. In effetti, se scopri che alcuni schemi di codice vengono utilizzati molto spesso e le modifiche sono molto di routine (come alcune stringhe o valori di parametro), potresti persino scrivere un generatore di codice che genera un codice di test ripetitivo basato su un piccolo (- ish?) input elenco di valori che cambiano. L'ho fatto molte volte (codice di test generato), utilizzando file batch, script SQLPlus e persino macro di Excel (sembra brutto, ma le variabili per i diversi script di test erano già in un foglio di calcolo) e può far risparmiare molto tempo . Il fatto è che se qualcosa cambia nella struttura complessiva del codice del test case ripetitivo, puoi semplicemente rigenerare tutto ciò di cui hai bisogno.


0

Questo è lo stesso della maggior parte delle altre risposte, ma in un modo che un manager non tecnico può capire.

Immagina il seguente scenario di errore:

  • Qualcuno apporta modifiche alla banca dati da cui dipende gran parte del test.
  • Conseguenza: improvvisamente 117 dei tuoi 2933 test automatici falliscono.

Cosa farai?

  • (1) correggere 117 test?
  • (2) elimina i 117 test e li reimplementa con il nuovo copia e incolla. questo potrebbe essere più semplice di (1)
  • (3) riformattare i test per estrarre il codice comune in modo che in futuro sia necessario adattare solo un metodo (o alcuni) per correggere i test (vedere le risposte di @pdr o @Michael Brown)
  • (4) eliminare i 117 test senza reimplementare i test

Dalla mia esperienza:

Quando si introduce la gestione automatica dei test, ad esempio "copia e incolla-test": si ottengono molti test in breve tempo.

Dopo alcuni degli "scenari di errore" la gestione preferisce (4) perché riparare "copia e incolla-test" è così costoso.

Farlo bene in primo luogo (3) non sarà così veloce ma aumenta le possibilità che i test sopravvivranno

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.