到目前为止,我一直在使用一种即兴的单元测试程序——基本上是由批处理文件自动运行的整个单元测试程序负载。尽管其中很多都明确地检查了他们的结果,但更多的作弊 - 他们将结果转储到版本控制的文本文件中。测试结果的任何变化都会被 subversion 标记出来,我可以很容易地识别出变化是什么。许多测试输出点文件或其他形式,使我能够获得输出的可视化表示。
问题是我正在改用cmake。使用 cmake 流程意味着使用源外构建,这意味着将结果转储到共享源/构建文件夹中并与源一起对它们进行版本控制并不真正起作用。
作为替代,我想做的是告诉单元测试工具在哪里可以找到预期结果的文件(在源代码树中)并让它进行比较。失败时,它应该提供实际结果和差异列表。
这是可能的,还是我应该采取完全不同的方法?
显然,我可以忽略 ctest 而只是将我一直在做的事情调整到源代码之外的构建。例如,我可以对我的文件夹-where-all-the-builds-live 进行版本控制(当然可以自由使用“ignore”)。那是理智的吗?可能不会,因为每个构建最终都会得到预期结果的单独副本。
此外,收到了有关使用 cmake/ctest 进行单元测试的推荐方法的任何建议。我在 cmake 上浪费了相当多的时间,不是因为它不好,而是因为我不明白如何最好地使用它。
编辑
最后,我决定让单元测试的 cmake/ctest 方面尽可能简单。为了根据预期结果测试实际结果,我在我的库中找到了以下函数的主页...
bool Check_Results (std::ostream &p_Stream ,
const char *p_Title ,
const char **p_Expected,
const std::ostringstream &p_Actual )
{
std::ostringstream l_Expected_Stream;
while (*p_Expected != 0)
{
l_Expected_Stream << (*p_Expected) << std::endl;
p_Expected++;
}
std::string l_Expected (l_Expected_Stream.str ());
std::string l_Actual (p_Actual.str ());
bool l_Pass = (l_Actual == l_Expected);
p_Stream << "Test: " << p_Title << " : ";
if (l_Pass)
{
p_Stream << "Pass" << std::endl;
}
else
{
p_Stream << "*** FAIL ***" << std::endl;
p_Stream << "===============================================================================" << std::endl;
p_Stream << "Expected Results For: " << p_Title << std::endl;
p_Stream << "-------------------------------------------------------------------------------" << std::endl;
p_Stream << l_Expected;
p_Stream << "===============================================================================" << std::endl;
p_Stream << "Actual Results For: " << p_Title << std::endl;
p_Stream << "-------------------------------------------------------------------------------" << std::endl;
p_Stream << l_Actual;
p_Stream << "===============================================================================" << std::endl;
}
return l_Pass;
}
一个典型的单元测试现在看起来像......
bool Test0001 ()
{
std::ostringstream l_Actual;
const char* l_Expected [] =
{
"Some",
"Expected",
"Results",
0
};
l_Actual << "Some" << std::endl
<< "Actual" << std::endl
<< "Results" << std::endl;
return Check_Results (std::cout, "0001 - not a sane test", l_Expected, l_Actual);
}
在我需要一个可重用的数据转储函数的地方,它需要一个 type 参数std::ostream&
,因此它可以转储到实际结果流。