【问题标题】:How to structure static function tests in C?如何在 C 中构造静态函数测试?
【发布时间】:2015-06-02 06:05:38
【问题描述】:

我无法编译任何合理的结构来对模块的帮助程序/静态函数进行单元测试。几乎所有这个模块都是静态函数并且它有很多,所以我尽量不要把我所有的测试放在同一个文件中。具体(大量)错误是: /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 11

但我对可以编译的通用方法感兴趣。

从命令行,首先安装 Cunit:

# Install cunit
sudo apt-get install libcunit1 libcunit1-doc libcunit1-dev

module_a.c:

#include <stdio.h>

int main(void)
{
  // Do the real thing
  printf("The number 42: %d\n", get_42());
  printf("The number 0: %d\n", get_0());

  return 0;
}

static int32_t get_42(void)
{
  return 42;
}

static int32_t get_0(void)
{
  return 42;
}

module_a_tests.c:

#define UNIT_TEST
#include "module_a.c"
#include "CUnit/Basic.h"
#ifdef UNIT_TEST

int set_up(void)
{
  return 0;
}

int tear_down(void)
{
  return 0;
}

void run_good_fn(void)
{
  CU_ASSERT(42 == get_42());
}

void run_bad_fn(void)
{
  CU_ASSERT(0 == get_0());
}

int main(void)
{
  CU_pSuite p_suite = NULL;

  // Initialize
  if (CU_initialize_registry() != CUE_SUCCESS) {
    return CU_get_error();
  }

  p_suite = CU_add_suite("First Suite", set_up, tear_down);
  if (p_suite == NULL) {
    goto exit;
  }
  CU_basic_set_mode(CU_BRM_VERBOSE);

  // Add tests
  if (CU_add_test(p_suite, "Testing run_good_fn", run_good_fn) == NULL) {
    goto exit;
  }

  if (CU_add_test(p_suite, "Testing run_bad_fn", run_bad_fn) == NULL) {
    goto exit;
  }

  // Run the tests
  CU_basic_run_tests();

  exit:
    CU_cleanup_registry();

  return CU_get_error();
}
#endif

相关:

How to test a static function

【问题讨论】:

  • 肯定在module_a.c 中你不应该以#define UNIT_TEST 开头,因为它应该由包含它的单元测试文件设置?
  • 是的。这意味着 module_a.c 不能有一个 main。正在编辑...

标签: c unit-testing unix


【解决方案1】:

这有点笨拙,但解决此问题的一种方法是在正确的位置使用#include 作为原始文本替换(在所有静态函数的前向声明之后)。对位置有依赖性,但如果您遵循约定,则很容易理解:

module_a.c:

#include <stdio.h>

// Comment this macro in and out to enable/disable unit testing
#define UNIT_TEST

static int32_t get_42(void);
static int32_t get_0(void);

#ifndef UNIT_TEST
int main(void)
{
  // Do the real thing
  printf("The number 42: %d\n", get_42());
  printf("The number 0: %d\n", get_0());

  return 0;
}
#else
#include "module_a_tests.c"
#endif

static int32_t get_42(void)
{
  return 42;
}

static int32_t get_0(void)
{
  return 42;
}

module_a_tests.c:

// Add a #include guard
#ifndef MODULE_A_TESTS_C
#define MODULE_A_TESTS_C

#include "CUnit/Basic.h"

int set_up(void)
{
  return 0;
}

int tear_down(void)
{
  return 0;
}

void run_good_fn(void)
{
  CU_ASSERT(42 == get_42());
}

void run_bad_fn(void)
{
  CU_ASSERT(0 == get_0());
}

int main(void)
{
  CU_pSuite p_suite = NULL;

  // Initialize
  if (CU_initialize_registry() != CUE_SUCCESS) {
    return CU_get_error();
  }

  p_suite = CU_add_suite("First Suite", set_up, tear_down);
  if (p_suite == NULL) {
    goto exit;
  }
  CU_basic_set_mode(CU_BRM_VERBOSE);

  // Add tests
  if (CU_add_test(p_suite, "run_good_fn", run_good_fn) == NULL) {
    goto exit;
  }

  if (CU_add_test(p_suite, "run_bad_fn", run_bad_fn) == NULL) {
    goto exit;
  }

  // Run the tests
  CU_basic_run_tests();

  exit:
    CU_cleanup_registry();

  return CU_get_error();
}
#endif

【讨论】:

  • 由于很多地方都禁止使用 goto .. 在 module_a_tests.c 中,您能否替换每个“goto exit;”说“return cleanExit();”并有一个助手“int cleanExit()”,它在你退出后只有两行代码:标签?或者由于特定的测试框架,这是否会不起作用?抱歉没有标记,一直没弄明白。
猜你喜欢
  • 1970-01-01
  • 2011-05-06
  • 2011-10-07
  • 2011-04-19
  • 2011-07-16
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 2014-03-14
相关资源
最近更新 更多