Punti di ingresso multipli nel progetto

4

La mia domanda è legata al C ++ ma in realtà proviene da Java.

Quando stavo programmando Java avevo più classi, che erano derivate da una classe base "Test". Il loro scopo era quello di testare le cose - eseguire test (unit test / non unit test).

Per eseguire un test, avevo un public static void main in ogni classe. Quindi la questione di eseguire un test del genere era fare clic su esegui in Eclipse / Netbeans , qualunque sia l'IDE corretto.

So che questa domanda potrebbe dipendere da IDE, in realtà si riduce a un makefile, ma è possibile mantenere una struttura simile negli IDE C ++?

In realtà la mia domanda è: come gestisci i test?

Metti un enorme metodo principale con alcune istruzioni switch / enum per eseguire i test o creare configurazioni di compilazione diverse per ciascun test o avere una soluzione diversa?

So che questa domanda non otterrà una risposta semplice, ma sono curioso di sapere come gestirlo in modo da poter scegliere qualcosa per me stesso.

    
posta spectre 08.03.2014 - 20:25
fonte

2 risposte

1

La risposta breve è "non puoi farlo in C o C ++ con la stessa facilità che puoi in Java."

Java ti consente di ottenere un metodo main() in ogni classe, poiché ogni classe è il proprio spazio dei nomi e può, in teoria, essere completamente autonoma. Quando invochi la JVM su una classe, stai dicendo quale spazio dei nomi contiene il main() che vuoi che venga eseguito. Ad esempio, java Foo significa davvero "Esegui Foo.main() ".

Le lingue che compongono gli oggetti nativi non funzionano in questo modo. La maggior parte dei sistemi ha un po 'di codice che viene collegato agli eseguibili ed è responsabile di eseguire un po' di preparazione pre-volo, chiamando main() e passando il int che ritorna al sistema operativo come codice di uscita. (Su molti sistemi Unix, quel codice si trova in un file chiamato crt0.o , o "C runtime zero.") Non esiste un modo semplice per passare una funzione main() alternativa al runtime perché il linker deve cucire tutto questo in precedenza.

Se vuoi ottenere qualcosa di simile in C o C ++, hai un paio di scelte:

Un modo è usare il preprocessore per sovvertire le solite cose che main() fa e chiamare direttamente un metodo se viene definito un simbolo:

class Foo {
  public:
    static void test() { // Your Test Here }
};

int main() {
#ifdef TEST_CLASS
  TEST_CLASS ## ::test();
#else
  // Do whatever main() usually does
#endif
}

Quindi, per fare in modo che funzioni, dovresti definire il tuo IDE TEST_CLASS sul nome della classe di cui desideri eseguire il test, ricompilarlo ed eseguirlo.

L'altro modo consiste nel compilare tutti gli oggetti in una libreria condivisa e aggiungere simboli esportati in C per eseguire i test. Quindi è necessario un piccolo programma che utilizza il caricatore dinamico per pescare il simbolo per il test che si desidera eseguire e chiamarlo. Come faresti questo è molto dipendente dal sistema e non ha alcun fondamento in uno standard, quindi non lo consiglierò né approfondirò su come è stato fatto.

    
risposta data 09.03.2014 - 16:54
fonte
2

Hai già una risposta accettata, ma penso che la risposta sia incompleta (specialmente dal momento che ha detto che non puoi definire più punti di accesso alle applicazioni con la stessa semplicità di java).

Per implementare più punti di ingresso nello stesso codice / modulo con C ++, fai quanto segue:

  • crea un nuovo file cpp per ogni punto di ingresso (ad es. main-app.cpp, io-tests.cpp, db-tests.cpp, network-tests.cpp, ecc.)

  • ogni file dovrebbe definire la sua funzione principale.

  • ogni file dovrebbe avere una destinazione binaria separata nel tuo sistema di build (make file?).

  • costruisci ed esegui obiettivi secondo necessità.

Fondamentalmente è facile come scrivere più funzioni main , ciascuna nel proprio file.

Questa soluzione funziona meglio se la tua funzione main () (nell'esempio sopra, quella definita in "main-app.cpp") è il più sottile possibile.

Una buona implementazione sarebbe simile a questa:

main-app.cpp:

#include <application.hpp>

int main(int, char**) {
    application app(std::cin, std::cout); // run application with std i/o
    return app.run();
}

db-tests.cpp:

#include <database.hpp>    // tested class
#include <unit-tests.hpp>  // unit testing fw

int main(int, char**) {
    database_test_suite suite;
    return suite.run();
}

Non avresti nessun obiettivo che compili entrambi questi file insieme (quindi non avresti nessun errore di linker con più definizioni per main).

    
risposta data 17.03.2014 - 14:11
fonte

Leggi altre domande sui tag