4

My question is related to C++ but it comes from Java actually.

When I was programming Java I had multiple classes, which were derived from a base "Test" class. Their purpose was to test things - run tests (unit tests/not unit tests).

In order to run a test, I had a public static void main in every class. So the matter of running such a test was to click run in Eclipse/Netbeans, whatever good IDE.

I know this question maybe IDE dependent, it actually boils down to a makefiles, but is it possible to maintain a similar structure in C++ IDEs?

Actually my question is: how do you deal with tests?

Do you put a huge main method with some switch/enum based statements to run the tests or make different build configurations for each test, or have different solution to this?

I know this question won't get a straightforward answer, but I'm curious how to deal with it so I can choose something for myself.

  • Is there a particular reason you're not using a unit testing framework that does these things for you in a clean way? – Jeroen Vannevel Mar 8 '14 at 21:06
  • Yes, because It's impossible to unit test OpenGL shaders and nested 3d transforms other than visually. – luke1985 Mar 8 '14 at 21:16
  • @JeroenVannevel: Sometimes it's handy to have a less-formal test jig for use during development. – Blrfl Mar 9 '14 at 15:56
1

The short answer is "you can't do this in C or C++ as easily as you can in Java."

Java lets you get away with having a main() method in every class because each class is its own namespace and can, in theory, be completely self-contained. When you invoke the JVM on a class, you're telling it which namespace contains the main() you want it to run. So, for example, java Foo really means "run Foo.main()."

Languages that compile to native objects don't work that way. Most systems have a bit of code that gets linked into executables and is responsible for doing a bit of pre-flight prep, calling main() and passing the int that it returns back to the operating system as an exit code. (On many Unixy systems, that code is in a file called crt0.o, or "C runtime zero.") There's no simple way to pass in an alternate main() function at runtime because the linker has to sew all of that up beforehand.

If you want to achieve something similar in C or C++, you have a couple of choices:

One way is to use the preprocessor to subvert the usual things main() does and call a method directly if a symbol is defined:

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

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

Then, to make this work, you'd have to have your IDE define TEST_CLASS to the name of the class whose test you'd like to run, recompile and run.

The other way is to compile all of your objects into a shared library and add exported-to-C symbols to run your tests. Then you'd need a small program that uses the dynamic loader to fish out the symbol for the test you want to run and call it. How you'd do this is very system-dependent and has no basis in a standard, so I'm not going to recommend it or elaborate on how it's done.

|improve this answer|||||
  • The thing you are talking about - I've actually done. Created defines separate for each test I wanted to perform. I've found that this is close to how test frameworks do this. – luke1985 Mar 9 '14 at 19:35
2

You already have an accepted answer, but I think the answer is incomplete (especially since it said you can't define multiple application entry points as easily as java).

To implement multiple entry points into the same code/module with C++, you do the following:

  • create a new cpp file for each entry point (i.e. main-app.cpp, io-tests.cpp, db-tests.cpp, network-tests.cpp, etc).

  • each file should define it's own main function.

  • each file should have a separate binary target in your build system (make file?).

  • build and run targets as needed.

Basically it's as easy as writing multiple main functions, each in their own file.

This solution works best if your main() function (in the example above, the one defined in "main-app.cpp") is as thin as possible.

A good implementation would look similar to this:

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();
}

You would have no target that compiles both of these files together (so you would not have any linker error with multiple definitions for main).

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.