首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Ceedling中使用静态全局变量测试函数

在Ceedling中使用静态全局变量测试函数
EN

Stack Overflow用户
提问于 2020-05-09 14:52:00
回答 4查看 1.2K关注 0票数 1

如何在Ceedling中为使用静态全局变量的函数编写测试?我想测试变量的每个可能值,以实现良好的测试覆盖率。

代码语言:javascript
复制
//Pseudo code for file_under_test.c
static int global_var;

int func_under_test(){ 

   switch(global_var){
    case x:
      return some_value;
    case y:
      return some_other_value;
    .
    .
    .
    .
    default:
      return something; 
   }

}
EN

回答 4

Stack Overflow用户

发布于 2020-05-10 18:36:25

这个问题实际上与Ceedling (或Unity,CMock等)没有任何特别的关系,但我认为这是一个以非常具体的方式解释“单位”这个词的例子。简而言之,您在这里编写的示例函数并不真正构成一个自包含的“单元”,因此我认为这不是真正的“单元可测试”。

只有当一个“函数”是一个纯函数,或者如果你能找到一个合适的接缝(例如存根、间谍或外部接口的模拟)时,才把“函数”当作一个“单元”!否则,您需要检查测试中的实现细节,这会使测试变得非常脆弱。

为了拥有一个可测试代码的“单元”,你需要能够看到被测单元的效果(例如,比较返回值和/或检查其他副作用),并且能够刺激被测单元(例如,通过向函数传递参数或者首先设置一些被测单元所依赖的副作用)。

示例函数依赖于其他函数的副作用(该函数的副作用是修改静态的“全局”变量),因此在这种情况下,“适当的单元”需要包括触发这些副作用的任何函数。我假设您的文件已经至少有一个这样的函数,否则您的示例代码永远不会返回任何不同的*。

*除非您的示例实际上有修改静态变量本身的副作用。在这种情况下,至少应该有一个重置“全局状态”的函数,否则您的测试将不会彼此隔离(即很难使它们与顺序无关)。更好的解决方案是通过像func_under_test(struct some_opaque_type *state)这样的func_under_test参数显式地公开状态的依赖关系,并添加一个struct some_opaque_type *init_for_func_under_test()函数。

TL;DR:如果您的函数不是纯函数(例如,它依赖于隐藏状态和/或本身有副作用),或者如果您没有适当的“接缝”(例如,存根或间谍),那么也要在您的测试单元定义中包括可以修改隐藏状态或验证副作用的函数。

票数 0
EN

Stack Overflow用户

发布于 2020-05-15 03:34:16

这是单元测试C代码中非常常见的问题,我所知道的最常见的解决方案是在测试时定义不存在的static关键字。这需要一些规划,在遗留代码中很难做到,但我计划测试的任何静态字符串都会被其他字符串替换。通常是静态的,或者更好的是TESTABLE_STATIC。

记住,割让和可能的大多数单元测试框架都设置了编译时宏测试,因此您的代码将是

代码语言:javascript
复制
//Pseudo code for file_under_test.c
#ifdef TEST
#define TESTABLE_STATIC 
#else
#define TESTABLE_STATIC static
#endif


TESTABLE_STATIC int global_var;

int func_under_test(){ 

   switch(global_var){
    case x:
      return some_value;
    case y:
      return some_other_value;
    .
    .
    .
    .
    default:
      return something; 
   }

}

然后,在您的测试文件中,您只需将变量视为全局变量

代码语言:javascript
复制
// your ceedling test 
#include <your_functions.h>

extern int global_var;
void test_function_under_test(void)
{
    // your test code setting global_var as needed
    global_var = some_test_value;
    TEST_ASSERT_EQUAL(expected_val, func_under_test());
}

我通常将TESTABLE_STATIC隐藏在一个项目头文件中,或者如果你有一个datatypes.h文件,那么它通常在我的项目中的任何地方都可用。

这也适用于在翻译单元中对静态函数进行单元测试。

票数 0
EN

Stack Overflow用户

发布于 2020-08-20 22:03:38

我使用了一个包装器,它包含了原始的C文件,并添加了一些用于测试的帮助器,这样你就有了一个不变的原始C源代码,但可以访问所有需要的内部结构。

文件wrapped_for_test.h

代码语言:javascript
复制
#include <file_under_test.h>
void set_for_test(int value);

文件wrapped_for_test.c

代码语言:javascript
复制
#include <file_under_test.c>

void set_for_test(int value)
{
  global_var = value;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61692910

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档