Quando devo scrivere i test di integrazione?


30

Secondo le regole del TDD, i test unitari sono scritti prima del codice di produzione, ma per quanto riguarda i test di integrazione che esercitano l'interazione tra oggetti cablati concreti (non simulati)?

Dovrebbero essere scritti prima dei test unitari o dopo il codice di produzione solo per testare il "cablaggio"?

Si noti che non sto parlando di test di accettazione o funzionali ma di test di integrazione di livello inferiore.

Risposte:


49

Il libro Rspec , tra le altre risorse BDD, suggerisce un ciclo come questo:

inserisci qui la descrizione dell'immagine

In sostanza, il processo è:

While behaviour required
    Write an integration test for a specific behaviour
    While integration test failing
        Write a unit test to fulfil partial behavior
        While unit test failing
            Write code to make unit test pass
        Commit
        While refactoring can be done
            Refactor
            While unit test failing
                Write code to make unit test pass
            Commit
    Push

Dichiarazione di non responsabilità: non ho dubbi sul fatto che questo porta al miglior codice e prodotto, ma può richiedere molto tempo. Ci sono tutti i tipi di difficoltà riguardo ai dati e al determinismo, quando si tratta di dire che i test di integrazione devono sempre passare. Non è appropriato in tutte le circostanze; a volte devi solo portare cose fuori dalla porta.

Detto questo, avere in mente un processo ideale è grandioso. Ti dà un punto da cui scendere a compromessi.


2
Grazie @pdr ma ho specificato che non stavo parlando dei test di accettazione scritti prima / all'inizio di una iterazione, sono interessato ai test di integrazione di livello inferiore.
Chedy2149,

@ chedy2149: Akkh. Ho perso quel commento. Prima di rimuovere la mia risposta, penso che dovresti essere più specifico su cosa intendi per "livello inferiore" nel contesto dei test di integrazione.
pdr,

Livello inferiore: quale comportamento non è specificato da utenti o client e quali sono utilizzati per testare le interazioni tra classi / componenti è previsto dagli sviluppatori.
Chedy2149,

4
In realtà, non penso che faccia la differenza se metti "test di accettazione" o "test di integrazione" in quella foto - è una visione idealizzata per qualsiasi tipo di test su diversi livelli di astrazione. Ma IMHO il vero problema non è che questo potrebbe richiedere "tempo" - il vero problema è che scrivere i test di integrazione "in anticipo" su un'interfaccia pubblica che è ancora stata progettata con l'aiuto di TDD è come sparare a un "bersaglio mobile" ".
Doc Brown,

@DocBrown quindi la tua risposta è dopo il codice di produzione e prima del rilascio?
Chedy2149,

10

Il vero progetto mi ha mostrato che non è possibile scrivere unit test e quindi l'integrazione e anche la direzione opposta è sbagliata :-) Quindi, di solito scrivo unit test insieme a quelli di integrazione.

Perché? Fammi scrivere come vedo entrambi i tipi di test:

  1. Test unitari - Oltre a Wikipedia e tutte le informazioni note, i test unitari ti aiutano a restringere il design , migliorare il modello, le relazioni. Il flusso è semplice: una volta che inizi a digitare un nuovo progetto / nuovo componente, la maggior parte delle volte stai realizzando una sorta di PoC . Quando hai finito, hai sempre metodi lunghi, classi lunghe, metodi e classi non coerenti, ecc.

    I test unitari aiutano a rimuovere questi problemi come quando si eseguono test di unità reali utilizzando le classi mock (senza dipendenza da altri componenti) sopra descritte non sono verificabili. Il segno di base del codice non verificabile è una parte beffarda dei test perché sei costretto a deridere molte dipendenze (o situazioni)

  2. Test di integrazione - test corretti e funzionanti ti dicono che il tuo nuovo componente (o componenti) lavora insieme o con altri componenti - questa è la definizione normale. Ho scoperto che i test di integrazione aiutano principalmente a definire il flusso su come utilizzare il componente dal lato consumatore .

    Questo è davvero importante perché a volte ti dice che la tua API non ha senso dall'esterno.

Bene, cosa succede una volta che ho scritto unit test e test di integrazione in seguito?

