嵌套预处理程序指令或其他技巧来有条件地重新定义静态关键字

时间:2015-07-24 20:32:00

标签: c unit-testing c-preprocessor

我使用统一进行单元测试。

我的项目中有一个标题,我包含了一些辅助宏,就像一个断言包装器,我可以用来跟踪哪个断言被触发。

在该标题中,我还有以下定义:

#define static //nothing

我从这篇文章中学到了一个小技巧: http://www.embedded.com/design/programming-languages-and-tools/4007177/2/Doing-C-code-unit-testing-on-a-shoestring-Part-1-The-basics-and-the-tools

这允许我编写静态函数的单元测试,它允许我从我的测试工具中访问任何相关的文件范围数据。

问题是这在功能范围内完全打破了静态。文章继续说我是否这样做:

#define static extern

然后可以在测试工具中定义任何在函数范围内为静态的变量。我们参加了比赛,对吧?不完全是。

因为发生以下情况

void foo()
{
    extern bool my_flag = false;
}

现在我们正在为声明提供初始化程序,这是无效的。这意味着我以这种方式处理的任何静态变量本身都需要在启动后进行初始化。

因为函数中的静态变量相对不常见,我想我可以通过定义一个新符号LOCAL_STATIC来避免这种情况。所以现在在我的标题中我有以下

#define static extern
#define LOCAL_STATIC static

但这不起作用,因为这些指令严格按顺序进行评估 - #define LOCAL_STATIC static变为#define LOCAL_STATIC extern,或者至少这似乎正在发生。因为LOCAL_STATIC会产生相同的错误,并且最终会被预处理器更改为extern。

那有什么方法吗?

AFAIK这样的事情是不可能的:

#define LOCAL_STATIC  \
#undef static         \
static                \
#define static extern

我唯一能想到的就是单独留下静态并定义一个新符号,例如HARNESS_ACCESSIBLE

#ifdef UNIT_TEST
#define HARNESS_ACCESSIBLE extern
#else
#define HARNESS_ACCESSIBLE static
#endif

但是,这会使这个新奇怪的东西弄乱生产代码" HARNESS_ACCESSIBLE"。函数中的静态变量通常很少见,但几乎所有静态函数(除了琐碎的辅助函数)都需要我的测试运行者可以从外部访问。

我一直试图避免编写一个必须在构建之前运行的单独脚本,但我现在已经到了这一点。

1 个答案:

答案 0 :(得分:1)

我认为你创建一个HARNESS_ACCESSIBLE宏的想法是解决这个问题最干净的方法。由于您所描述的原因,您绝对不想#define-ing away static

我不认为使用此宏会使代码混乱。您只需将其替换为static,它就可以选择确切地指定您希望能够对哪些函数进行单元测试并明确保留这些次要效用函数static