mercoledì 11 gennaio 2012

Unit Test in C++ con MiniCppUnit

Continua la carrellata di tool utilissimi e semplici da usare per arricchire la nostra cassetta degli attrezzi C++.

Dopo aver visto quanto sia facile fare parsing ed editing di documenti xml con TinyXML, vi segnalo una libreria molto pratica per lo unit testing: MiniCppUnit.

MiniCppUnit condivide con TinyXML l'approccio lib-free, ovvero non la trovate compilata come libreria da includere nel vostro progetto, ma come due semplici file (un header e la relativa implementazione) da aggiungere e compilare assieme al vostro codice (C++ standard, STL e nessuna dipendenza esterna... good!).

L'utilizzo segue la logica del più noto JUnit per Java, di cui esiste il porting C++, CppUnit, del quale il nostro MiniCppUnit non è altro che la versione semplificata. Per chi non conoscesse JUnit (o NUnit per .Net) facciamo un rapidissimo ripassino:

  • si crea un progetto per il test di un altro progetto/classe/sottosistema
  • si creano una o più classi speciali marcate come TestFixture e contenenti metodi marcati come Test
  • si scrivono test basati sull'utilizzo di asserzioni
  • si danno tutte le TestFixture in pasto ad un motore che le esegue e riporta i risultati (successo/fallimento)

NB: per info più precise sullo Unit Testing si veda la Rete.


Cosa mi fa testare?


MiniCppUnit permette di verificare vari tipi di asserzioni:

ASSERT(3==1+2);
ASSERT_MESSAGE( 2==1+1, "2 should be 1 plus 1 ");
ASSERT_EQUALS(expected, result);
ASSERT_EQUALS_EPSILON(expected, result, 0.05);

...e pure una macro sul controllo delle eccezioni!

Sono poche e semplici, ma sicuramente l'essenziale per mettere in piedi un sistema di testing più evoluto di un main con tanti cout, o peggio ancora di no tests at all.

Come lo lancio?


Il main è quanto di più banale possa esistere:

#include "MiniCppUnit.hxx"

int main()
{
   return TestFixtureFactory::theInstance().runTests() ? 0 : -1;
} 

Il singleton TestFixtureFactory va in automatico a prendersi tutte le classi TestFixture (registrate tramite apposita macro REGISTER_FIXTURE()) e le esegue, riportando il risultato in una schermata di console. Semplice, pratico e pulito.

Il pacchetto che scaricate, oltre ai due file da includere nel vostro progetto, contiene anche altri due file con un esempio d'uso, da cui ho preso il codice d'esempio. Sono più che sufficienti a togliere ogni dubbio residuo sull'utilizzo, ma se servisse altro c'è pure una ottima documentazione doxygen online.

Concludendo


Niente scuse, quindi: il vostro prossimo progetto C++ godrà di unit testing, perché if it ain't tested, it's broken!