Ho preso lezioni carine, design chiaro, buon costruttore, metodi brevi e coerenti, predisposto per l'IoC ecc. Una volta che ho dato la mia classe / API a un consumatore, ad esempio uno sviluppatore del team di integrazione o GUI, non è stato in grado di usare la mia API perché sembra non logico , strano. Era solo confuso. Quindi ho riparato l'API in base al suo punto di vista, ma ha anche richiesto di riscrivere molti test perché sono stato spinto a cambiare i metodi e talvolta anche il flusso su come utilizzare l'API.

Bene, cosa succede dopo aver scritto i test di integrazione e i test unitari in seguito?

Ho il flusso esatto, buona usabilità. Quello che ho anche sono grandi classi, codice non coerente, nessuna registrazione, metodi lunghi. Codice spaghetti

Qual è il mio consiglio?

Ho imparato il seguente flusso:

  1. Sviluppa lo scheletro di base del tuo codice
  2. Scrivi test di integrazione che diano se ha senso dal punto di vista del consumatore. Il caso d'uso di base è abbastanza per ora. Il test ovviamente non funziona.
  3. Scrivi il codice insieme ai test unitari per ogni classe.
  4. Scrivi il resto / mancante dei test di integrazione. Sarebbe meglio implementare questi test entro # 3 su come stai migliorando il tuo codice.

Si noti che ho fatto una piccola presentazione sui test di unità / integrazione, vedere la diapositiva n. 21 in cui è descritto lo scheletro.


5

I test unitari vengono utilizzati per testare il più piccolo bit testabile possibile di software in un'applicazione e per testarne la funzionalità. Ogni unità viene testata separatamente prima di riunirle in parti o componenti più grandi dell'applicazione.

È qui che arrivano i test di integrazione :
testano queste parti appena create che sono costituite dalle unità precedentemente testate durante il montaggio di queste parti. Il caso migliore sarebbe quello di scrivere i test a questo punto mentre si scrive l'applicazione stessa.


Quindi la tua risposta è dopo il codice di produzione?
Chedy2149,

Questo non risponde alla domanda. Chiede se il codice di produzione viene scritto dopo che sono stati scritti i test di integrazione. La tua risposta può essere presa in entrambi i modi.
Reactgular

1
@MathewFoscarini - risposta aggiornata. Spero che ora diventi più chiaro.
Ben McDougall,

Per quanto riguarda i test di unità, vorrei prendere problema con il "più piccolo possibile po 'di software". Verifica ciò che è nel contratto (ad es. Metodi pubblici di un oggetto, funzioni esportate di una libreria) perché il contratto definisce cosa deve funzionare. Altre cose sono verificabili, eppure non è solo una perdita di tempo ma controproducente.
itsbruce,

3

Tendo a considerare i test di integrazione molto simili ai test unitari. In quello sto trattando un sottoinsieme del codice come una scatola nera. Quindi i test di integrazione sono solo una scatola più grande.

Preferisco scriverli prima del codice di produzione. Questo ha il vantaggio di aiutarmi a ricordare quali pezzi non ho ancora collegato o che ho leggermente modificato un dettaglio nell'interazione degli oggetti.


Esistono diversi livelli di test: test dei componenti della scatola bianca, test dei componenti di integrazione della scatola bianca. Test di componenti black box, test di integrazione black box. Esistono anche test del sistema di integrazione.
Alexander.Iljushkin,

2

A parte i test di accettazione, tendo a scrivere solo test di integrazione ai limiti di un'applicazione, per verificare che si integri bene con sistemi o componenti di terze parti.

L'idea è quella di creare oggetti adattatore che traducono da come la terza parte parla a ciò di cui la tua applicazione ha bisogno e testare questi traduttori rispetto al vero sistema esterno. Sia che tu faccia quel test per primo o per ultimo, penso sia meno importante che con i tuoi test unitari regolari perché

  • Le informazioni sul design fornite da TDD non contano molto qui poiché il design è praticamente noto in anticipo e in genere non c'è nulla di terribilmente complesso in questione, basta mappare le cose da un sistema all'altro.

  • A seconda del modulo / sistema che si desidera affrontare, può richiedere molta esplorazione, modifica della configurazione, preparazione dei dati di esempio, che richiede tempo e non si adatta molto bene in un breve circuito di feedback TDD.

Tuttavia, se ti senti davvero più a tuo agio a costruire il tuo adattatore in modo incrementale in piccoli passaggi sicuri, ti consiglio vivamente di iniziare il test, non può far male.

