come e dovrei 'unit test' un intero pacchetto?

4

Sto ancora imparando a fare del test di livello unit , dato che sono sempre stato un po 'trascurato nel fare solo test funzionali in passato, quindi voglio ricontrollare I' Sto facendo questo 'giusto'.

Ho un pacchetto che è responsabile per l'aggiornamento automatico di una particolare configurazione che dovrebbe cambiare regolarmente durante il runtime. Fornire un elenco di oggetti da monitorare al costruttore della mia classe di pacchetto principale. Quindi, ad un certo punto, l'aggiornamento delle chiamate passerà a tutte le diverse posizioni che definiscono la configurazione, rileva le modifiche, aggiorna lo stato appropriato per gli oggetti che sta monitorando e fornisce un rapporto su ciò che è stato modificato. Questo è tutto automatico e in altro modo trasparente per tutti gli altri pacchetti.

La mia inclinazione è quella di testarlo come un'unità, ma è un'unità piuttosto "grande", 5-6 classi e il recupero da più file e un'interfaccia riposante. Sembra che testare qualsiasi unità più piccola richiederebbe molto più tempo, essere meno flessibile per il refactoring e fornire solo una probabilità leggermente superiore di rilevare un difetto, ma potrebbe essere solo la mia pigrizia a parlare. Sarebbe considerato "migliore" testare a un livello inferiore?

Supponendo che sia 'giusto' testare il pacchetto come un'unità che è considerata appropriata per deridere qualcosa del genere? Ci sono metodi di classi che sono istanziati dalla mia classe principale (cioè, non qualcosa che passo direttamente in modo che io non possa passare il mio stesso finto) che abbia metodi che voglio controllare. Credo di poter usare powerMock nei due casi a cui riesco a pensare (o potrei, dopo aver ricercato ancora PowerMock), ma non sono sicuro che farlo sia abbastanza trasparente. Sta configurando PowerMock per rilevare e restituire un oggetto file di simulazione ogni volta che il mio pacchetto tenta di aprire un file di configurazione, anche se è sepolto in profondità nella logica del mio pacchetto, accettabile, o si ritiene che stia abusando della mia conoscenza dei dettagli specifici dell'implementazione? Sarebbe "più pulito" modificare effettivamente i file di configurazione sul file system e lasciarli leggere normalmente senza ulteriori derisioni? Avrei bisogno di modificare i file regolarmente per testare ...

Modifica: Per chiarire la questione dell'accoppiamento chiesto in una delle domande, non penso che le mie lezioni siano eccessivamente accoppiate. Effettivamente ho tre classi che recuperano lo stato da A, B e C, e quindi una classe 'principale' che prende lo stato dal tre e decide come combinarlo correttamente (cioè, se A e B non corrispondono all'uso A a meno che C). Potrei facilmente testare A B e C separatamente e poi deriderli per testare la mia classe 'principale'. Tuttavia, sembra che il test della mia classe "principale" testerebbe in ogni caso le interfacce comparativamente semplici per A, B e C se non le prendevo in giro. Quindi sembra un lavoro duplicato per testarli individualmente. Potrei ottenere una copertura del codice leggermente migliore, forse, con test individuali, ed è sempre bello avere un test solo una cosa. Ma non so se valga la pena coprire tutti i costi per benefici minori.

    
posta dsollen 01.04.2014 - 19:32
fonte

3 risposte

6

Il test unitario è il livello più basso di test, ma ciò significa solo che è il livello più basso che fai, non il livello più basso che potresti teoricamente fare. Se si esegue il test a livello di classe, è possibile eseguire il test a livello di metodo, utilizzando uno strumento di test appropriato per ottenere membri privati. Ma se si esegue il test a livello di metodo, è possibile eseguire il test a livello di istruzione, utilizzando uno strumento di test appropriato per ottenere la dichiarazione in isolamento, in modo da testarlo. E se decideste di testare a livello di istruzione, è comunque una decisione di non testare a livello di istruzione o di byteode. E quel processo di decomposizione si ferma solo quando qualcuno decide che "un'unità più piccola sarebbe stupida".

