1 背景
前面文章CppTest实战演示中报告如何使用CppTest库。其主函数如下:
- int main(int argc, char *argv[])
- {
- Test::Suite mainSuite;
- Test::TextOutput output(Test::TextOutput::Verbose);
- mainSuite.add(std::unique_ptr<Test::Suite>(new SeesionSuite));
- mainSuite.run(output, true);
- return 0;
- }
复制代码 以上代码有一点不好,就是每增加一个测试Suite就必要在main函数中调用mainSuite.add增加用例。有没有办法测试Suite自动添加,不必要修改main函数。下面报告的测试框架可以办理这个问题。
2 设计
起首设计类TestApp,该类是单例模式,可以添加测试Suite,其次AutoAddSuite是一模板类在其构造函数中自动添加测试Suite.
其类图如下:
类界说如下:
- class TestApp
- {
- Test::Suite mainSuite_;
- TestApp();
- public:
- static TestApp& Instance();
- void addSuite(Test::Suite * suite);
- int run(int argc, char *argv[]);
- };
- #define theTestApp TestApp::Instance()
- template<typename Suite>
- class AutoAddSuite
- {
- Suite* suite;
- public:
- AutoAddSuite()
- : suite(new Suite())
- {
- theTestApp.addSuite(suite);
- }
- };
- #define ADD_SUITE(Type) AutoAddSuite<Type> add##Type
复制代码 说明:
- TestApp类型是单例类,提高增加Suite接口和run接口
- AutoAddSuite是一个自动添加Suite的模板类型
- 宏ADD_SUITE界说了AutoAddSuite对象,用于自动添加。
3 实现
- #include "testapp.h"
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- namespace
- {
- void usage()
- {
- 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);
- }
- std::unique_ptr<Test::Output> cmdline(int argc, char* argv[])
- {
- if (argc > 2)
- usage(); // will not return
- Test::Output* output = 0;
- if (argc == 1)
- output = new Test::TextOutput(Test::TextOutput::Verbose);
- else
- {
- const char* arg = argv[1];
- if (strcmp(arg, "--compiler") == 0)
- output = new Test::CompilerOutput;
- else if (strcmp(arg, "--html") == 0)
- output = new Test::HtmlOutput;
- else if (strcmp(arg, "--text-terse") == 0)
- output = new Test::TextOutput(Test::TextOutput::Terse);
- else if (strcmp(arg, "--text-verbose") == 0)
- output = new Test::TextOutput(Test::TextOutput::Verbose);
- else
- {
- std::cout << "invalid commandline argument: " << arg << std::endl;
- usage(); // will not return
- }
- }
- return std::unique_ptr<Test::Output>(output);
- }
- }
- TestApp & TestApp::Instance()
- {
- static TestApp theApp;
- return theApp;
- }
- TestApp::TestApp()
- {}
- void TestApp::addSuite(Test::Suite * suite)
- {
- mainSuite_.add(std::unique_ptr<Test::Suite>(suite));
- }
- int TestApp::run(int argc, char *argv[])
- {
- try
- {
- std::unique_ptr<Test::Output> output(cmdline(argc, argv));
- mainSuite_.run(*output, true);
- Test::HtmlOutput* const html = dynamic_cast<Test::HtmlOutput*>(output.get());
- if (html)
- html->generate(std::cout, true, argv[0]);
- }
- catch (...)
- {
- 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 主函数
- #include "testapp.h"
- int main(int argc, char *argv[])
- {
- try
- {
- theTestApp.run(argc, argv);
- }
- catch(const std::exception& e)
- {
- std::cerr << e.what() << '\n';
- }
- return 0;
- }
复制代码 主函数很简朴,不再详述。
4.2 测试用例
这里使用C++尺度库中std::mutex作为测试示例.
4.2.1 界说
- #ifndef MUTEX_TEST_H
- #define MUTEX_TEST_H
- #include <cpptest/cpptest.h>
- class MutexSuite : public Test::Suite
- {
- public:
- MutexSuite()
- {
- TEST_ADD(MutexSuite::construct)
- TEST_ADD(MutexSuite::lock)
- TEST_ADD(MutexSuite::try_lock)
- TEST_ADD(MutexSuite::unlock)
- }
- void construct();
- void lock();
- void try_lock();
- void unlock();
- };
- #endif
复制代码 说明:
4.2.2 实现
- #include "mutex_test.h"
- #include "testapp.h"
- #include <thread>
- #include <mutex>
- ADD_SUITE(MutexSuite);
- void addCount(std::mutex & mutex, int & count)
- {
- mutex.lock();
- count++;
- mutex.unlock();
- }
- void MutexSuite::construct()
- {
- std::mutex muxtex;
- int count = 0;
- std::thread threads[10];
- for(int i = 0; i < 10; i++)
- threads[i] = std::thread(addCount, std::ref(muxtex), std::ref(count));
- for(auto &thread : threads)
- thread.join();
- TEST_ASSERT_EQUALS(10, count)
- }
- void MutexSuite::lock()
- {
- std::mutex muxtex;
- int count = 10;
- std::thread threads[10];
- for(int i = 0; i < 10; i++)
- threads[i] = std::thread(addCount, std::ref(muxtex), std::ref(count));
- for(auto &thread : threads)
- thread.join();
- TEST_ASSERT_EQUALS(20, count)
- }
- struct Function
- {
- volatile int counter = 0;
- void add_10k_count(std::mutex & muxtex)
- {
- for(int i = 0; i < 10000; i++)
- {
- if(muxtex.try_lock())
- {
- ++counter;
- muxtex.unlock();
- }
- }
- }
- };
- void MutexSuite::try_lock()
- {
- std::mutex muxtex;
- Function function;
- std::thread threads[10];
- for(int i = 0; i < 10; i++)
- threads[i] = std::thread(&Function::add_10k_count, std::ref(function), std::ref(muxtex));
- for(auto &thread : threads)
- thread.join();
- TEST_ASSERT_EQUALS(true, function.counter < (10 * 10000))
- std::cerr << "function.counter: " << function.counter << std::endl;
- }
- void MutexSuite::unlock()
- {
- std::mutex muxtex;
- int count = 20;
- std::thread threads[10];
- for(int i = 0; i < 10; i++)
- threads[i] = std::thread(addCount, std::ref(muxtex), std::ref(count));
- for(auto &thread : threads)
- thread.join();
- TEST_ASSERT_EQUALS(30, count)
- }
复制代码 说明:
- 重点说明下文件头部宏ADD_SUITE的使用,如下所示转达给ADD_SUITE的参数正是MutexSuite,通过该界说,将MutexSuite自动添加到TestApp实例中,不必要修改main函数.
4.3 运行
说明:
- testapp是编译出的可实行文件
- 参数–html 说明测试报告按网页格式输出.
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |