我进入了一个项目,我们拥有一个庞大的代码库,目前它根本没有单元测试框架。我们正在处理的代码最终会在一个充当交换机/路由器/防火墙的盒子上运行。
所以我正在编写一段需要使用Gtest进行单元测试的代码。 我遇到的问题是模拟变量以测试函数本身。 例如,我有一个函数,它使用4个不同对象的指针并使用几个全局变量。为了测试代码中的不同路径,我需要初始化几乎整个状态机制/因变量的值。 在大型代码库中增加了复杂性,我编写的这个函数/方法使用了一堆其他需要测试的例程/方法。每个都需要进行单一测试,每个都有自己的依赖关系。 我不确定我是否正确处理问题,或者gtest可能不是测试如此大型代码库的正确工具。
如果有人有说测试的经验,说一个电话堆栈说
function A {
code
code
function B
code
code
function C
code
}
function B
{
function D
code
function E
}
function C{
code
function F
function G
code
}
像这样的事情。我如何测试所有这些功能A-F ??什么是好策略?
答案 0 :(得分:2)
首先要重构代码,以便隔离可测试的部分。特别是,这意味着删除对全局变量的访问。例如:
int global;
int function() {
int r = foo();
global += r / 2;
bar(r);
return 42;
}
删除全局对象意味着将其转换为输入参数:
int real_function(int* target) {
assert(target);
int r = foo();
*target += r / 2;
bar(r);
return 42;
}
然后剩下的代码当然会停止编译,所以你添加一个向后兼容的cludge:
int global_bar;
// @deprecated, use real_function() directly
int function() {
return real_function(&global_bar);
}
使用它,你升级调用链,提取依赖关系,并希望有一天删除对需要全局变量的变量的最后一次调用。与此同时,您可以为不再依赖于全局内容的函数编写测试。请注意,对于C ++,您将使用引用而不是指针,并可能将所需的外部对象传递给类构造函数。这也称为依赖注入,请务必研究该术语以便全面了解。
测试接触全局变量的函数的另一种方法是使用测试的setup函数将全局重置为已知状态。这仍然需要在全球范围内进行链接,这可能会很困难。并且不使用全局变量可能会使代码库首先变得更好,所以接受它也会发送错误的消息。
答案 1 :(得分:0)
对于您要测试的任何全局函数,您应该查看
然后考虑:
如果您的函数是对象而不是全局函数的函数,则可以另外考虑:
我认为使函数可测试的最后一件事是它是否属于一个类。
一旦解决了所有这些问题,您通常可以轻松地模拟所需的位。如果您正在使用gtest,您可以使用gmock来简化这一过程。 (我之前使用gmock和gtest非常无痛。)
(是的,我之前在大型代码库上采用了这种方法......开始时通常非常痛苦,但是一旦你习惯它并且代码开始变得更加可测试 - 事情就会好转。 )