如何测试静态函数

Kev*_* Yu 38 c unit-testing

在对某些C代码应用单元测试时,我们遇到了一个问题,即在不修改源代码的情况下,无法在测试文件中调用某些静态函数.有没有简单或合理的方法来解决这个问题?

Jon*_*ler 49

我有一个测试工具.在可怕的情况下 - 比如尝试测试静态函数,我使用:

#include "code_under_test.c"
...test framework...
Run Code Online (Sandbox Code Playgroud)

也就是说,我在测试工具中包含了包含被测功能的整个文件.这是最后的手段 - 但它确实有效.

  • 当“code_under_test.c”包含静态和非静态函数并且与我的测试文件链接在一起时,这会给我带来问题。然后,非静态函数被定义两次。 (6认同)
  • @BhupeshPant:你有什么不明白的?如果一个函数是`static`,那么它在定义它的翻译单元(粗略地说,源文件)之外是不可访问的。答案中的解决方案通过将要测试的源代码复制到通过 `#include "code_under_test.c"` 指令测试它的文件中,确保要测试的函数包含在测试它的代码中。编译器将要测试的代码和进行测试的代码视为一个单独的翻译单元,因此测试代码可以调用静态函数,否则这是不可能的。 (3认同)

Jar*_*Par 13

您能否提供更多有关无法调用此功能的信息?

它不可用,因为它是.c文件的私有内容吗?如果是这样,最好的办法是使用允许访问函数的条件编译,以允许其他编译单元访问它.例如

SomeHeaderSomewher.h

#if UNIT_TEST
#define unit_static 
#else
#define unit_static static
#endif
Run Code Online (Sandbox Code Playgroud)

foo.h中

#if UNIT_TEST
void some_method
#endif
Run Code Online (Sandbox Code Playgroud)

Foo.cpp中

unit_static void some_method() ...
Run Code Online (Sandbox Code Playgroud)


pax*_*blo 7

对于单元测试,我们实际上在源文件本身中有测试代码,并且我们在测试时有条件地编译它.这使单元测试可以完全访问所有函数和文件级变量(静态或其他).

单元测试本身并不是静态的 - 这允许我们从单个超级测试程序调用单元测试,该程序单元测试所有编译单元.

当我们发送代码时,我们有条件地编译出单元测试,但这实际上并不是必需的(如果你想确定你运送的是完全相同的代码).

我们总是发现将单元测试与您正在测试的代码放在同一个位置是非常宝贵的,因为它使得更明显的是您需要在代码更改时更新测试.

  • 当单元测试足够小以适合时,我会这样做。当单元测试变得比被测源大时,我求助于单独的测试程序,它可以与对象链接(仅使用外部依赖项时)或在玩静态函数时使用我的答案中的技巧。 (2认同)

小智 6

#define static
Run Code Online (Sandbox Code Playgroud)

这是一个非常糟糕的主意。如果您在函数中声明了一个局部变量,它会改变该函数的行为。例子:

static int func(int data)
{
   static int count = 0;

   count += data;
   return count;
}
Run Code Online (Sandbox Code Playgroud)

您可以从单元测试中调用该函数,因为 func() 将被导出,但是代码的基本功能将被修改。

——库尔特


Bee*_*eep 5

不 - 你不能直接测试静态函数而不至少修改一下源(即C中静态的定义 - 它不能从不同文件中的函数调用).

你可以在测试文件中创建一个单独的函数来调用静态函数吗?

例如:

//Your fn to test
static int foo(int bar)
{
  int retVal;
  //do something
  return retVal;
}

//Wrapper fn
int test_foo(int bar)
{
  return foo(bar);
}
Run Code Online (Sandbox Code Playgroud)

我们通常不直接测试我们的静态函数,而是确保它们执行的逻辑通过调用函数的不同测试得到充分测试.

  • 如果你不直接测试函数,那不是单元测试. (4认同)

Dus*_*ara 5

静态函数本质上是公共(即公开的)函数的辅助函数。因此,IMO,您的单元测试应使用可行使静态函数中所有路径的输入来调用公共接口。

公共功能的输出(返回值/副作用)应用于测试静态效果。

这意味着您需要有适当的存根来“捕获”这些副作用。(例如,如果函数调用文件IO,则需要提供存根以覆盖这些文件IO lib函数)。最好的方法是将每个测试套件都设置为单独的项目/可执行文件,并避免链接到任何外部lib函数。您甚至可以模拟C函数,但这是不值得的。

无论如何,这是我到目前为止使用的方法,它对我有用。祝好运

  • 然而,自下而上测试的要点是,您不需要“调用执行静态函数中所有路径的公共接口”。否则,就像在测试汽车时,您还要检查每个螺母和螺栓是否符合其规格。最好分别测试螺母和螺栓的生产,如果可以的话,您只需检查汽车的驱动是否正确即可。不确定我解释得那么好...... (3认同)

A. *_*lov 5

如果你是Unix环境下您可以在测试文件附加头yourheader_static.h与你的静态函数的声明和翻译OBJ文件code_under_test.o通过objdump --globalize-symbols=syms_name_file全球化的局部符号。它们将像非静态函数一样可见。