Configurazione oggetto per il test: manipolare l'oggetto o utilizzare le sue funzioni?

2

Supponendo di avere la seguente (molto semplice) classe

class Foo
{
  public:
    void setAB(int a, int b) { m_a = a; m_b = b; m_aIsBigger = a > b; }
    int getA() const { return m_a; }
    int getB() const { return m_b; }
    bool isABigger() const { return m_aIsBigger; }

  protected:
    int m_a;
    int m_b;
    bool m_aIsBigger;
}

e voglio metterlo sotto test automatizzato (ad esempio, unit test, modulo test). Posso vedere due possibili modi per testare le funzioni:

O posso usare le sue funzioni per testarlo, cioè invocare setAB() e quindi verificare che getA() , getB() e isABigger() restituiscano i valori previsti. Oppure potrei impostare direttamente m_a (ad esempio sottoclassando Foo), quindi richiamare getA() e verificare che il valore sia identico a quello impostato.

Il primo metodo sembra più "organico", poiché usa la funzionalità incorporata della classe ed è indipendente dalla sua implementazione (ad esempio, nel caso mi rendo conto che potrei calcolare "a > b" al volo per isABigger() invece di usare m_aIsBigger ). Tuttavia sembra violare il principio del "test solo una cosa" per i test (anche se separo getA() , getB() e isABigger() nei loro casi di test, non posso testarli separatamente da setAB() ; Prova setAB() senza invocare getA() e getB() )

Se sottoclassi Foo posso testare ciascuna funzione individualmente, ma è un po 'sbagliato manipolare la classe' interna in questo modo, ed è molto più fragile (cambiare isABigger() per calcolare il risultato al volo richiederebbe una modifica in il test, anche se sembra non dovrebbe).

Quindi la domanda è: qual è il modo migliore per impostare un oggetto da testare o è semplicemente una questione di preferenza personale?

    
posta CharonX 06.04.2018 - 11:55
fonte

2 risposte

4

La tua intuizione è corretta: testare attraverso i metodi pubblici è meglio. "Testare solo una cosa" non significa solo esercitare un solo metodo, ma significa che un test dovrebbe solo verificare un singolo "comportamento".

La sottoclasse di Foo per impostare manualmente i campi è un antipattern, poiché questo accopperebbe il test ai dettagli di implementazione di Foo. Vuoi testare il comportamento di Foo senza bloccare le parti interne.

    
risposta data 06.04.2018 - 12:07
fonte
1

I metodi Accessor sono spesso usati per qualcosa di più che semplicemente assegnare o recuperare un valore. Si consiglia di bloccare un valore float solo al dominio positivo prima di assegnarlo. Oppure esegui una trasformazione quando recuperi un valore perché ha una memoria di memoria più piccola quando memorizzato nella classe (e può assumere il costo di trasformazione in termini di prestazioni). Pertanto, alterare direttamente i dati interni potrebbe accidentalmente avere effetti collaterali se il resto della classe non è preparato per dati non validi nei suoi attributi.

Inoltre, i test dovrebbero essere centrati nell'interfaccia pubblica della classe (puoi testare l'interfaccia privata / protetta solo per assicurarti che il riutilizzo di quei metodi anche in altre parti sia sicuro, ma questa è un'altra storia). Il punto qui è che nessun altro client / dovrebbe accedere agli attributi protetti quando esiste già un'interfaccia pubblica (i suoi accessor) per esso. Quindi testare gli accessors dovrebbe essere almeno altrettanto sicuro quanto testare gli attributi stessi.

    
risposta data 06.04.2018 - 19:11
fonte

Leggi altre domande sui tag