如何像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 宏将自动注册并实例化它们,无论是否从执行路径调用。
我知道 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 宏将自动注册并实例化它们,无论是否从执行路径调用。