0


单元测试之CppTest测试框架

目录

1 背景

前面文章CppTest实战演示中讲述如何使用CppTest库。其主函数如下:

  1. intmain(int argc,char*argv[]){
  2. Test::Suite mainSuite;
  3. Test::TextOutput output(Test::TextOutput::Verbose);
  4. mainSuite.add(std::unique_ptr<Test::Suite>(new SeesionSuite));
  5. mainSuite.run(output,true);return0;}

以上代码有一点不好,就是每增加一个测试Suite就需要在main函数中调用mainSuite.add增加用例。有没有办法测试Suite自动添加,不需要修改main函数。下面讲述的测试框架可以解决这个问题。

2 设计

首先设计类TestApp,该类是单例模式,可以添加测试Suite,其次AutoAddSuite是一模板类在其构造函数中自动添加测试Suite.
其类图如下:
类图

类定义如下:

  1. classTestApp{
  2. Test::Suite mainSuite_;TestApp();public:static TestApp&Instance();voidaddSuite(Test::Suite * suite);intrun(int argc,char*argv[]);};#definetheTestAppTestApp::Instance()template<typenameSuite>classAutoAddSuite{
  3. Suite* suite;public:AutoAddSuite():suite(newSuite()){
  4. theTestApp.addSuite(suite);}};#defineADD_SUITE(Type) AutoAddSuite<Type> add##Type

说明:

  • TestApp类型是单例类,提高增加Suite接口和run接口
  • AutoAddSuite是一个自动添加Suite的模板类型
  • 宏ADD_SUITE定义了AutoAddSuite对象,用于自动添加。

3 实现

  1. #include"testapp.h"#include<iostream>#include<cstring>#include<cstdio>namespace{voidusage(){
  2. std::cout <<"usage: test [MODE]\n"<<"where MODE may be one of:\n"<<" --compiler\n"<<" --html\n"<<" --text-terse (default)\n"<<" --text-verbose\n";exit(0);}
  3. std::unique_ptr<Test::Output>cmdline(int argc,char* argv[]){if(argc >2)usage();// will not return
  4. Test::Output* output =0;if(argc ==1)
  5. output =newTest::TextOutput(Test::TextOutput::Verbose);else{constchar* arg = argv[1];if(strcmp(arg,"--compiler")==0)
  6. output =new Test::CompilerOutput;elseif(strcmp(arg,"--html")==0)
  7. output =new Test::HtmlOutput;elseif(strcmp(arg,"--text-terse")==0)
  8. output =newTest::TextOutput(Test::TextOutput::Terse);elseif(strcmp(arg,"--text-verbose")==0)
  9. output =newTest::TextOutput(Test::TextOutput::Verbose);else{
  10. std::cout <<"invalid commandline argument: "<< arg << std::endl;usage();// will not return}}return std::unique_ptr<Test::Output>(output);}}
  11. TestApp &TestApp::Instance(){static TestApp theApp;return theApp;}TestApp::TestApp(){}voidTestApp::addSuite(Test::Suite * suite){
  12. mainSuite_.add(std::unique_ptr<Test::Suite>(suite));}intTestApp::run(int argc,char*argv[]){try{
  13. std::unique_ptr<Test::Output>output(cmdline(argc, argv));
  14. mainSuite_.run(*output,true);
  15. Test::HtmlOutput*const html =dynamic_cast<Test::HtmlOutput*>(output.get());if(html)
  16. html->generate(std::cout,true, argv[0]);}catch(...){
  17. std::cout <<"unexpected exception encountered\n";return EXIT_FAILURE;}return EXIT_SUCCESS;}

说明:

  • Instance 返回一个单例引用
  • addSuite 增加Suite到mainSuite_
  • run - 首先根据命令行返回Test::Output- 然后调用mainSuite_运行测试用例- 最后如果类型是Output是Test::HtmlOutput类型,则将结果输出到标准输出std::cout.

4 使用

4.1 主函数

  1. #include"testapp.h"intmain(int argc,char*argv[]){try{
  2. theTestApp.run(argc, argv);}catch(const std::exception& e){
  3. std::cerr << e.what()<<'\n';}return0;}

主函数很简单,不再详述。

4.2 测试用例

这里使用C++标准库中std::mutex作为测试示例.

4.2.1 定义

  1. #ifndefMUTEX_TEST_H#defineMUTEX_TEST_H#include<cpptest/cpptest.h>classMutexSuite:public Test::Suite{public:MutexSuite(){TEST_ADD(MutexSuite::construct)TEST_ADD(MutexSuite::lock)TEST_ADD(MutexSuite::try_lock)TEST_ADD(MutexSuite::unlock)}voidconstruct();voidlock();voidtry_lock();voidunlock();};#endif

说明:

  • cpptest库标准使用,不再详述。

4.2.2 实现

  1. #include"mutex_test.h"#include"testapp.h"#include<thread>#include<mutex>ADD_SUITE(MutexSuite);voidaddCount(std::mutex & mutex,int& count){
  2. mutex.lock();
  3. count++;
  4. mutex.unlock();}voidMutexSuite::construct(){
  5. std::mutex muxtex;int count =0;
  6. std::thread threads[10];for(int i =0; i <10; i++)
  7. threads[i]= std::thread(addCount, std::ref(muxtex), std::ref(count));for(auto&thread : threads)
  8. thread.join();TEST_ASSERT_EQUALS(10, count)}voidMutexSuite::lock(){
  9. std::mutex muxtex;int count =10;
  10. std::thread threads[10];for(int i =0; i <10; i++)
  11. threads[i]= std::thread(addCount, std::ref(muxtex), std::ref(count));for(auto&thread : threads)
  12. thread.join();TEST_ASSERT_EQUALS(20, count)}structFunction{volatileint counter =0;voidadd_10k_count(std::mutex & muxtex){for(int i =0; i <10000; i++){if(muxtex.try_lock()){++counter;
  13. muxtex.unlock();}}}};voidMutexSuite::try_lock(){
  14. std::mutex muxtex;
  15. Function function;
  16. std::thread threads[10];for(int i =0; i <10; i++)
  17. threads[i]= std::thread(&Function::add_10k_count, std::ref(function), std::ref(muxtex));for(auto&thread : threads)
  18. thread.join();TEST_ASSERT_EQUALS(true, function.counter <(10*10000))
  19. std::cerr <<"function.counter: "<< function.counter << std::endl;}voidMutexSuite::unlock(){
  20. std::mutex muxtex;int count =20;
  21. std::thread threads[10];for(int i =0; i <10; i++)
  22. threads[i]= std::thread(addCount, std::ref(muxtex), std::ref(count));for(auto&thread : threads)
  23. thread.join();TEST_ASSERT_EQUALS(30, count)}

说明:

  • 重点说明下文件头部宏ADD_SUITE的使用,如下所示传递给ADD_SUITE的参数正是MutexSuite,通过该定义,将MutexSuite自动添加到TestApp实例中,不需要修改main函数.
  1. ADD_SUITE(MutexSuite);

4.3 运行

  1. $ testapp --html

说明:

  • testapp是编译出的可执行文件
  • 参数–html 说明测试报告按网页格式输出.

本文转载自: https://blog.csdn.net/flysnow010/article/details/139479329
版权归原作者 flysnow010 所有, 如有侵权,请联系我们删除。

“单元测试之CppTest测试框架”的评论:

还没有评论