Quindi la domanda "come dovrei unità testare questo" è esattamente equivalente a "come dovrei prima prova questo '. Se il modo migliore di testare un pacchetto è nel suo insieme, perché è di dimensioni e complessità in cui testarlo come un'unità è il modo più efficace per raggiungere gli obiettivi di affidabilità e manutenibilità, allora fallo.

Se non lo è, non farlo.

Chiunque stia cercando di dare consigli più specifici senza vedere il proprio codice base o conoscere il contesto del progetto (centrale nucleare in un orfanotrofio o generatore di posta elettronica) è molto probabilmente non solo sbagliato, ma anche poco saggio.

    
risposta data 01.04.2014 - 23:19
fonte
2

Questa è una domanda abbastanza comune alle persone che iniziano a imparare TDD. Non so se questo è il tuo caso, ma la logica che puoi seguire è la stessa.

Per prima cosa, dimentica la parola "unità" per un momento. Pensa a come affronterai lo sviluppo dello stesso pacchetto da ground zero e test-first. Non puoi iniziare testando "solo una classe" o "solo un metodo" perché non hai ancora nulla e non sai tutte le classi e i metodi che saranno necessari.

Quindi si inizia specificando il primo pezzo di comportamento previsto in un test, per poi passare il test, il tutto con la quantità minima di codice richiesta per la parte specifica del comportamento. Ripeti questo ciclo fino a quando non viene implementato tutto il comportamento, mentre esegui il refactoring tra i cicli.

Durante il refactoring, puoi dividere la logica tra classi diverse e provare le opzioni di progettazione. I test continueranno a essere eseguiti sulla classe "main" o sulla "public API" della tua funzionalità. Questa è considerata la best practice per lo stesso motivo per cui hai menzionato, per evitare di ostacolare la libertà di refactoring del tuo codice.

Con questo ciclo in mente, nel tuo caso specifico, difficilmente sarà necessario prendere in giro qualcuno dei tuoi stessi collaboratori. Tuttavia, dovresti effettivamente prendere in giro le dipendenze esterne del tuo codice, come i file di configurazione e i servizi restful. Soprattutto perché dovresti essere in grado di testare il tuo codice senza dipendere da fattori ambientali come un file esistente in una directory e inoltre puoi aumentare la flessibilità della tua funzionalità se fornisci un punto di iniezione per tali dipendenze.

PS: So che non inizierai a scrivere il codice da zero, ma questa era una descrizione del processo che avresti seguito con TDD, solo per darti un'idea di come sarebbero stati i test.

PS2: Per "finto" intendo qualsiasi tipo di doppio di prova, come falsi, manichini, matrici, spie e vere mocche.

    
risposta data 02.04.2014 - 05:10
fonte
1

Il test unitario è come un ragionamento induttivo. Assicurati che il piccolo pezzo n sia ben educato, e quindi puoi fidarti che mentre costruisci il sistema, ogni n + 1 pezzo è anche ben educato.

Nel tuo caso, isolerei tutte le classi 5-6 nei singoli test per assicurarmi che ognuno stia facendo ciò che dovrebbe. (Questo ha un ulteriore vantaggio nell'accelerare la tua codifica, perché non stai sempre inciampando su difetti imprevisti.)

Se poi vuoi testare quelli che lavorano insieme in isolamento, va bene - considera solo ciò di cui hai bisogno per prendere in giro o fermare per dare il via a specifici percorsi logici. Ad un certo punto, qualcosa sta chiamando nel tuo sistema per attivare l'aggiornamento, quindi prendi in giro.

Una buona regola è, non testare qualcosa che non hai scritto - prendilo in giro.

A un livello più filosofico;) la definizione di "unità" non è una linea luminosa. Un'unità può essere un metodo o una classe, ma anche all'interno di un metodo, probabilmente ci sono riferimenti a più oggetti. Finché puoi tracciare un confine ragionevolmente piccolo attorno alla "unità" ed eseguirlo in isolamento, va tutto bene.

...

Un'altra considerazione è che se le tue 5-6 classi piccole sono facili da testare individualmente, allora sono probabilmente progettate per te. Se queste classi sono strettamente accoppiate e non puoi esercitarle separatamente, significa che probabilmente devi fare un passo indietro e osservare il tuo design.

    
risposta data 01.04.2014 - 19:41
fonte

Leggi altre domande sui tag