Copia-e-incollato codice di prova: quanto è cattivo questo?

11

Il mio attuale lavoro è principalmente la scrittura di codice di test GUI per varie applicazioni su cui lavoriamo. Tuttavia, trovo che io tendo a copiare e incollare un sacco di codice all'interno dei test. Il motivo è che le aree che sto testando sono abbastanza simili da richiedere ripetizioni, ma non abbastanza simili per incapsulare il codice in metodi o oggetti. Trovo che quando cerco di 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 una grande porzione di codice di test da una sezione e la incollo su un'altra, e apporto le modifiche minori di cui ho bisogno. Non uso metodi di codifica più strutturati, come l'utilizzo di più principi OO o funzioni.

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 automatico per i test della GUI in ogni caso) possa rendere questi principi difficili da seguire. O ho solo bisogno di più pratica di codifica e 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 di Windows, ma ho anche provato le app Web utilizzando questa configurazione.

    
posta joshin4colours 19.09.2012 - 18:44
fonte

9 risposte

22

I casi di test copiati e incollati copiati spesso vanno 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 in precedenza casi di test quasi identici possono divergere improvvisamente. L'aggiornamento di un test case senza doversi preoccupare di rompere altri casi è una buona cosa.

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

    
risposta data 19.09.2012 - 19:09
fonte
11

La ripetizione è la radice di tutti i mali

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

Ogni volta che guardi un programma o ne stai scrivendo uno e scopri qualche tipo di ripetizione: rimuovilo! Uccidilo immediatamente ... qualunque cosa tranne liberati di esso !

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

Pensa a un design pulito e snello (come incapsulare i blocchi di codice ripetuti nelle classi di helper) e scrivi alcuni test prima di cambiare qualcosa (solo per essere sicuro di non aver infranto qualcosa). Questo è vero per ogni pezzo di codice che viene scritto e i codici di test non fanno eccezione.

Ecco una buona lettura di Code Horror che mi ispira - Una proposta modesta per il riutilizzo del codice di copia e incolla del codice .

    
risposta data 19.09.2012 - 19:49
fonte
6

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

I tuoi test potrebbero essere fragili, perché sei vulnerabile a qualcosa che richiede un cambiamento in tutto quel codice copiato e incollato. 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 da soli. Scrivere i test dei metodi di test è solitamente difficile da ottenere, dato che è necessario interrompere il codice per testare il test. Ma tu puoi metodi di test di unità di misura.

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

Tutto ciò che ho elencato è qualcosa che potrebbe essere un problema. Se non trovi nessuno di questi sono un problema, ovviamente va bene.

    
risposta data 19.09.2012 - 19:08
fonte
4

Ero d'accordo con te. Ma poi, nel tempo, ho scoperto che ogni cambiamento che ho apportato (in particolare i cambiamenti di DI nei test unitari) richiedeva numerosi test per cambiare ed era ingombrante. Ora mi iscrivo alla scuola di DRY, anche quando scrivo test.

Per i test della GUI, ti consigliamo di consultare il pattern PageObject per ridurre il codice ripetuto.

    
risposta data 19.09.2012 - 19:06
fonte
2

Raccomando di prendere in considerazione i pattern XUnit. Avevo lo stesso identico problema fino a quando non ho iniziato a sfruttare quel libro. Il modello Oggetto Madre sembra il più utile per il tuo scenario.

Come qualcun altro ha menzionato, incapsulare correttamente questo codice di configurazione potrebbe essere oneroso, ma doverlo modificare in tutte le posizioni che copi e incolla lo è ancora di più.

    
risposta data 19.09.2012 - 19:48
fonte
2

Le persone dovrebbero cercare di limitare la ripetizione quando possono - sì. Ma il guadagno dipende dalla situazione. Questo 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 nella UAT cambierà? Se è improbabile che cambierà, allora ci sono meno possibilità che tu debba aggiornare ognuno dei tuoi set di codice. 2) Se c'è un cambiamento in UAT, avrà sempre un impatto su ogni serie del codice copiato o potrebbe influire 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 a farlo gestire tutti gli scenari? Stai aggiungendo un sacco di nidificati se / else / loop? Se inizi a fare tutte le ramificazioni, potresti finire con un codice difficile da comprendere. Sarebbe più semplice fare l'aggiornamento in ciascuno dei testi copiati rispetto a quello di rivedere tutta la logica di ramificazione?

