1

我进入了一个项目,我们有一个庞大的代码库,目前它根本没有单元测试框架。我们正在处理的代码最终将在一个充当交换机/路由器/防火墙的盒子上运行。

所以我正在研究一段需要使用 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
}

像这样的东西。我如何测试所有这些功能 AF ?什么是好的策略??

4

2 回答 2

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;
}

然后当然剩下的代码将停止编译,所以你添加一个向后兼容的插件:

int global_bar;
// @deprecated, use real_function() directly
int function() {
    return real_function(&global_bar);
}

使用它,您可以加强调用链,提取依赖关系,并希望有一天能删除对需要全局变量的最后一次调用。同时,您可以为不再依赖全局内容的函数编写测试。请注意,对于 C++,您将使用引用而不是指针,并且可能将所需的外部对象传递给类构造函数。这也称为依赖注入,请务必研究该术语以彻底理解。

测试接触全局的函数的另一种方法是使用测试的设置函数将全局重置为已知状态。但是,这仍然需要在全球范围内进行链接,这可能很困难。并且不使用全局变量可能会使代码库变得更好,因此接受它也会发送错误信息。

于 2014-09-11T05:52:30.367 回答
0

Ulrich Eckhardt 本质上说,“你需要摆脱全局变量来制作易于测试的代码”。但你真的应该走得更远。

对于您要测试的任何全局函数,您应该查看

  • 它访问的全局变量。
  • 它使用的参数。
  • 它调用的函数。

然后考虑:

  • 将它调用的函数转换为对一个或多个接口的调用,并将它们作为参数传递。
  • 将全局变量转换为参数或接口上的函数调用。

如果您的函数是对象上的函数而不是全局函数,则可以另外考虑:

  • 制作全局成员变量,并将它们传递给构造函数
  • 制作它调用虚拟成员函数的函数

为了使函数可测试,我考虑的最后一件事是它是否属于一个类。

一旦解决了所有这些问题,您通常可以轻松地模拟所需的位。如果您使用的是 gtest,则可以使用 gmock 来简化此操作。(我之前使用过 gmock 和 gtest,而且非常轻松。)

(是的,我以前在大型代码库上采用过这种方法……一开始通常会很痛苦,但是一旦你习惯了它并且代码开始变得更加可测试 - 事情会有所改善。)

于 2014-09-11T06:37:41.283 回答