Devo testare metodi privati ​​o solo pubblici? [chiuso]


348

Ho letto questo post su come testare metodi privati. Di solito non li collaudo, perché ho sempre pensato che fosse più veloce testare solo metodi pubblici che verranno chiamati dall'esterno dell'oggetto. Collaudi metodi privati? Devo sempre testarli?



"Devo testare gli aiutanti privati?" Sì. "Devo testare direttamente gli aiutanti privati?" Dipende, generalmente se riesci a testarli facilmente attraverso l'interfaccia pubblica, perché testarli direttamente? Se diventa complesso testare tutti gli aspetti degli helper attraverso un'interfaccia pubblica, allora il componente è sopravvissuto alla sua esistenza come singola unità?
Mihai Danila,

Risposte:


328

Non collaudo i metodi privati ​​dell'unità. Un metodo privato è un dettaglio dell'implementazione che dovrebbe essere nascosto agli utenti della classe. Il test di metodi privati ​​interrompe l'incapsulamento.

Se trovo che il metodo privato sia enorme o complesso o abbastanza importante da richiedere i propri test, lo inserisco in un'altra classe e lo pubblico ( oggetto metodo ). Quindi posso facilmente testare il metodo precedentemente privato, ma ora pubblico, che ora vive nella sua stessa classe.


88
Non sono d'accordo. Idealmente, scrivi un test rapido prima di iniziare a scrivere una funzione. Pensa all'input tipico e quale sarà l'output. Scrivi il test (che non dovrebbe richiedere più di qualche secondo) e codifica fino a quando il test non è corretto. Non c'è motivo di abbandonare quello stile di lavoro per metodi privati.
Frank,

254
Dire che i metodi privati ​​non hanno bisogno di essere testati è come dire che un'auto va bene finché guida bene e non importa cosa c'è sotto il cofano. Ma non sarebbe bello sapere che alcuni cavi all'interno si stanno allentando, anche se l'utente non nota nulla? Certo, puoi rendere tutto pubblico, ma che senso ha? Avrai sempre bisogno di alcuni metodi privati.
Frank,

37
"Un metodo privato è un dettaglio di implementazione che dovrebbe essere nascosto agli utenti della classe." ma i test sono davvero dalla stessa parte dell'interfaccia della classe degli utenti "normali" (runtime)? ;)
mlvljr,

34
Il pericolo di estrarre tutto ciò che si desidera testare in un'altra classe è che si può finire con l'overhead di progettare eccessivamente il prodotto e avere un milione di componenti riutilizzabili che non vengono mai riutilizzati.
occulus,

44
Confrontare un pezzo di codice con un'auto è sbagliato; il codice non " va male " con il tempo, è eterno . Se il test dell'interfaccia pubblica arriva fino a determinare che " sembra a posto ", il test del codice pubblico è insufficiente. In questo caso testare metodi privati ​​separatamente non completerà il test generale, indipendentemente da quanto ci si provi. Concentrati sul test esaustivo del tuo codice pubblico nel suo insieme, usando la conoscenza del funzionamento interno del codice per creare gli scenari giusti.
Rustyx,

293

Qual è lo scopo del test?

La maggior parte delle risposte finora afferma che i metodi privati ​​sono dettagli di implementazione che non contano (o almeno non dovrebbero) a condizione che l'interfaccia pubblica sia ben testata e funzionante. È assolutamente corretto se il tuo unico scopo per i test è garantire che l'interfaccia pubblica funzioni .

Personalmente, il mio uso principale per i test del codice è quello di garantire che future modifiche al codice non causino problemi e, se lo fanno, mi aiutano i miei sforzi di debug. Trovo che testare i metodi privati ​​altrettanto accuratamente dell'interfaccia pubblica (se non di più!) Favorisce tale scopo.

Considera: hai un metodo pubblico A che chiama il metodo privato B. A e B utilizzano entrambi il metodo C. C viene modificato (forse da te, forse da un fornitore), facendo sì che A inizi a fallire i suoi test. Non sarebbe utile fare anche dei test per B, anche se è privato, in modo da sapere se il problema è nell'uso di C da parte di C, nell'uso di C da parte di B o in entrambi?

Testare metodi privati ​​aggiunge anche valore nei casi in cui la copertura dei test dell'interfaccia pubblica è incompleta. Sebbene questa sia una situazione che generalmente vogliamo evitare, i test delle unità di efficienza dipendono sia dai test che rilevano i bug sia dai relativi costi di sviluppo e manutenzione di tali test. In alcuni casi, i vantaggi della copertura del test al 100% possono essere giudicati insufficienti per giustificare i costi di tali test, producendo lacune nella copertura dei test dell'interfaccia pubblica. In tali casi, un test ben mirato di un metodo privato può essere un'aggiunta molto efficace alla base di codice.


72
Il problema qui è che quei "futuri cambiamenti di codice" invariabilmente significano refactoring del funzionamento interno di qualche classe. Questo succede così spesso che scrivere test crea una barriera al refactoring.
Programmatore fuorilegge,

40
Inoltre, se si modificano continuamente i test unitari, si è persa ogni coerenza nei test e si potrebbero persino creare bug nei test unitari stessi.
17 del 26

6
@ 17 Se i test e l'implementazione vengono modificati in modo sincrono (come sembra, dovrebbe essere), ci saranno molti meno problemi.
mlvljr,

11

3
@Pacerier C'è anche una differenza tra testare il codice e avere un processo di test automatico continuo. Ovviamente dovresti assicurarti che il tuo metodo privato funzioni, ma non dovresti avere test che ti accoppino al metodo privato, perché non fa parte del caso d'uso del software.
Didier A.

150

Tendo a seguire il consiglio di Dave Thomas e Andy Hunt nel loro libro Pragmatic Unit Testing :

In generale, non vuoi interrompere alcun incapsulamento per motivi di test (o come diceva la mamma, "non esporre i tuoi privati!"). Il più delle volte, dovresti essere in grado di testare una classe esercitando i suoi metodi pubblici. Se c'è una funzionalità significativa che è nascosta dietro l'accesso privato o protetto, potrebbe essere un segnale di avvertimento che c'è un'altra classe lì che lotta per uscire.

Ma a volte non riesco a smettere di testare metodi privati ​​perché mi dà quel senso di rassicurazione che sto costruendo un programma completamente solido.


9
Consiglierei di disabilitare i test unitari destinati a metodi privati. Sono un accoppiamento di codice e graveranno sui futuri lavori di refactoring o talvolta ostacolano l'aggiunta o la modifica delle funzionalità. È bene scrivere un test per loro mentre li stai implementando, come un modo automatizzato per affermare che le tue implementazioni funzionano, ma non è utile mantenere i test come regressione.
Didier A.

