Car*_* D. 5 c++ unit-testing catch-unit-test
我正在使用CATCH v1.1 build 14对我的C++代码进行单元测试.
作为测试的一部分,我想在我的代码中检查几个模块的输出.没有一定数量的模块; 可以随时添加更多模块.但是,测试每个模块的代码是相同的.因此,我认为将测试代码放在for循环中是理想的.事实上,使用catch.hpp,我已经验证我可以在一个测试用例中动态创建Sections,其中每个Section对应一个模块.我可以通过将SECTION宏包含在for循环中来实现,例如:
#include "catch.hpp"
#include <vector>
#include <string>
#include "myHeader.h"
TEST_CASE("Module testing", "[module]") {
myNamespace::myManagerClass manager;
std::vector<std::string> modList;
size_t n;
modList = manager.getModules();
for (n = 0; n < modList.size(); n++) {
SECTION(modList[n].c_str()) {
REQUIRE(/*insert testing code here*/);
}
}
}
Run Code Online (Sandbox Code Playgroud)
(这不是一个完整的工作示例,但你明白了.)
这是我的困境.我想独立测试模块,这样如果一个模块出现故障,它将继续测试其他模块而不是中止测试.但是,CATCH的工作方式,如果单个REQUIRE失败,它将中止整个测试用例.出于这个原因,我想为每个模块创建一个单独的测试用例,而不仅仅是一个单独的部分.我尝试将我的for循环放在TEST_CASE宏之外,但是这段代码无法编译(正如我所料):
#include "catch.hpp"
#include <vector>
#include <string>
#include "myHeader.h"
myNamespace::myManagerClass manager;
std::vector<std::string> modList;
size_t n;
modList = manager.getModules();
for (n = 0; n < modList.size(); n++) {
TEST_CASE("Module testing", "[module]") {
SECTION(modList[n].c_str()) {
REQUIRE(/*insert testing code here*/);
}
}
}
Run Code Online (Sandbox Code Playgroud)
有可能通过编写我自己的方法 来做到这一点main(),但我看不出如何完全做到这一点.(我会将我的TEST_CASE代码直接放入main()吗?如果我想将TEST_CASE代码保存在不同的文件中,该怎么办?另外,它会影响我的其他更标准的测试用例吗?)
我还可以使用CHECK宏而不是REQUIRE宏来避免在模块出现故障时中止测试用例,但后来我遇到了相反的问题:它试图继续对应该在早期失败的模块进行测试.如果我可以将每个模块放在自己的测试用例中,这应该给我理想的行为.
有没有一种在CATCH中动态创建测试用例的简单方法?如果是这样,你能给我一个如何做的例子吗?我通读了CATCH文档并在线搜索,但我找不到任何关于如何执行此操作的说明.
听起来 Catch 可能会转向基于属性的测试,我希望这将允许一种动态创建测试用例的方法。与此同时,这就是我最终所做的事情。
我创建了一个.cpp文件,其中包含一个用于TEST_CASE单个模块的文件,以及一个用于模块名称的全局变量。(是的,我知道全局变量是邪恶的,这就是为什么我要小心并将其用作最后的手段):
module_unit_test.cpp:
#include "catch.hpp"
#include <string>
#include "myHeader.h"
extern const std::string g_ModuleName; // global variable: module name
TEST_CASE("Module testing", "[module]") {
myNamespace::myManagerClass manager;
myNamespace::myModuleClass *pModule;
SECTION(g_ModuleName.c_str()) {
pModule = manager.createModule(g_ModuleName.c_str());
REQUIRE(pModule != 0);
/*insert more testing code here*/
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我创建一个可执行文件,它将在命令行指定的单个模块上运行此测试。(我尝试循环遍历Catch::Session().run()下面的内容,但 Catch 不允许它运行多次。)创建可执行文件时,链接了下面代码module_test.cpp和上面单元测试代码中的目标文件。module_unit_test.cpp
module_test.cpp:
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <string>
#include <cstdio>
std::string g_ModuleName; // global variable: module name
int main(int argc, char* argv[]) {
// Make sure the user specified a module name.
if (argc < 2) {
std::cout << argv[0] << " <module name> <Catch options>" << std::endl;
return 1;
}
size_t n;
char* catch_argv[argc-1];
int result;
// Modify the input arguments for the Catch Session.
// (Remove the module name, which is only used by this program.)
catch_argv[0] = argv[0];
for (n = 2; n < argc; n++) {
catch_argv[n-1] = argv[n];
}
// Set the value of the global variable.
g_ModuleName = argv[1];
// Run the test with the modified command line arguments.
result = Catch::Session().run(argc-1, catch_argv);
return result;
}
Run Code Online (Sandbox Code Playgroud)
然后,我在单独的可执行文件中执行循环(未链接到上面代码中的目标文件):
module_test_all.cpp:
#include <cstdlib>
#include <vector>
#include <string>
#include "myHeader.h"
int main(int argc, char* argv[]) {
std::string commandStr;
int result, status = 0;
myNamespace::myManagerClass manager;
std::vector<std::string> modList;
size_t m, n;
// Scan for modules.
modList = manager.getModules();
// Loop through the module list.
for (n = 0; n < modList.size(); n++) {
// Build the command line.
commandStr = "module_test " + modList[n];
for (m = 1; m < argc; m++) {
commandStr += " ";
commandStr += argv[m];
}
// Do a system call to the first executable.
result = system(commandStr.c_str());
// If a test fails, I keep track of the status but continue
// looping so all the modules get tested.
status = status ? status : result;
}
return status;
}
Run Code Online (Sandbox Code Playgroud)
是的,它很丑,但我已经确认它有效。
| 归档时间: |
|
| 查看次数: |
3117 次 |
| 最近记录: |