cgreen

时间:2016-01-02 02:34:43

标签: c unit-testing gcc tdd bdd

我正在使用cgreen为我的C代码编写测试,我的问题是:

简短版本 是否可以在一个文件中放置多个Describe()

长版: 我有不同的测试文件,有自己的Describe()BeforeEach()AfterEach()。因为在这些文件中,我使用了相同的模块,所以我必须将它们一起编译。 [为了防止编译器多次包含该模块,我使用了这个技巧(包括后卫)

#ifndef SOME_NAME
#define SOME_NAME

...

#endif

我还有一个包含我所有测试的文件,比如all_tests.c。现在,我想将我的测试文件包含到all_tests.c中并将所有内容编译在一起,如下所示:

#include <cgreen/cgreen.h>

#include "./test1.c"
#include "./test2.c"

int main() {
    TestSuite *suite = create_test_suite();

    add_suite(suite, test1_tests());
    add_suite(suite, test2_tests());

    return run_test_suite(suite, create_text_reporter());
}

会导致这些错误:

error: redefinition of ‘setup’
error: redefinition of ‘teardown’

显然,因为Describe()BeforeEach()AfterEach()有多种定义。好吧,我找不到更好的主意,使用推荐的

方式
TestSuite *test1_tests();
TestSuite *test2_tests();

而不是直接包含文件,分别汇编和编译每个测试文件,然后将所有文件链接在一起导致此错误:

multiple definition of `some_global_module'

这是预期的,如在链接状态中,some_global_module有多个定义。为了清楚起见,test1.c文件看起来像这样(以及test2.c文件,只需在以下代码中将test1更改为test2

#include <cgreen/cgreen.h>

#include "./some_global_module.h"
#include "./some_other_module_i_want_to_test1.h"

Describe(test1);

BeforeEach(test1) {
    ...
}

AfterEach(test1) {
    ...
}

Ensure(test1, do_something) {
    ...
}

TestSuite *test1_tests() {
    TestSuite *suite = create_test_suite();
    add_test_with_context(suite, test1, do_something);
    return suite;
}

有什么想法吗?也许我可以使用一些编译技巧或更简单的方法来管理整个事情?

1 个答案:

答案 0 :(得分:1)

无法在同一测试文件中包含多个Describe()。它不应该是必要的。

您无法准确解释如何组装测试/模块。有几种选择:

  1. #include您的模块源代码在测试文件中 - 这是可能的,但是您显然无法将多个测试文件链接在一起,您需要单独运行它们,因为它们定义相同的所有被测模块中的符号。

  2. 让测试&#34;模块&#34;以与其他用户相同的方式使用您的测试模块(\#include并调用公共接口)。在这种情况下,您的测试文件与其他模块一样,应该与被测模块的单个实例链接在一起。

  3. 使用cgreen-runner。它加载共享库并发现库中的所有测试,使您免于记住将每个新测试用例添加到套件中的负担。

  4. 如果要将测试改装为现有的,不可测试的代码,或者 需要测试内部,例如static函数,请仅使用#1

    #2非常标准,可能就是你应该做的。在这种情况下,请从您的#include "some_global_module.c"中删除测试文件中的所有test1.c。您的Makefile应该类似于:

    all: all_tests
    
    all_tests: all_tests.o some_global_module.o \
        test1.o some_global_module_under_test1.o \
        test2.o some_global_module_under_test2.o
    

    因此,如果您指出test1.ctest2.c,以及上面的Makefile内容,我就不明白为什么您应该得到&#34;多重定义&#34;在链接时。

    #3是我最喜欢的。将所有内容链接到共享对象库(Linux上为.so)并在其上运行cgreen-runner。您的Makefile应该类似于:

    all: all_tests.so
        cgreen-runner ./$^ 
    
    all_tests.so: some_global_module.o \
            test1.o some_global_module_under_test1.o \
            test2.o some_global_module_under_test2.o
        $(LINK) -shared -o $@ $^
    

    注意:如果您的some_global_module_under_test1依赖于许多其他模块,您也需要链接它们,或者模仿它们。