61

Mi sento in qualche modo obbligato a testare le funzioni private mentre seguo sempre più una delle nostre ultime raccomandazioni QA nel nostro progetto:

Non più di 10 nella complessità ciclomatica per funzione.

Ora l'effetto collaterale dell'applicazione di questa politica è che molte delle mie funzioni pubbliche molto grandi si dividono in molte funzioni private più mirate e meglio denominate .
La funzione pubblica è ancora lì (ovviamente) ma è essenzialmente ridotta a chiamare tutte quelle "sotto-funzioni" private

Questo è davvero interessante, perché il callstack è ora molto più facile da leggere (invece di un bug all'interno di una funzione di grandi dimensioni, ho un bug in una sotto-funzione con il nome delle funzioni precedenti nel callstack per aiutarmi a capire 'come ci sono arrivato')

Tuttavia, ora sembra più facile testare direttamente tali funzioni private e lasciare i test della grande funzione pubblica a una sorta di test di "integrazione" in cui è necessario affrontare uno scenario.

Solo i miei 2 centesimi.


2
per reagire a @jop, non sento la necessità di esportare quelle funzioni private (create a causa della divisione di una grande funzione pubblica complessa troppo ciclomatica) in un'altra classe. Mi piace averli ancora strettamente associati alla funzione pubblica, nella stessa classe. Ma ancora testato dall'unità.
VonC,

2
La mia esperienza è che quei metodi privati ​​sono solo metodi di utilità che vengono riutilizzati da quei metodi pubblici. A volte è più conveniente dividere la classe originale in due (o tre) classi più coerenti, rendendo pubblici quei metodi privati ​​nelle proprie classi e quindi verificabili.
jop

7
no, nel mio caso, quelle nuove funzioni private fanno davvero parte dell'algoritmo più grande rappresentato dalla funzione pubblica. Tale funzione è divisa in parti più piccole, che non sono utilità, ma passaggi di un processo più ampio. Da qui la necessità di testarli
unitamente

Per chi fosse interessato la complessità ciclomatica, ho aggiunto una domanda sul tema: stackoverflow.com/questions/105852/...
VonC

Spiacenti, l'URL della domanda è cambiato a causa di un errore di battitura nel titolo! stackoverflow.com/questions/105852/...
VonC

51

Sì, collaudo le funzioni private, perché sebbene siano testate con i tuoi metodi pubblici, è bello in TDD (Test Driven Design) testare la parte più piccola dell'applicazione. Ma le funzioni private non sono accessibili quando si è nella propria classe di unità di test. Ecco cosa facciamo per testare i nostri metodi privati.

Perché abbiamo metodi privati?

Le funzioni private esistono principalmente nella nostra classe perché vogliamo creare codice leggibile nei nostri metodi pubblici. Non vogliamo che l'utente di questa classe chiami direttamente questi metodi, ma attraverso i nostri metodi pubblici. Inoltre, non vogliamo cambiare il loro comportamento durante l'estensione della classe (in caso di protezione), quindi è un privato.

Quando codifichiamo, utilizziamo TDD (test-driven-design). Ciò significa che a volte ci imbattiamo in un pezzo di funzionalità che è privato e vogliamo testare. Le funzioni private non sono testabili in phpUnit, perché non possiamo accedervi nella classe Test (sono private).

Pensiamo che qui ci siano 3 soluzioni:

1. Puoi testare i tuoi privati ​​attraverso i tuoi metodi pubblici

vantaggi

  • Test unitari semplici (non sono necessari "hack")

svantaggi

  • Il programmatore deve capire il metodo pubblico, mentre vuole solo testare il metodo privato
  • Non stai testando la parte più piccola testabile dell'applicazione

2. Se il privato è così importante, allora forse è un codemell creare una nuova classe separata per esso

vantaggi

  • Puoi rifattarlo in una nuova classe, perché se è così importante, anche altre classi potrebbero averne bisogno
  • L'unità testabile è ora un metodo pubblico, quindi testabile

svantaggi

  • Non si desidera creare una classe se non è necessaria e utilizzata solo dalla classe da cui proviene il metodo
  • Potenziale perdita di prestazioni a causa del sovraccarico aggiunto

3. Modificare il modificatore di accesso su (finale) protetto

vantaggi

  • Stai testando la parte più piccola testabile dell'applicazione. Quando si utilizza la protezione finale, la funzione non sarà sostituibile (proprio come un privato)
  • Nessuna perdita di prestazioni
  • Nessun costo aggiuntivo

svantaggi

  • Stai modificando un accesso privato a protetto, il che significa che è accessibile dai suoi figli
  • Hai ancora bisogno di una classe Mock nella tua classe di test per usarla

Esempio

class Detective {
  public function investigate() {}
  private function sleepWithSuspect($suspect) {}
}
Altered version:
class Detective {
  public function investigate() {}
  final protected function sleepWithSuspect($suspect) {}
}
In Test class:
class Mock_Detective extends Detective {

  public test_sleepWithSuspect($suspect) 
  {
    //this is now accessible, but still not overridable!
    $this->sleepWithSuspect($suspect);
  }
}

Quindi la nostra unità di test ora può chiamare test_sleepWithSuspect per testare la nostra precedente funzione privata.


eddy147, mi piace molto il concetto di testare metodi protetti tramite simulazioni. Grazie!!!!
Theodore R. Smith

15
Voglio solo sottolineare che nella descrizione originale del TDD, nei test unitari, l' unità è la classe , non un metodo / funzione. Pertanto, quando si parla di "test della parte più piccola dell'applicazione", è errato fare riferimento alla parte più piccola testabile come metodo. Se usi questa logica, potresti anche parlare una sola riga di codice anziché un intero blocco di codice.
Matt Quigley,

@Matt Un'unità di lavoro può puntare a una classe, ma anche a un singolo metodo.
eddy147,

4
@ eddy147 Il test unitario arriva Test Driven Development, in cui l'unità è stata definita come una classe. Come accade con The Internet, la semantica si è espansa per significare un sacco di cose (cioè chiedere a 2 persone qual è la differenza tra unità e test di integrazione e otterrai 7 risposte). TDD era inteso come un modo per scrivere software con principi SOLID, inclusa la responsabilità singola, in cui una classe aveva una sola responsabilità e non dovrebbe avere un'elevata complessità ciclica. In TDD, scrivi la tua classe e testa insieme, entrambe le unità. I metodi privati ​​sono incapsulati non hanno un test unitario corrispondente.
Matt Quigley,

"Quando codifichiamo, utilizziamo TDD (test-driven-design). Ciò significa che a volte ci imbattiamo in un pezzo di funzionalità che è privato e vogliamo testare." Non sono assolutamente d'accordo con questa affermazione, per favore vedi la mia risposta sotto per ulteriori dettagli. TDD non significa che sei costretto a testare metodi privati. Puoi scegliere di testare metodi privati: e questa è la tua scelta, ma non è TDD che ti sta facendo fare una cosa del genere.
Matt Messersmith,

41

Non mi piace testare la funzionalità privata per un paio di motivi. Sono i seguenti (questi sono i punti principali per le persone TLDR):

  1. In genere quando sei tentato di testare il metodo privato di una classe, è un odore di design.
  2. Puoi testarli attraverso l'interfaccia pubblica (che è come li vuoi testare, perché è così che il client li chiamerà / li utilizzerà). Puoi ottenere un falso senso di sicurezza vedendo il via libera su tutti i test di superamento per i tuoi metodi privati. È molto meglio / più sicuro testare casi limite sulle funzioni private attraverso l'interfaccia pubblica.
  3. Rischi una duplicazione grave dei test (test che sembrano / sembrano molto simili) testando metodi privati. Ciò ha conseguenze importanti quando i requisiti cambiano, poiché molti più test del necessario si interromperanno. Può anche metterti in una posizione in cui è difficile eseguire il refactoring a causa della tua suite di test ... che è la massima ironia, perché la suite di test è lì per aiutarti a riprogettare e refactoring in sicurezza!

Spiegherò ciascuno di questi con un esempio concreto. Si scopre che 2) e 3) sono in qualche modo collegati in modo complesso, quindi il loro esempio è simile, anche se li considero motivi separati per cui non dovresti testare metodi privati.