Puoi trovare esempi di questo approccio qui: http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html (sesto paragrafo) http://blog.8thlight.com/eric- smith / 2011/10/27 / thats-non-yours.html


qui stai parlando di test di integrazione che verificano le interazioni tra il "nostro sistema" e le librerie di terze parti, che ne dici di testare le interazioni con una piattaforma durante lo sviluppo di un plug-in, ad esempio?
Chedy2149,

Anche se ho poca esperienza con lo sviluppo di plug-in, suppongo che potrebbero essere diversi poiché sono per natura strettamente accoppiati con l'applicazione host, quindi potresti voler abbracciare completamente tale integrazione e decidere di non aver bisogno di un livello adattatore. In tal caso, tuttavia, farei molta attenzione alle prestazioni del test - a seconda dell'applicazione host, chiamare la sua API direttamente in un gran numero di test può essere molto lento. Se ne hai paura, puoi sempre ricorrere all'approccio del "livello aggiuntivo di astrazione" e utilizzare i test di simulazione + integrazione sugli adattatori.
guillaume31,

1

Quindi avrei accettato la prima risposta ma è stata eliminata.
Per riassumere
In una data iterazione:

  1. Scrivi unit-test
  2. Scrivi il codice di produzione
  3. Scrivi test di integrazione per testare le interazioni

Tenere presente i test di integrazione mentre 1 e 2 per garantire la testabilità a livello di integrazione.

I test di integrazione non sono necessariamente scritti end-to-end nella fase 3, ma possono essere parzialmente scritti tra la fase 1 e 2.


3
Questo riassunto ignora completamente la natura iterativa del processo. Una volta che l'API del tuo codice di produzione è stabile in una certa misura, puoi iniziare a scrivere test di integrazione, quindi puoi lavorare di nuovo sul tuo codice di produzione e probabilmente modificare o estendere i tuoi test di integrazione. Quindi nella maggior parte dei casi non "scrivi test di integrazione dopo il codice di produzione", in genere fai entrambi in una certa misura in parallelo. E in realtà, questo dipende anche fortemente dal tipo di software che stai lavorando. Il pensiero "in bianco e nero" non ti porta oltre.
Doc Brown,

Un buon punto: la risposta sembra ignorare la natura iterativa del design attraverso il refactoring.
Chedy2149,

0

I test unitari verificano blocchi discreti di codice all'interno del progetto.
I test di integrazione testano come il tuo codice si interfaccia con altri codici: in altre parole, testano l' interfaccia del tuo codice.

Scrivi unit test durante lo sviluppo di codice dietro un'interfaccia.
Scrivere test di integrazione quando si sviluppa l'interfaccia o qualsiasi codice che implementa l'interfaccia.

Ciò significa che a volte scriverai test di integrazione molto tardi in un progetto, perché la maggior parte del lavoro è dietro l'interfaccia: ad esempio un compilatore, un particolare servizio web che implementa diversi livelli di logica o ... qualcosa che coinvolge un sacco di logica interna.

Tuttavia, se stai implementando una serie di servizi REST o rifattorizzando il modello di dati e aggiungendo il supporto per le transazioni XA, inizierai a sviluppare test di integrazione quasi immediatamente, poiché la maggior parte del tuo lavoro è centrata sull'interfaccia, indipendentemente dal fatto che sia l'API REST o come il programma utilizza il modello di dati.


Accetteresti di dire che i test unitari sono test whitebox e i test di integrazione sono test blackbox?
Chedy2149,

Sfortunatamente, dipende. Le tecnologie per i test di integrazione hanno apportato enormi miglioramenti negli ultimi anni (almeno nel mondo Java) in modo che io possa testare 1 classe, ma su un server delle applicazioni. La domanda diventa allora: dov'è il confine tra unit test e test di integrazione? Un test di integrazione quando si verifica il codice si interfaccia con altre tecnologie o è un test di integrazione quando si verifica l'intera applicazione, ma non necessariamente nell'ambiente in cui è previsto l'esecuzione?
Marco,

In breve, in alcuni casi, i test di integrazione sicuri sono test in scatola nera, ma non in tutti i casi.
Marco,

FYI: Wiki definisce i test di integraion come "la fase di test del software in cui i singoli moduli software sono combinati e testati come un gruppo"
Marco,

Esatto, Marco. Esistono integrazioni a livello di ciascun componente. Livello di codice, livello di applicazione, livello di sistema.
Alexander.Iljushkin,
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.