Se sei bloccato copia / incolla / altera penso che vorrai 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) è possibile 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 l'aggiornamento.

    
risposta data 20.09.2012 - 20:00
fonte
0

One Big Procedure

Un pensiero: sembra che tu stia cercando di evitare il codice cut-n-paste 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
}

Many Little Procedures (toolkit)

Hai anche considerato l'approccio opposto? Invece di passare un milione di parametri a una grande procedura testScreen (), forse crea il tuo framework o kit di strumenti di piccole procedure di supporto che ti frustano nel momento in cui ne hai bisogno. Come:

testScreenTop()
verifyLinks(list)
testScreenBottom()

Ancora tagliate e incollate queste procedure in ogni schermata, ma state tagliando e incollando piccoli pezzi di codice e ritagliandoli pezzi di comunanza che non vengono tagliati e incollati (il contenuto di ciascuna piccola procedura).

Taglia e incolla

L'unica volta in cui il codice cut-and-pasted non mi ha morso è stato quando il codice è stato gettato via prima che dovessi cambiarlo. La mia più grande preoccupazione per i test dell'interfaccia utente è quanto velocemente diventano obsoleti. Se scopri di buttare via tutto il codice prima di cambiarlo, allora forse hai trovato una nicchia in cui tagliare e incollare è OK! Inoltre, non è così male quando non c'è codice downstream dal codice cut-and-pasted (ad esempio nell'interfaccia utente di un'applicazione). Se stai incollando più di 3 linee, vorrei davvero fare qualcosa al riguardo. Almeno fai dei passi per minimizzarlo!

Test UI automatizzato

Diamine, se puoi dimostrare una maggiore produttività con i test UI automatizzati rispetto ai test manuali usando la tecnica qualsiasi (il costo di scrittura / mantenimento dei test automatici è inferiore a quello manuale ogni volta, tuttavia la qualità è la stessa ) Penso che dovresti scrivere un articolo. Lo leggerei! Ora riesco a vedere il titolo: "Copia e incolla il codice per ottenere un test UI!"

    
risposta data 19.09.2012 - 21:09
fonte
0

Non è poi così male. Infatti, se si trovano che alcuni pattern di codice vengono utilizzati molto spesso e le modifiche sono di routine (come alcune stringhe o valori di parametro), si potrebbe anche scrivere un generatore di codice che genera un codice di test ripetitivo basato su un piccolo (- ish?) lista di input dei valori che cambiano. Ho fatto questo (codice di test generato) molte volte, usando file batch, script SQLPlus, anche macro di Excel (sembra brutto, ma le variabili per i diversi script di test erano già in un foglio di calcolo) e può essere un ottimo risparmio di tempo . Il fatto è che se qualcosa cambia nella struttura complessiva del codice del caso di test ripetitivo, puoi semplicemente rigenerare tutto ciò che ti serve.

    
risposta data 19.09.2012 - 23:25
fonte
0

Questo è uguale alla 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 al database in cui molti dei test dipendono.
  • Conseguenza: improvvisamente 117 dei 2933 test automatici falliscono.

Che cosa farai?

  • (1) risolvi 117 test?
  • (2) elimina i 117 test e li reimplementa con nuova copia e incolla. questo potrebbe essere più facile di (1)
  • (3) rifattora i test per estrarre il codice comune in modo che in futuro devi adattare solo un metodo (o alcuni) per correggere i test (vedi le risposte di @pdr o @Michael Brown)
  • (4) elimina i 117 test senza reimplementare i test

Dalla mia esperienza:

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

Dopo che alcuni degli "scenari di errore" preferiscono la gestione (4), perché la correzione di "copia e collaudo" è così costosa.

Fai bene in primo luogo (3) non sarà così veloce ma aumenterai le probabilità che i test sopravvivano

    
risposta data 22.03.2017 - 15:31
fonte

Leggi altre domande sui tag