接着上次的过程,继续体验c++test v7.1的自动化测试过程。
今天的测试C文件为test.c,其源代码如下:
extern int get_oil_pressure(void);
extern int get_bus_status(void);
void Pointer_Arithmetic (void)
{
int array[100];
int i, *p = array;
for(i = 0; i < 100; i++)
{
*p = 0;
p++;
}
if(get_bus_status() > 0)
{
if(get_oil_pressure() > 0)
{
*p = 5; /* 指针访问越界 */
}
else
{
i++;
}
}
i = get_bus_status();
if (i >= 0) {*(p-i) = 10;}
if ((0 < i) && (i <= 100))
{
p = p - i;
*p = 5;
}
}
代码简单说明一下,被测单元(函数)Pointer_Arithmetic()中调用了两个外部函数,这两个外部函数是其他开发员编写。另外为了简化测试,被测函数没有设计传入参数,对于有参数的函数单元测试请参考本博另外一篇文章http://www.51testing.com/?10851/action_viewspace_itemid_81692.html
今天的意图很明显,就是希望在单元测试中发现该函数中的“指针访问越界”问题。
在使用c++test自动化测试之前,我先使用传统的单元测试手段来简单测试一下,测试使用Visual C++ v6.0环境。
1 根据实际情况,简单编写桩函数(stub)和驱动函数(driver),测试文件stub.c内容如下
int get_oil_pressure(void);
int get_bus_status(void);
extern void Pointer_Arithmetic (void);
/*手动编写的桩函数*/
int get_oil_pressure(void)
{
return 10;
}
int get_bus_status(void)
{
return 10;
}
/*手动编写的驱动函数*/
void main()
{
Pointer_Arithmetic();
}
2 rebuild all,然后执行,执行完成后出错提示,如下图
预示着代码执行中遇到了运行时错误(Run-time Errors),但通过IDE提供的Debug工具不能定位到具体是哪里有错误,需要开发员自己分析代码,才能找到藏在其中的“指针越界错误”。
下面我使用c++test 7.1对以上test.c做自动化的单元测试,看看效果如何。
1 创建新项目Import Microsoft Visual Studio 6.0 Projects,然后导入刚才创建的工程
注意:导入后先删除测试代码stub.c文件
2 先做静态分析:如果静态分析就能发现以上的错误,那就太好了。
执行规则检查,没有发现有价值的信息;执行BugDetective分析,什么都没有提示,预示着c++test没有发现任何错误。
看来是空欢喜一场,c++test的静态分析没有能让我们提前实现目标。
3 再做单元测试:
×Generate Unit Tests:由于被测函数没有参数,所以也不需要测试用例,只需要生成一个调用被测函数的驱动即可。该步骤执行后,生成的测试代码如下
#include "cpptest.h"
CPPTEST_CONTEXT("/test/test.c");
CPPTEST_TEST_SUITE_INCLUDED_TO("/test/test.c");
CPPTEST_TEST_SUITE(TestSuite_test_c_5f7e64d5);
CPPTEST_TEST(TestSuite_test_c_5f7e64d5_test_Pointer_Arithmetic_1);
CPPTEST_TEST_SUITE_END();
void TestSuite_test_c_5f7e64d5_test_Pointer_Arithmetic_1();
CPPTEST_TEST_SUITE_REGISTRATION(TestSuite_test_c_5f7e64d5);
void TestSuite_test_c_5f7e64d5_setUp()
{
}
void TestSuite_test_c_5f7e64d5_tearDown()
{
}
/* CPPTEST_TEST_CASE_BEGIN test_Pointer_Arithmetic_1 */
/* CPPTEST_TEST_CASE_CONTEXT void Pointer_Arithmetic(void) */
void TestSuite_test_c_5f7e64d5_test_Pointer_Arithmetic_1()
{
/* Pre-condition initialization */
{
/* Tested function call */
Pointer_Arithmetic();
/* Post-condition check */
}
}
/* CPPTEST_TEST_CASE_END test_Pointer_Arithmetic_1 */
2 Generate Stubs:c++test可以自动生成桩函数,省去了开发人员自己写桩函数的麻烦。自动生成的桩函数代码如下:
#include "cpptest.h"
/**
* This file contains auto-generated stub definitions.
*
* Available C++test API functions (see C++test Users Guide for details):
* void CppTest_Assert(bool test, const char * message)
* void CppTest_Break()
* const char* CppTest_GetCurrentTestCaseName()
* const char* CppTest_GetCurrentTestSuiteName()
* bool CppTest_IsCurrentTestCase(const char* testCaseName)
*/
/** Auto-generated stub definition for function: int get_oil_pressure(void) */
EXTERN_C_LINKAGE int get_oil_pressure () ;
EXTERN_C_LINKAGE int CppTest_Auto_Stub_get_oil_pressure (void)
{
return 0;
}
/** Auto-generated stub definition for function: int get_bus_status(void) */
EXTERN_C_LINKAGE int get_bus_status () ;
EXTERN_C_LINKAGE int CppTest_Auto_Stub_get_bus_status (void)
{
return 0;
}
从以上代码可以看出,c++test生成的桩函数很简单,直接返回一个值(int类型返回0),好像不大符合实际测试的要求。
3 Build Test Executable,编译链接成可执行的文件
4 Run Unit Tests: 结果显示,c++test在执行过程中没有遇到错误,再看看覆盖率指标,
很多条件分支内的代码没有执行到,再联想到第二步中 2 Generate Stubs生成的桩函数返回值都是0,这些分支当然执行不到。
为了执行到分支内的所有代码,只能修改桩函数,把两个桩函数的返回值都修改为10(和手动编写的桩函数返回值相同),这样起码可以保证基本的覆盖率,修改后的桩函数如下
重复第3-4步骤,看结果
c++test在执行过程中,覆盖率指标已经正常,出错的语句的颜色预示着c++test已经执行过该语句,但遗憾的是还是没有发现任何错误。
怎么会这样呢?Visual C++ 6.0 IDE中都提示的错误现象在c++test中竟然没有任何提示!是不是默认的Run Unit Tests选项中不提示这样的现象?我简单的看了一下Run Unit Tests的选项,没有看到相关的选项。
非常遗憾,今天的体验没有达到预订的目标。
总结一下:
1 c++test提供的只是一个自动化的框架(framework),虽说它可以自动生成桩函数,但大多数情况下,在测试过程中,用户要手动修改桩函数以适应实际测试环境。同样,c++test可以自动生成测试用例,但在某些情况下,用户还需要再手动添加新的测试用例。
建议:用户可以构建自己的桩函数库(如返回随机数的函数等),采用头文件的形式,这样在实际使用过程中会方便。
2 c++test的特色功能BugDetective功能有所创新,几乎没有误报的情况,但和所宣传的功能相比,漏报比较多。
3 c++test只是自动化的工具,它提供了一个自动化的执行框架,大大提高单元测试的效率,但具体到使用效果,还真的要依赖于使用者。
今天就到这里吧,就到这里。