0

失败

给定以下 cmocka 测试,其中包含依赖项中的静态变量:

main.c

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include "dependency.h"

void test1(void** state) {
    increment();
    assert_int_equal(1, get_incrementer());
}

void test2(void** state) {
    increment();
    assert_int_equal(1, get_incrementer());
}

int main() {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(test1),
        cmocka_unit_test(test2),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

dependency.h

void increment();
int get_incrementer();

dependency.c

static int incrementer = 0;

void increment() {
    ++incrementer;
}

int get_incrementer() {
    return incrementer;
}

(编译gcc main.c dependency.c -lcmocka并运行)

我得到以下输出:

[==========] Running 2 test(s).
[ RUN      ] test1
[       OK ] test1
[ RUN      ] test2
[  ERROR   ] --- 0x1 != 0x2
[   LINE   ] --- main.c:14: error: Failure!
[  FAILED  ] test2
[==========] 2 test(s) run.
[  PASSED  ] 1 test(s).
[  FAILED  ] 1 test(s), listed below:
[  FAILED  ] test2

 1 FAILED TEST(S)

这是因为incrementer不是在每次测试之间“重置”。

这只是一个证明观点的最小示例。实际上,我的依赖深入到我在测试中调用的代码中。

让它工作的替代方案

但是,如果我将每个测试分成自己的可执行文件和自己的测试组,我就可以incrementer按照预期为每个测试重新设置。

问题

  • 是唯一用 cmocka 实现测试隔离将每个测试分离成自己的可执行文件的吗?

当我发现这种情况发生时,我很震惊。我是 C 和 C 测试的新手,我一直认为测试隔离是单元测试框架的关键部分。对我来说,为什么甚至会有测试组开始是没有意义的,因为大多数时候您将测试具有依赖关系的代码,其中在某处使用静态变量,因此每个测试都会生成一个可执行文件。

4

1 回答 1

1

是的,如果您在测试对象中有一个静态变量,如果他们期望一个“新鲜”的测试对象,您需要编译单独的测试。

无论如何,我都会这样做,每个测试都在一个单独的可执行文件中,因为您的测试对象中有一个 Singleton。

这是一个很好的例子,为什么单例模式在今天是一种反模式。很难测试。

于 2022-02-15T08:02:18.630 回答