C语言 如何手动执行单元测试



实现手动单元测试背后的架构是什么?如果要根据执行路径或失败路径相应地返回值,如何让这些返回的值有效地解释它?我要求答案与C语言相关。

我建议你考虑用C语言进行单元测试,就像它在任何xUnit框架中的工作方式一样。

在 xUnit 中,测试被分组到"套件"中(每个要测试的类一个套件是常见的(,并且每个函数都有一个或多个测试。 在运行套件中的测试之前调用安装函数,在该套件中的所有测试完成后调用拆解函数。

由于您的语言没有类,因此您可以将这些函数指针存储在函数指针的结构中,并且可以循环访问它们的数组,进行设置、测试和拆卸。

如果你愿意,你当然可以引入一个单元测试框架。 有许多可用于 C 语言。 您可以在维基百科上看到一个列表。

如果你不想把所有的东西都大而正式,这里有一个完全用 C 实现的简单单元测试框架的例子,以及一个带有一些示例单元测试的示例"附加"应用程序。 其中一个测试旨在故意失败,以便您可以看到失败的测试如何响应。 最后,有一个测试执行应用程序的示例。 单元测试框架不必全部大而重量级才能非常有效。


这两个模块是整个测试框架。

testFramework.h

/* testFramework.h */
#pragma once
typedef struct 
{
  int(*test)();
} UNITTEST;
typedef struct
{
  void(*setup)();
  void(*teardown)();
  UNITTEST *tests;
} UNITTESTSUITE;
extern int callTest(UNITTEST *test);
extern int callTestSuite(UNITTESTSUITE suite);
extern void testFailed(const char* testName, const int testLine, const char* message);
#define TESTFAILED(X) testFailed(__FILE__, __LINE__, X)

testFramework.c

/* testFramework.c */
#include <stdio.h>
#include <stdlib.h>
#include "testFramework.h"
int callTest(UNITTEST *test)
{
  return (*test).test();
};
int callTestSuite(UNITTESTSUITE suite)
{
  int rc = 1;
  UNITTEST* test = suite.tests;
  if (suite.setup)
    (suite.setup());
  while (test->test != 0)
  {
    if (callTest(test++))
    {
      printf(".");
    }
    else
    {
      printf("#");
      rc = 0;
    }
  }
  if (suite.teardown)
    (suite.teardown());
  printf("n");
  return rc;
}
void testFailed(const char* testName, const int testLine, const char* message)
{
  fprintf(stderr, "%s(%i): ERROR test failed, %sn", testName, testLine, message);
};

这是我需要测试的应用程序代码。

加法.h

/* addition.h */
#pragma once
extern int add(int x, int y);

增补.c

/* addition.c */
#include <stdio.h>
#include <stdlib.h>
int add(int x, int y)
{
  return x+y;
};

以下是证明我的应用程序有效的单元测试。

另外测试.h

/* additionTests.h */
#pragma once
#include "testFramework.h"
extern void setupAdd();
extern void teardownAdd();
extern int testAddPositives();
extern int testAddFaultyTest();
extern int testAddNegatives();
extern int testAddMixed();
extern int testAddZeroes();
extern UNITTEST additionTests[];
extern UNITTESTSUITE additionSuite;

另外测试.c

/* additionTests.c */
#include <stdio.h>
#include <stdlib.h>
#include "testFramework.h"
#include "addition.h"
void setupAdd()
{
  return;
};
void teardownAdd()
{
  return;
};
int testAddPositives()
{
  int x=2, y=3;
  int expected = 5;
  int actual;
  actual = add(x,y);
  if (actual != expected)
  {
    TESTFAILED("actual not equal expected");
    return 0;
  }
  return 1;
};
int testAddFaultyTest()
{
  int x=2, y=2;
  int expected = 5;
  int actual;
  actual = add(x,y);
  if (actual != expected)
  {
    TESTFAILED("actual not equal expected");
    return 0;
  }
  return 1;
};
int testAddNegatives()
{
  int x=-2, y=-3;
  int expected = -5;
  int actual;
  actual = add(x,y);
  if (actual != expected)
  {
    TESTFAILED("actual not equal expected");
    return 0;
  }
  return 1;
};
int testAddMixed()
{
  int x=2, y=-3;
  int expected = -1;
  int actual;
  actual = add(x,y);
  if (actual != expected)
  {
    TESTFAILED("actual not equal expected");
    return 0;
  }
  return 1;
};
int testAddZeroes()
{
  int x=0, y=0;
  int expected = 0;
  int actual;
  actual = add(x,y);
  if (actual != expected)
  {
    TESTFAILED("actual not equal expected");
    return 0;
  }
  return 1;
};
/* add each additional unit test to this array */
UNITTEST additionTests[] = {&testAddPositives, &testAddFaultyTest, &testAddNegatives, &testAddMixed, &testAddZeroes, 0 };
UNITTESTSUITE additionSuite = {&setupAdd, &teardownAdd, additionTests};

最后,这是我的测试框架应用程序运行程序。

testMain.c

/* testMain.c */
#include <stdio.h>
#include <stdlib.h>
/* include the unit test .h files here */
#include "additionTests.h"
int main(int argc, char**argv)
{
  /* call each unit test suite here */
  if (callTestSuite(additionSuite))
    return 0;
  return 2;
};

只需围绕您的代码编写一些代码。 您可以使用 C 标准库 assert 之类的东西。 假设您有一个函数int foo(int)应该为输入2返回1。 您是手动单元测试:

#include <assert.h>
#include "foo.h"
int main() {
    assert(foo(2) == 1);
}

显然,你会想要比这个玩具例子更坚固。

相关内容

  • 没有找到相关文章

最新更新