By passing an -E option to g++ you can inspect the code after preprocessing. Example code using the GTest library:
#include <gtest/gtest.h>
TEST(testcase, mytest) {
// Code
}
int main() {
return RUN_ALL_TESTS();
}
And compiling it with:
g++ -E -Igtest_include_path example.cpp -oexample_preprocessed.cpp
The TEST macro expanded to:
class testcase_mytest_Test : public ::testing::Test {
public:
testcase_mytest_Test() {}
private:
virtual void TestBody();
static ::testing::TestInfo* const test_info_ __attribute__ ((unused));
testcase_mytest_Test(testcase_mytest_Test const &);
void operator=(testcase_mytest_Test const &);
};
::testing::TestInfo* const testcase_mytest_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "testcase", "mytest", __null, __null, ::testing::internal::CodeLocation("cpp_test.c", 3), (::testing::internal::GetTestTypeId()), ::testing::Test::SetUpTestCase, ::testing::Test::TearDownTestCase, new ::testing::internal::TestFactoryImpl< testcase_mytest_Test>);
void testcase_mytest_Test::TestBody() {
// Code
}
And RUN_ALL_TESTS() is not a macro:
inline int RUN_ALL_TESTS() {
return ::testing::UnitTest::GetInstance()->Run();
}
So it's in fact a complicated chain of preprocessor macros that make up a class out of your test case, and does all sorts of things to link it to the machinery that runs it.
Obviously you are not going to be able to do it like this in a C99 project, as GTest is a C++ library, and it heavily relies on C++ features to do the job.
If you wish to understand how it works fully, you should check out the GTest code in its repository: https://github.com/google/googletest