Test del comportamento della classe astratta

3

Attualmente sto rifattorizzando un progetto esistente, che è stato creato senza TDD. Esiste una gerarchia di classi con una classe base astratta e due sottoclassi. Nel design originale, queste classi erano per lo più solo possessori di dati senza molto comportamento. Ho identificato alcune funzionalità che dovrebbero essere implementate nella classe base, e mi piacerebbe scrivere test per questa funzionalità ora. Ma dal momento che la classe è astratta, non posso istanziarla (ovviamente).

Nota: la funzionalità che vorrei testare non richiama alcun metodo pure virtual .

class Base {}; // Is abstract

TEST(BaseTest, doesSomethingAmazing) {
    Base aBase; // <-------- Not possible!!! 
    ASSERT_THAT(aBase.amazeMe(), Eq(AMAZING_RESULT));
}

Modifica: per chiarire alcune cose:

  • L'ereditarietà ha effettivamente senso in questa situazione - entrambe le sottoclassi mappano a concetti specifici del dominio e il polimorfismo aiuta a mantenere pulito il codice circostante
  • Esiste un comportamento che verrà utilizzato in entrambe le sottoclassi e che richiede dati comuni a entrambe le classi. Quindi penso che abbia senso metterlo in una super classe comune.

Posso pensare a diverse soluzioni possibili, ma nessuna mi sembra ottimale:

  • Aggiungi una sottoclasse al codice di test, che implementa tutte le funzioni pure virtual . Lato negativo: difficile nominare la sottoclasse in modo conciso, comprendere i test diventa più difficile
  • Crea un'istanza di un oggetto della sottoclasse. Lato negativo: rende i test abbastanza confusi
  • Aggiungi implementazioni vuote alla classe base. Lato negativo: la classe non è più astratta

Tendo all'opzione 3, per rendere i test più chiari possibile, ma non ne sono veramente soddisfatto. C'è un modo migliore di cui non sono a conoscenza?

    
posta lethal-guitar 14.04.2014 - 15:30
fonte

2 risposte

2

Finché la funzionalità che vorresti testare non invoca metodi virtuali puri e non viene sovrascritta nelle sottoclassi, rimango con il tuo numero di punto elenco 1, creando una sottoclasse specifica per il test. Puoi chiamarlo Sub<ClassName> o qualsiasi nome generico che rifletta il fatto che la sottoclasse stessa non è importante.

Ora se ciò che vuoi testare può essere modificato in qualsiasi modo dalla classe concreta finale, potresti prendere in considerazione questo:

Non so se c'è un equivalente nel framework di test C ++ che stai usando, ma NUnit (e credo JUnit) ti consente di implementare il Test astratto modello.

In breve, hai

  • Una classe di test di base astratta. Contiene un metodo di fabbrica astratto utilizzato per generare l'oggetto in prova e i metodi di prova di per sé. Questi metodi verificano le cose che devono rimanere vere indipendentemente dall'oggetto concreto sottostante.

  • Come molte classi di test derivate quante sono le derivate della classe astratta in prova. Devi semplicemente implementare qui il metodo factory per restituire un'istanza della classe derivata.

Quando il test runner vede una classe di test derivata, eseguirà automaticamente tutti i metodi di test ereditati dalla classe di test di base rispetto all'oggetto generato dal metodo factory.

    
risposta data 17.04.2014 - 12:34
fonte
1

Potresti fare quanto segue:

  • crea una classe base astratta con solo metodi virtuali puri, ad esempio AmazingObjectInterface ;
  • aggiungi una sottoclasse chiamata BasicAmazingObject che definisce i metodi non virtuali che devi testare;
  • infine, le tue 2 sottoclassi originali diventano sottoclassi di BasicAmazingObject .

Ciò consente di separare ciò che varia e testare ciò che è necessario in modo appropriato. Ovviamente, si introdurrebbe quindi un'altra classe, ma questo è il prezzo da pagare per la mancanza di supporto all'interfaccia (in senso java) in C ++.

    
risposta data 17.04.2014 - 11:23
fonte

Leggi altre domande sui tag