Ci sono momenti in cui testare metodi privati ​​è appropriato, è importante essere consapevoli dei lati negativi sopra elencati. Lo esaminerò più dettagliatamente in seguito.

Vado anche oltre perché TDD non è una scusa valida per testare metodi privati ​​alla fine.

Rifattorizzare la tua via d'uscita da un cattivo design

Uno dei più comuni (anti) sostenitori che vedo è ciò che Michael Feathers chiama una classe "Iceberg" (se non sai chi è Michael Feathers, vai a comprare / leggere il suo libro "Lavorare efficacemente con il codice legacy". una persona che vale la pena sapere se sei un ingegnere / sviluppatore di software professionale). Ci sono altri (anti) schemi che fanno sorgere questo problema, ma questo è di gran lunga il più comune in cui mi sono imbattuto. Le classi "Iceberg" hanno un metodo pubblico e il resto è privato (motivo per cui è allettante testare i metodi privati). Si chiama classe "Iceberg" perché di solito esiste un metodo pubblico solitario, ma il resto della funzionalità è nascosto sott'acqua sotto forma di metodi privati.

Valutatore di regole

Ad esempio, potresti voler testare GetNextToken()chiamandolo su una stringa in successione e vedendo che restituisce il risultato atteso. Una funzione come questa merita un test: quel comportamento non è banale, specialmente se le tue regole di tokenizzazione sono complesse. Facciamo finta che non sia così complesso, e vogliamo solo legare in token delimitati dallo spazio. Quindi scrivi un test, forse sembra qualcosa del genere (qualche codice psuedo agnostico in lingua, si spera che l'idea sia chiara):

TEST_THAT(RuleEvaluator, canParseSpaceDelimtedTokens)
{
    input_string = "1 2 test bar"
    re = RuleEvaluator(input_string);

    ASSERT re.GetNextToken() IS "1";
    ASSERT re.GetNextToken() IS "2";
    ASSERT re.GetNextToken() IS "test";
    ASSERT re.GetNextToken() IS "bar";
    ASSERT re.HasMoreTokens() IS FALSE;
}

Bene, sembra davvero carino. Vorremmo assicurarci di mantenere questo comportamento mentre apportiamo modifiche. Ma GetNextToken()è una funzione privata ! Quindi non possiamo provarlo in questo modo, perché non verrà nemmeno compilato (supponendo che stiamo usando un linguaggio che impone effettivamente pubblico / privato, a differenza di alcuni linguaggi di scripting come Python). Ma che dire di cambiare la RuleEvaluatorclasse per seguire il principio di responsabilità singola (principio di responsabilità singola)? Ad esempio, sembra che un parser, un tokenizer e un valutatore siano bloccati in una classe. Non sarebbe meglio separare queste responsabilità? Inoltre, se crei una Tokenizerclasse, i suoi metodi pubblici sarebbero HasMoreTokens()e GetNextTokens(). La RuleEvaluatorclasse potrebbe avere unTokenizeroggetto come membro. Ora, possiamo mantenere lo stesso test di cui sopra, tranne per il fatto che stiamo testando la Tokenizerclasse anziché laRuleEvaluator classe.

Ecco come potrebbe apparire in UML:

Valutatore di regole refactored

Nota che questo nuovo design aumenta la modularità, quindi potresti potenzialmente riutilizzare queste classi in altre parti del tuo sistema (prima che non potessi, i metodi privati ​​non sono riutilizzabili per definizione). Questo è il principale vantaggio di abbattere RuleEvaluator, insieme a una maggiore comprensibilità / località.

Il test sembrerebbe estremamente simile, tranne che questa volta verrà effettivamente compilato poiché il GetNextToken()metodo è ora pubblico sulla Tokenizerclasse:

TEST_THAT(Tokenizer, canParseSpaceDelimtedTokens)
{
    input_string = "1 2 test bar"
    tokenizer = Tokenizer(input_string);

    ASSERT tokenizer.GetNextToken() IS "1";
    ASSERT tokenizer.GetNextToken() IS "2";
    ASSERT tokenizer.GetNextToken() IS "test";
    ASSERT tokenizer.GetNextToken() IS "bar";
    ASSERT tokenizer.HasMoreTokens() IS FALSE;
}

Test dei componenti privati ​​tramite un'interfaccia pubblica ed evitando la duplicazione del test

Anche se non pensi di poter scomporre il tuo problema in un minor numero di componenti modulari (che puoi provare il 95% delle volte se provi a farlo), puoi semplicemente testare le funzioni private attraverso un'interfaccia pubblica. Molte volte i membri privati ​​non valgono la pena testarli perché saranno testati attraverso l'interfaccia pubblica. Molte volte quello che vedo sono test che sembrano molto simili, ma testano due diverse funzioni / metodi. Quello che finisce per accadere è che quando i requisiti cambiano (e lo fanno sempre), ora hai 2 test non funzionanti invece di 1. E se davvero hai testato tutti i tuoi metodi privati, potresti avere più di 10 test rotti invece di 1. In breve , test delle funzioni private (usandoFRIEND_TESTo renderli pubblici o utilizzare la riflessione) che potrebbero altrimenti essere testati tramite un'interfaccia pubblica può causare la duplicazione del test. Non lo vuoi davvero, perché niente fa più male della tua suite di test che ti rallenta. Dovrebbe ridurre i tempi di sviluppo e ridurre i costi di manutenzione! Se testate metodi privati ​​altrimenti testati attraverso un'interfaccia pubblica, la suite di test potrebbe benissimo fare il contrario e aumentare attivamente i costi di manutenzione e aumentare i tempi di sviluppo. Quando rendi pubblica una funzione privata, o se usi qualcosa di simile FRIEND_TESTe / o riflesso, di solito finirai per pentirti a lungo termine.

Considera la seguente possibile implementazione della Tokenizerclasse:

inserisci qui la descrizione dell'immagine

Supponiamo che SplitUpByDelimiter()sia responsabile della restituzione di un array in modo tale che ogni elemento dell'array sia un token. Inoltre, diciamo solo che GetNextToken()è semplicemente un iteratore su questo vettore. Quindi il tuo test pubblico potrebbe apparire così:

TEST_THAT(Tokenizer, canParseSpaceDelimtedTokens)
{
    input_string = "1 2 test bar"
    tokenizer = Tokenizer(input_string);

    ASSERT tokenizer.GetNextToken() IS "1";
    ASSERT tokenizer.GetNextToken() IS "2";
    ASSERT tokenizer.GetNextToken() IS "test";
    ASSERT tokenizer.GetNextToken() IS "bar";
    ASSERT tokenizer.HasMoreTokens() IS false;
}

Facciamo finta di avere quello che Michael Feather chiama uno strumento a tentoni . Questo è uno strumento che ti consente di toccare le parti private di altre persone. Un esempio è FRIEND_TESTda googletest o riflessione se la lingua lo supporta.

TEST_THAT(TokenizerTest, canGenerateSpaceDelimtedTokens)
{
    input_string = "1 2 test bar"
    tokenizer = Tokenizer(input_string);
    result_array = tokenizer.SplitUpByDelimiter(" ");

    ASSERT result.size() IS 4;
    ASSERT result[0] IS "1";
    ASSERT result[1] IS "2";
    ASSERT result[2] IS "test";
    ASSERT result[3] IS "bar";
}

Bene, ora diciamo che i requisiti cambiano e la tokenizzazione diventa molto più complessa. Decidi che un delimitatore di stringa semplice non è sufficiente e ti serve unDelimiter classe per gestire il lavoro. Naturalmente, ci si aspetta che un test si interrompa, ma quel dolore aumenta quando si testano funzioni private.

Quando possono essere appropriati i test sui metodi privati?

Nel software non esiste "taglia unica". A volte va bene (e in realtà l'ideale) "infrangere le regole". Consiglio vivamente di non testare la funzionalità privata quando è possibile. Ci sono due situazioni principali quando penso che vada bene:

  1. Ho lavorato a lungo con i sistemi legacy (motivo per cui sono un grande fan di Michael Feathers), e posso tranquillamente dire che a volte è semplicemente più sicuro testare solo la funzionalità privata. Può essere particolarmente utile per ottenere "test di caratterizzazione" nella baseline.

  2. Sei di fretta e devi fare la cosa più veloce possibile per qui e ora. A lungo termine, non si desidera testare metodi privati. Ma dirò che di solito ci vuole un po 'di tempo per refactoring per affrontare i problemi di progettazione. E a volte devi spedire in una settimana. Va bene: fai il veloce e sporco e prova i metodi privati ​​usando uno strumento di brancolio se è quello che pensi sia il modo più veloce e affidabile per fare il lavoro. Ma capisci che quello che hai fatto è stato non ottimale nel lungo periodo, e per favore considera di tornarci (o, se è stato dimenticato ma lo vedi in seguito, risolvilo).

Probabilmente ci sono altre situazioni in cui va bene. Se pensi che vada bene e hai una buona giustificazione, allora fallo. Nessuno ti sta fermando. Basta essere consapevoli dei potenziali costi.

La scusa del TDD

A parte questo, non mi piacciono davvero le persone che usano TDD come scusa per testare metodi privati. Pratico TDD e non credo che TDD ti costringa a farlo. È possibile scrivere prima il test (per l'interfaccia pubblica) e quindi scrivere il codice per soddisfare tale interfaccia. A volte scrivo un test per un'interfaccia pubblica e lo soddisferò anche scrivendo uno o due metodi privati ​​più piccoli (ma non collaudo direttamente i metodi privati, ma so che funzionano o il mio test pubblico fallirebbe ). Se ho bisogno di testare casi limite di quel metodo privato, scriverò un sacco di test che li colpiranno attraverso la mia interfaccia pubblica.Se non riesci a capire come colpire i casi limite, questo è un segnale forte che devi rifattorizzare in piccoli componenti ognuno con i propri metodi pubblici. È un segno che le tue funzioni private stanno facendo troppo e al di fuori dell'ambito della classe .

Inoltre, a volte trovo che scrivo un test che è troppo grande per essere morso al momento, e quindi penso "eh tornerò a quel test più tardi quando avrò più di un'API con cui lavorare" (I lo commenterò e lo terrò nella parte posteriore della mia mente). È qui che molti sviluppatori che ho incontrato inizieranno a scrivere test per la loro funzionalità privata, usando TDD come capro espiatorio. Dicono "oh, beh, ho bisogno di qualche altro test, ma per scrivere quel test, avrò bisogno di questi metodi privati. Pertanto, dal momento che non posso scrivere alcun codice di produzione senza scrivere un test, ho bisogno di scrivere un test per un metodo privato ". Ma quello che devono davvero fare è il refactoring in componenti più piccoli e riutilizzabili invece di aggiungere / testare un mucchio di metodi privati ​​nella loro classe attuale.

Nota:

Ho risposto a una domanda simile sul test di metodi privati ​​utilizzando GoogleTest qualche tempo fa. Ho principalmente modificato quella risposta per essere più agnostico della lingua qui.

PS Ecco la lezione pertinente sulle lezioni di iceberg e gli strumenti per tentare di Michael Feathers: https://www.youtube.com/watch?v=4cVZvoFGJTU


Il problema che ho con l'elenco "potresti potenzialmente riutilizzare queste classi in altre parti del tuo sistema" come vantaggio, è che a volte il motivo per cui segnare una funzione è privato perché non voglio che venga usato da altre parti di il sistema. Questo è un problema specifico della lingua: idealmente, sarebbe privato di un "modulo", ma se la lingua non lo supporta (ad esempio PHP), la mia classe rappresenta il modulo, non l'unità: i metodi privati ​​sono codice riutilizzabile con i propri contratti, ma devono essere riutilizzati solo all'interno di quella classe.
IMSoP,

Capisco quello che stai dicendo, ma mi piace il modo in cui la comunità Python gestisce questo problema. Se chiami il membro "privato" in questione con un lead _, segnala "hey, questo è" privato ". Puoi usarlo, ma divulgazione completa, non è stato progettato per il riutilizzo e dovresti usarlo solo se davvero sai cosa stai facendo ". Potresti adottare lo stesso approccio in qualsiasi lingua: rendere pubblici quei membri, ma contrassegnarli con un vantaggio _. O forse quelle funzioni dovrebbero essere private e testate semplicemente attraverso un'interfaccia pubblica (vedi la risposta per maggiori dettagli). Caso per caso, nessuna regola generale
Matt Messersmith il

26

Penso che sia meglio testare semplicemente l'interfaccia pubblica di un oggetto. Dal punto di vista del mondo esterno, conta solo il comportamento dell'interfaccia pubblica e questo è ciò a cui devono essere rivolti i test unitari.

Dopo aver scritto alcuni test unitari solidi per un oggetto, non è necessario tornare indietro e modificarli solo perché l'implementazione dietro l'interfaccia è cambiata. In questa situazione, hai rovinato la coerenza del test dell'unità.


21

Se il tuo metodo privato non viene testato chiamando i tuoi metodi pubblici, cosa sta facendo? Sto parlando privato non protetto o amico.


3
Grazie. Questo è un commento sorprendentemente sottovalutato e soprattutto ancora rilevante, anche dopo quasi 8 anni da quando è stato scritto.
Sauronlord,

1
Con lo stesso ragionamento si potrebbe sostenere di testare il software solo dall'interfaccia utente (test a livello di sistema), perché in qualche modo ogni funzione nel software verrebbe eseguita in qualche modo da lì.
Dirk Herrmann,

18

Se il metodo privato è ben definito (cioè ha una funzione che è testabile e non è destinata a cambiare nel tempo), allora sì. Metto alla prova tutto ciò che è testabile dove ha senso.

Ad esempio, una libreria di crittografia potrebbe nascondere il fatto che esegue la crittografia a blocchi con un metodo privato che crittografa solo 8 byte alla volta. Scriverei un unit test per questo - non è destinato a cambiare, anche se è nascosto, e se si rompe (a causa di futuri miglioramenti delle prestazioni, ad esempio), allora voglio sapere che è la funzione privata che si è rotta, non solo quella delle funzioni pubbliche si è rotta.

Accelera il debug in seguito.

-Adamo


1
In questo caso, non avrebbe senso spostare quel metodo privato in un'altra classe, quindi renderlo pubblico o pubblico statico?
Programmatore fuorilegge,

+1 Se non testate le funzioni dei vostri membri privati ​​e il vostro test dell'interfaccia pubblica fallisce, tutto ciò che otterrete è un risultato equivalente a qualcosa che non funziona senza alcuna idea di cosa sia quel qualcosa.
Olumide,

12

Se stai sviluppando test driven (TDD), testerai i tuoi metodi privati.



4
Non è vero, si verificano i metodi pubblici e una volta superati i test, si estrae il codice nei metodi pubblici in metodi privati ​​durante la fase di "pulizia". Testare metodi privati ​​è una cattiva idea perché rende più difficile cambiare l'implementazione (cosa succede se un giorno vuoi cambiare il modo in cui fai qualcosa, dovresti essere in grado di cambiarlo ed eseguire tutti i tuoi test e se il tuo nuovo modo di fare il cosa corretta dovrebbero passare, non vorrei cambiare tutti i miei test privati ​​per questo).
Tesseract,

1
@Tesseract, se potessi votare il tuo commento più di una volta lo farei. "... dovresti essere in grado di cambiarlo ed eseguire tutti i tuoi test e se il tuo nuovo modo di fare la cosa è corretto dovrebbero passare" QUELLO è uno dei maggiori vantaggi dei test unitari. Ti permettono di refactoring con sicurezza. Puoi cambiare completamente il funzionamento privato interno della tua classe e (senza riscrivere tutti i tuoi test unitari) hai la certezza di non aver rotto nulla perché tutti i tuoi test (esistenti) (sulla tua interfaccia pubblica) continuano a passare.
Lee,

Non sono d'accordo, vedi la mia risposta di seguito
Matt Messersmith,

11

Non sono un esperto in questo campo, ma i test unitari dovrebbero testare il comportamento, non l'implementazione. I metodi privati ​​fanno parte rigorosamente dell'implementazione, quindi IMHO non dovrebbe essere testato.


Dove viene testata l'implementazione? Se alcune funzionalità utilizzano la memorizzazione nella cache, si tratta di un dettaglio di implementazione e la memorizzazione nella cache non viene testata?
Dirk Herrmann,

11

Testiamo metodi privati ​​per deduzione, intendo che cerchiamo una copertura totale dei test di classe di almeno il 95%, ma i nostri test chiamano solo metodi pubblici o interni. Per ottenere la copertura, dobbiamo effettuare più chiamate al pubblico / interni in base ai diversi scenari che possono verificarsi. Questo rende i nostri test più intenzionali riguardo allo scopo del codice che stanno testando.

La risposta di Trumpi al post che hai collegato è la migliore.


9

I test unitari credo siano per testare metodi pubblici. I tuoi metodi pubblici usano i tuoi metodi privati, quindi indirettamente vengono anche testati.


7

Ho escogitato questo problema per un po ', soprattutto con il tentativo di mettere mano al TDD.

Mi sono imbattuto in due post che penso affrontino abbastanza bene questo problema nel caso del TDD.

  1. Test di metodi privati, TDD e refactoring test-driven
  2. Lo sviluppo guidato dai test non sta testando

In sintesi:

  • Quando si usano tecniche di sviluppo (design) basate su test, i metodi privati ​​dovrebbero sorgere solo durante il processo di ricopertura di codice già funzionante e testato.

  • Per la natura stessa del processo, qualsiasi piccola funzionalità di implementazione semplice estratta da una funzione accuratamente testata sarà autotestata (ovvero copertura test indiretto).

A me sembra abbastanza chiaro che nella parte iniziale della codifica la maggior parte dei metodi avrà funzioni di livello superiore perché incapsulano / descrivono il progetto.

Pertanto, questi metodi saranno pubblici e testarli sarà abbastanza facile.

I metodi privati ​​arriveranno più tardi una volta che tutto funzionerà bene e stiamo facendo il factoring per motivi di leggibilità e pulizia .


6

Come citato sopra, "Se non collaudi i tuoi metodi privati, come fai a sapere che non si romperanno?"

Questo è un grosso problema. Uno dei punti principali dei test unitari è sapere dove, quando e come qualcosa si è rotto al più presto. Diminuendo così una notevole quantità di sviluppo e sforzo di controllo qualità. Se tutto ciò che viene testato è il pubblico, allora non hai una copertura e una delineazione onesta degli interni della classe.

Ho trovato uno dei modi migliori per farlo è semplicemente aggiungere il riferimento al test al progetto e mettere i test in una classe parallela ai metodi privati. Inserire la logica di compilazione appropriata in modo che i test non vengano integrati nel progetto finale.

Quindi hai tutti i vantaggi di avere questi metodi testati e puoi trovare problemi in pochi secondi rispetto a minuti o ore.

Quindi, in sintesi, sì, unit test i tuoi metodi privati.


2
Non sono d'accordo. "Se non collaudi i tuoi metodi privati, come fai a sapere che non si romperanno?" : Lo so perché se i miei metodi privati ​​sono rotti, i test che testano i miei metodi pubblici che si basano su quei metodi privati ​​falliranno. Non voglio cambiare i miei test ogni volta che cambio idea su come implementare i metodi pubblici. Penso anche che l'interesse principale dei test unitari non sia sapere in particolare quale riga di codice sia difettosa, piuttosto ti permette di essere più o meno fiducioso di non aver rotto nulla quando hai apportato modifiche (ai metodi privati).
Tesseract,

6

Non dovresti . Se i tuoi metodi privati ​​hanno una complessità sufficiente che deve essere testata, dovresti metterli in un'altra classe. Mantenere alta la coesione , una classe dovrebbe avere un solo scopo. L'interfaccia pubblica di classe dovrebbe essere sufficiente.


3

Se non collaudi i tuoi metodi privati, come fai a sapere che non si romperanno?


19
Scrivendo attraverso test dei tuoi metodi pubblici.
scubabbl,

3
Questi metodi privati ​​sono presumibilmente chiamati dai metodi pubblici della classe. Quindi basta testare i metodi pubblici che chiamano i metodi privati.
jop

1
Se i tuoi metodi pubblici funzionano correttamente, ovviamente i metodi privati ​​a cui accedono funzionano correttamente.
17 del 26

Se i test dei tuoi metodi pubblici falliscono, sai immediatamente che qualcosa non è corretto a un livello inferiore nel tuo oggetto / componente / ecc.
Rob,

3
È davvero bello, tuttavia, sapere che è una funzione interna e non solo le funzioni esterne che si sono interrotte (o viceversa che le funzioni interne vanno bene e puoi concentrarti sull'esterno).
Adam Davis,

2

Ovviamente dipende dalla lingua. In passato con c ++, ho dichiarato che la classe testing era una classe amico. Sfortunatamente, questo richiede che il codice di produzione sia a conoscenza della classe di test.


5
La parola chiave amico mi rende triste.
Rob,

Questo non è un problema se la classe di test è implementata in un altro progetto. L'importante è che il codice di produzione non faccia riferimento alla classe di test.
Olumide,

2

Comprendo il punto di vista in cui i metodi privati ​​sono considerati come dettagli di implementazione e quindi non devono essere testati. E rispetterei questa regola se dovessimo svilupparci al di fuori dell'oggetto. Ma noi, siamo una specie di sviluppatori con restrizioni che si stanno sviluppando solo al di fuori degli oggetti, chiamando solo i loro metodi pubblici? O stiamo davvero sviluppando quell'oggetto? Dato che non siamo tenuti a programmare oggetti esterni, probabilmente dovremo chiamare quei metodi privati ​​in nuovi metodi pubblici che stiamo sviluppando. Non sarebbe bello sapere che il metodo privato resiste contro ogni previsione?

So che alcune persone potrebbero rispondere che se stiamo sviluppando un altro metodo pubblico in quell'oggetto, questo dovrebbe essere testato e il gioco è fatto (il metodo privato potrebbe continuare a vivere senza test). Ciò vale anche per qualsiasi metodo pubblico di un oggetto: quando si sviluppa un'app Web, tutti i metodi pubblici di un oggetto vengono chiamati dai metodi dei controller e quindi potrebbero essere considerati come dettagli di implementazione per i controller.

Allora perché siamo oggetti di unit test? Perché è davvero difficile, per non dire impossibile, essere sicuri che stiamo testando i metodi dei controller con l'input appropriato che attiverà tutti i rami del codice sottostante. In altre parole, più siamo in alto nello stack, più è difficile testare tutto il comportamento. E così è lo stesso per i metodi privati.

Per me la frontiera tra metodi pubblici e privati ​​è un criterio psicologico quando si tratta di prove. I criteri che contano di più per me sono:

  • il metodo viene chiamato più volte da luoghi diversi?
  • il metodo è abbastanza sofisticato da richiedere prove?

1

Se trovo che il metodo privato sia enorme o complesso o abbastanza importante da richiedere i propri test, lo inserisco in un'altra classe e lo pubblico (oggetto metodo). Quindi posso facilmente testare il metodo precedentemente privato ma ora pubblico che ora vive sulla sua stessa classe.


1

Non capisco mai il concetto di Unit Test ma ora so qual è l'obiettivo.

Un test unitario non è un test completo . Quindi, non è un sostituto del QA e del test manuale. Il concetto di TDD in questo aspetto è sbagliato poiché non è possibile testare tutto, inclusi i metodi privati ​​ma anche i metodi che utilizzano risorse (in particolare risorse che non abbiamo controllo). TDD sta basando tutta la sua qualità è qualcosa che non è stato possibile raggiungere.

Un test unitario è più un test pivot Contrassegni un pivot arbitrario e il risultato di pivot dovrebbe rimanere lo stesso.


1

Pubblico vs privato non è una distinzione utile per ciò che le API chiamano dai tuoi test, né è metodo vs. classe. La maggior parte delle unità testabili sono visibili in un contesto, ma nascoste in altri.

Ciò che conta è la copertura e i costi. Devi minimizzare i costi mentre raggiungi gli obiettivi di copertura del tuo progetto (linea, ramo, percorso, blocco, metodo, classe, classe di equivalenza, caso d'uso ... qualunque cosa il team decida).

Quindi utilizzare gli strumenti per garantire la copertura e progettare i test in modo da ridurre i costi (a breve e lungo termine ).

Non rendere i test più costosi del necessario. Se è più economico testare solo i punti di accesso pubblici, fallo. Se è più economico testare metodi privati, fallo.

Man mano che acquisirai maggiore esperienza, sarai in grado di prevedere meglio quando vale la pena eseguire il refactoring per evitare costi a lungo termine per la manutenzione dei test.


0

Se il metodo è abbastanza significativo / abbastanza complesso, di solito lo renderò "protetto" e lo testerò. Alcuni metodi saranno lasciati privati ​​e testati implicitamente come parte dei test unitari per i metodi pubblici / protetti.


1
@VisibleForTesting è un'annotazione per questo. Non rilasserei l'incapsulamento per i test, piuttosto usare dp4j.com
simpatico

0

Vedo che molte persone sono nella stessa linea di pensiero: test a livello pubblico. ma non è quello che fa il nostro team QA? Testano input e output previsti. Se come sviluppatori testiamo solo i metodi pubblici, stiamo semplicemente rifacendo il lavoro di controllo qualità e non aggiungendo alcun valore mediante "unit test".


La tendenza attuale è quella di ridurre o non avere un team di controllo qualità. Questi test unitari diventano test automatici eseguiti ogni volta che un ingegnere invia il codice sul ramo principale. Anche con il controllo qualità, non è possibile testare l'intera applicazione tanto rapidamente quanto i test automatici.
Patrick Desjardins,

0

La risposta a "Devo testare metodi privati?" è "....... a volte". In genere dovresti testare l'interfaccia delle tue classi.

  • Uno dei motivi è perché non è necessaria una doppia copertura per una funzione.
  • Un altro motivo è che se modifichi metodi privati, dovrai aggiornare ogni test per loro, anche se l'interfaccia del tuo oggetto non è cambiata affatto.

Ecco un esempio:

class Thing
  def some_string
    one + two
  end

  private 

  def one
    'aaaa'
  end

  def two
    'bbbb'
  end

end


class RefactoredThing
def some_string
    one + one_a + two + two_b
  end

  private 

  def one
    'aa'
  end

  def one_a
    'aa'
  end

  def two
    'bb'
  end

  def two_b
    'bb'
  end
end

In RefactoredThingora avete 5 prove, 2 delle quali si doveva aggiornare per il refactoring, ma la funzionalità del vostro oggetto in realtà non è cambiato. Quindi diciamo che le cose sono più complesse di così e hai qualche metodo che definisce l'ordine dell'output come:

def some_string_positioner
  if some case
  elsif other case
  elsif other case
  elsif other case
  else one more case
  end
end

Questo non dovrebbe essere eseguito da un utente esterno, ma la tua classe di incapsulamento potrebbe essere troppo pesante per far girare ancora e ancora quella logica attraverso di essa. In questo caso, forse preferiresti estrarlo in una classe separata, dare a quella classe un'interfaccia e testarla contro di essa.

E infine, diciamo che il tuo oggetto principale è super pesante, e il metodo è piuttosto piccolo e devi davvero assicurarti che l'output sia corretto. Stai pensando "Devo testare questo metodo privato!". Forse potresti rendere più leggero il tuo oggetto passando parte del lavoro pesante come parametro di inizializzazione? Quindi puoi passare qualcosa di più leggero e metterti alla prova.


0

No Non dovresti testare i metodi privati perché? e inoltre il popolare framework di derisione come Mockito non fornisce supporto per testare metodi privati.


0

Un punto principale è

Se testiamo per garantire la correttezza della logica e un metodo privato sta portando una logica, dovremmo testarla. No? Allora perché lo salteremo?

Scrivere test basati sulla visibilità dei metodi è un'idea del tutto irrilevante.

al contrario

D'altra parte, chiamare un metodo privato al di fuori della classe originale è un problema principale. E ci sono anche delle limitazioni a deridere un metodo privato in alcuni strumenti di derisione. (Es .: Mockito )

Sebbene ci siano alcuni strumenti come Power Mock che lo supporta, si tratta di un'operazione pericolosa. Il motivo è che è necessario hackerare la JVM per raggiungere questo obiettivo.

È possibile risolvere un problema (se si desidera scrivere casi di test per metodi privati)

Dichiara quei metodi privati come protetti . Ma potrebbe non essere conveniente per diverse situazioni.


0

Non si tratta solo di metodi o funzioni pubbliche o private, si tratta di dettagli di implementazione. Le funzioni private sono solo un aspetto dei dettagli di implementazione.

Il test unitario, dopo tutto, è un approccio di test a scatola bianca. Ad esempio, chiunque utilizzi l'analisi della copertura per identificare parti del codice che sono state finora trascurate nei test, passa ai dettagli di implementazione.

A) Sì, dovresti testare i dettagli dell'implementazione:

Pensa a una funzione di ordinamento che per motivi di prestazioni utilizza un'implementazione privata di BubbleSort se ci sono fino a 10 elementi e un'implementazione privata di un approccio di ordinamento diverso (diciamo, heapsort) se ci sono più di 10 elementi. L'API pubblica è quella di una funzione di ordinamento. La tua suite di test, tuttavia, sfrutta meglio la consapevolezza che esistono effettivamente due algoritmi di ordinamento utilizzati.

In questo esempio, sicuramente, potresti eseguire i test sull'API pubblica. Ciò richiederebbe tuttavia un numero di casi di test che eseguono la funzione di ordinamento con più di 10 elementi, in modo tale che l'algoritmo heapsort sia sufficientemente ben testato. L'esistenza di tali casi di test da soli indica che la suite di test è collegata ai dettagli di implementazione della funzione.

Se i dettagli di implementazione della funzione di ordinamento cambiano, forse nel modo in cui viene spostato il limite tra i due algoritmi di ordinamento o che heapsort viene sostituito da mergesort o altro: i test esistenti continueranno a funzionare. Tuttavia, il loro valore è quindi discutibile e probabilmente devono essere rielaborati per testare meglio la funzione di ordinamento modificata. In altre parole, ci sarà uno sforzo di manutenzione nonostante il fatto che i test fossero sull'API pubblica.

B) Come testare i dettagli di implementazione

Uno dei motivi per cui molte persone sostengono che non si dovrebbero testare funzioni private o dettagli di implementazione è che i dettagli di implementazione hanno maggiori probabilità di cambiare. Questa maggiore probabilità di cambiamento è almeno uno dei motivi per nascondere i dettagli di implementazione dietro le interfacce.

Ora supponiamo che l'implementazione dietro l'interfaccia contenga parti private più grandi per le quali i singoli test sull'interfaccia interna potrebbero essere un'opzione. Alcuni sostengono che queste parti non dovrebbero essere testate quando private, dovrebbero essere trasformate in qualcosa di pubblico. Una volta pubblico, il test unitario di quel codice sarebbe OK.

Questo è interessante: mentre l'interfaccia era interna, era probabile che cambiasse, essendo un dettaglio di implementazione. Prendere la stessa interfaccia, renderla pubblica fa una trasformazione magica, vale a dire trasformarla in un'interfaccia che ha meno probabilità di cambiare. Ovviamente c'è qualche difetto in questa argomentazione.

Tuttavia, c'è qualcosa di vero dietro questo: quando si testano i dettagli dell'implementazione, in particolare utilizzando le interfacce interne, si dovrebbe cercare di utilizzare interfacce che probabilmente rimarranno stabili. Tuttavia, la probabilità che alcune interfacce siano stabili non è semplicemente determinabile in base al fatto che sia pubblica o privata. Nei progetti dal mondo in cui lavoro da qualche tempo, anche le interfacce pubbliche cambiano abbastanza spesso e molte interfacce private sono rimaste intatte per secoli.

Tuttavia, è una buona regola empirica usare la "porta principale prima" (vedi http://xunitpatterns.com/Principles%20of%20Test%20Automation.html ). Ma tieni presente che si chiama "porta d'ingresso prima" e non "solo porta d'ingresso".

C) Riepilogo

Prova anche i dettagli di implementazione. Preferisci test su interfacce stabili (pubbliche o private). Se i dettagli di implementazione cambiano, è necessario rivedere anche i test sull'API pubblica. Trasformare qualcosa di privato in pubblico non cambia magicamente la sua stabilità.


0

Sì, dovresti testare metodi privati, ove possibile. Perché? Per evitare un'esplosione non necessaria dello spazio di stato dei casi di test che alla fine finiscono per testare implicitamente ripetutamente le stesse funzioni private sugli stessi input. Spieghiamo perché con un esempio.

Considera il seguente esempio leggermente inventato. Supponiamo di voler esporre pubblicamente una funzione che accetta 3 numeri interi e restituisce vero se e solo se quei 3 numeri interi sono tutti primi. Potremmo implementarlo in questo modo:

public bool allPrime(int a, int b, int c)
{
  return andAll(isPrime(a), isPrime(b), isPrime(c))
}

private bool andAll(bool... boolArray)
{
  foreach (bool b in boolArray)
  {
    if(b == false) return false;
  }
  return true;
}

private bool isPrime(int x){
  //Implementation to go here. Sorry if you were expecting a prime sieve.
}

Ora, se dovessimo adottare l'approccio rigoroso secondo cui solo le funzioni pubbliche dovrebbero essere testate, ci sarebbe permesso solo testare allPrimee non isPrimeo andAll.

Come tester, potremmo essere interessati a cinque possibilità per ogni argomento: < 0, = 0, = 1, prime > 1, not prime > 1. Ma per essere precisi, dovremmo anche vedere come ogni combinazione di argomenti gioca insieme. Quindi sono 5*5*5= 125 casi di test di cui avremmo bisogno per testare a fondo questa funzione, secondo le nostre intuizioni.

D'altra parte, se ci fosse permesso di testare le funzioni private, potremmo coprire tutto il terreno con meno casi di test. Avremmo bisogno di soli 5 casi di test isPrimeper testare allo stesso livello della nostra intuizione precedente. E con l' ipotesi di piccolo ambito proposta da Daniel Jackson, avremmo solo bisogno di testare la andAllfunzione fino a una piccola lunghezza, ad esempio 3 o 4. Che sarebbe al massimo 16 ulteriori test. Quindi 21 test in totale. Invece di 125. Naturalmente, probabilmente vorremmo eseguire alcuni testallPrime , ma non ci sentiremmo così obbligati a coprire in modo esaustivo tutte le 125 combinazioni di scenari di input di cui ci siamo preoccupati. Solo alcuni percorsi felici.

Un esempio inventato, certo, ma era necessario per una chiara dimostrazione. E il modello si estende al vero software. Le funzioni private sono generalmente i mattoni di livello più basso e quindi vengono spesso combinate insieme per produrre una logica di livello superiore. Significato ai livelli più alti, abbiamo più ripetizioni delle cose di livello inferiore a causa delle varie combinazioni.


Innanzitutto, non devi testare combinazioni del genere con funzioni pure come hai mostrato. Le chiamate a isPrimesono veramente indipendenti, quindi testare ogni combinazione alla cieca è piuttosto inutile. In secondo luogo, contrassegnare una funzione pura chiamata isPrimeprivate viola così tante regole di progettazione che non so nemmeno da dove cominciare. isPrimedovrebbe essere chiaramente una funzione pubblica. Detto questo, capisco quello che stai dicendo indipendentemente da questo esempio estremamente scarso. Tuttavia è costruito fuori la premessa che ci si vuole fare il test combinazione, quando in sistemi software reali questo è raramente una buona idea.
Matt Messersmith,

Matt sì, l'esempio non è l'ideale, te lo darò. Ma il principio dovrebbe essere ovvio.
Colm Bhandal,

La premessa non è esattamente che vorresti fare un test di combinazione. È quello che dovresti, se ti limitassi a testare solo pezzi pubblici del puzzle. Ci sono casi in cui vorresti rendere privata una funzione pura per aderire ai principi di incapsulamento corretti. E questa pura funzione privata potrebbe essere utilizzata da quelle pubbliche. In modo combinato, forse con altre pure funzioni private. In tal caso, seguendo il dogma che non testerai come privato, verrai costretto a fare test di combinazione sulla funzione pubblica piuttosto che a test modulari dei componenti privati.
Colm Bhandal,

0

Puoi anche rendere il tuo metodo pacchetto privato, ovvero predefinito e dovresti essere in grado di testarlo a meno che non sia necessario che sia privato.

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.