如何像junit一样使用cppunit——两条主线

How to use cppunit just like junit --- two mains

我知道 Java 的单元测试非常简单。我们只需要使用 JUnit 和 运行 测试 类 作为 JUnit 测试。

现在我正在使用 C++,我找到了一个测试库:cppunit。

看来我需要 运行 我的测试具有特定功能 main。 但是,一个 cpp 项目只能有一个 main.

我该怎么办?我在做测试和 运行 我的项目时必须切换电源?

What should I do? I have to switch mains when I do my test and when I run my project?

您应该将要测试的代码分离到一个库项目中,该项目可以从您的目标应用程序和单元测试运行器链接。

然后再有两个项目提供 main() 功能:

  • 一个用于目标应用程序,它只是将 main() 实现转发给 MyTargetApp class 成员函数的调用,例如MyTargetApp::run()
  • 一个用于单元测试,调用 TestRunner,并包含所有测试套件和夹具 classes(包括 MyTargetApp 的这些)。

无需链接 cppunit 库和您的测试 suite/fixture 实现即可配置目标应用程序项目(这肯定会减少最终工件的占用空间)。


However, a cpp project can have ONLY ONE main.

另一种选择是仅使用一个具有窄 main() 函数的项目,该函数可以使用条件预处理器语句进行编译(来自他们在 TestRunner class 上的示例):

 #ifdef TESTING
 int runUnitTests(int argc, char* argv[]);
 #endif

 int main(int argc, char* argv[]) {

 #ifdef TESTING
     // run the unit tests
     // -----------------------------------------------------------------
     return runUnitTests(argc,argv);
 #else
     // run the application
     // -----------------------------------------------------------------
     MyTargetApp app;
     return app.run(argc,argv);
 #endif

 #ifdef TESTING
 int runUnitTests(int argc, char* argv[]) {
   std::string testPath = (argc > 1) ? std::string(argv[1]) : "";

   // Create the event manager and test controller
   CppUnit::TestResult controller;

   // Add a listener that colllects test result
   CppUnit::TestResultCollector result;
   controller.addListener( &result );        

   // Add a listener that print dots as test run.
   CppUnit::TextTestProgressListener progress;
   controller.addListener( &progress );      

   // Add the top suite to the test runner
   CppUnit::TestRunner runner;
   runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() );   
   try {
     std::cout << "Running "  <<  testPath;
     runner.run( controller, testPath );

     std::cerr << std::endl;

     // Print test in a compiler compatible format.
     CppUnit::CompilerOutputter outputter( &result, std::cerr );
     outputter.write();                      
   }
   catch ( std::invalid_argument &e ) {
     // Test path not resolved
     std::cerr  <<  std::endl  
                <<  "ERROR: "  <<  e.what()
                << std::endl;
     return 0;
   }         

   return result.wasSuccessful() ? 0 : 1;
 }
 #endif

然后有 2 个不同的项目配置,一个定义 TESTING,一个没有。

尽管如此,此解决方案的一个缺点是,您将在程序中保留所有单元测试套件和固定装置,因为 cppunit 宏将自动注册并实例化它们,无论是否从执行路径调用。