调用名称未知的函数

时间:2014-04-29 13:07:14

标签: c unit-testing

作为一个小小的个人项目,我在C中做了一个小而简单的测试框架。

我面临的问题是,我希望能够在用户编写测试用例时自动注册测试用例(即其中包含某些类型的ASSERTS的函数),然后在我预定义的主函数中运行它们。

所以从用户方面来说,我只想做

TEST_CASE("TestName1")
{
    // Testing stuff here
}

TEST_CASE("TestName2")
{
     // Testing more stuff here
}

其余的应该被覆盖。

目前,定义只是

#define TEST_CASE(name) int name()

问题是,如果有可能在某种程度上记住"这些函数让我可以在main函数中调用它们。

编辑: 所以重点是用户应该包含一个" test-framework.h"它定义了一个预定义的main()函数,该函数运行用户使用TEST_CASEs指定的所有测试。这意味着它应该看起来像这样:

用户定义文件:

// File where tests are defined
#include "framework.h"

TEST_CASE("TestCase1")
{
    // Test stuff
}

TEST_CASE("TestCase2")
{
    // Test more stuff
}

在框架文件中:

// framework.h

#define TEST_CASE(name) int name()

int main()
{
    // Here run all TEST_CASEs there is
}

那意思,我不知道我的main()中TEST_CASES的名字。

3 个答案:

答案 0 :(得分:1)

你无法按照自己想要的方式真正做到这一点,但如果你对用户不得不做更多的工作感到满意,比如说。 :

TEST_CASE(TestName1) {
    return 42;
}

TEST_CASE(TestName2) {
    return 0;
}

ALL_TEST_CASES {
    REGISTER_TEST_CASE(TestName1);
    REGISTER_TEST_CASE(TestName2);
}

然后你的框架可能有这样的代码(使用函数指针来注册测试用例):

typedef struct TestCase {
    const char* name;
    int (*fptr)();
} TestCase;

TestCase testCases[10];
size_t testCnt = 0;

#define ALL_TEST_CASES void registerTestCases()
#define TEST_CASE(NAME) int NAME()
#define REGISTER_TEST_CASE(NAME) do { testCases[testCnt].name = #NAME; testCases[testCnt++].fptr = &NAME; } while (0)

和主要:

int main(void) {
    registerTestCases();

    size_t i;
    for (i = 0; i < testCnt; ++i) {
        fprintf(stdout, "Test %s : %d\n", testCases[i].name, testCases[i].fptr());
    }

    return 0;
}

显然,这需要更加健壮等等 - 它应该只是作为概念的证明。

答案 1 :(得分:1)

您可以根据情况重新定义TEST_CASE宏,因此在不同情况下它会执行不同的操作。

这样的东西
#define TEST_CASE(name)  int Test##name(void)

TEST_CASE(Function1)
{
    // Test Function1
}

TEST_CASE(Function2)
{
    // Test Function2
}

#undef TEST_CASE
#define TEST_CASE(name) { #name, Test##name }

static const struct
{
    char *name;
    int (*func)(void);
} tests[] = {
    TEST_CASE(Function1),
    TEST_CASE(Function2),
    { NULL, NULL }
};

int DoTests(void)
{
    for (int test = 0; tests[test].name != NULL; ++test)
    {
        printf("Running test #%d (%s)...", test + 1, tests[test].name);
        fflush(stdout);

        if (tests[test].func != NULL)
        {
            if (tests[test].func() == 0)
            {
                printf("Failed\n");
                return 0;
            }
        }

        printf("Ok\n");
    }

    return 1;
}

然后在main函数中调用DoTests()并调用所有测试

答案 2 :(得分:1)

C中没有人支持做我认为你想做的事情。话虽这么说,如果你想使用一些不可移植的技巧,你可以看看这个问题并回答:How can I implement a dynamic dispatch table in C