实施手动单元测试的架构是什么?如果要根据执行或失败的路径相应地返回值,我如何获得这些返回值有效地解释它?我要求答案与C语言相关。
答案 0 :(得分:3)
我建议你在C语言中考虑单元测试,就像在任何xUnit框架中一样。
在xUnit中,测试分为"套件" (每个要测试的类一个套件很常见),每个功能有一个或多个测试。在运行套件中的测试之前调用setup函数,并在完成该套件中的所有测试后调用拆卸函数。
由于您的语言没有类,您可以将这些函数指针存储在函数指针的结构中,并且可以遍历它们的数组,进行设置,测试和拆解。
如果您愿意,您当然可以引入单元测试框架。有许多可用于C语言。您可以在Wikipedia上看到一个列表。
如果您不想获得所有大型和官方的,那么这里是一个完全用C实现的简单单元测试框架的示例,另外还有一个示例" add"应用一些样本单元测试。其中一项测试旨在故意失败,以便您可以看到失败的测试如何响应。最后,有一个测试执行应用程序的示例。单元测试框架不一定非常有效且重要。
这两个模块是整个测试框架。
<强> 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, %s\n", testName, testLine, message);
};
这是我需要测试的应用程序代码。
<强> addition.h 强>
/* addition.h */
#pragma once
extern int add(int x, int y);
<强> addition.c 强>
/* addition.c */
#include <stdio.h>
#include <stdlib.h>
int add(int x, int y)
{
return x+y;
};
以下是证明我的申请有效的单元测试。
<强> additionTests.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;
<强> additionTests.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;
};
答案 1 :(得分:0)
只需在代码周围编写一些代码即可。您可以使用C标准库assert
之类的东西。假设您有一个函数int foo(int)
,它应该为输入1
返回2
。你是手动单元测试:
#include <assert.h>
#include "foo.h"
int main() {
assert(foo(2) == 1);
}
显然你会比这个玩具例子更健壮。