系列文章目录
LDRA Testbed软件静态分析_操作指南
LDRA Testbed软件静态分析_自动提取静态分析数据生成文档
LDRA Testbed软件静态分析_Jenkins持续集成(自动静态分析并用邮件自动发送分析结果)
LDRA Testbed软件静态分析_软件质量度量
LDRA Testbed软件静态分析_常见问题及处理
LDRA Testbed(TBrun)软件单元测试_操作指南、实例讲解
LDRA Testbed(TBrun)软件单元测试_常见问题及处理
LDRA Testbed(TBrun)软件集成测试_操作指南、实例讲解
LDRA Testbed(TBrun)软件集成测试_常见问题及处理
粉丝问题解答系列文章… …
文章目录
- 系列文章目录
- 前言
- 一、被测代码示例
- 二、单元测试配置
- 1、新建测试工程
- 2、配置编译器
- 三、编写测试用例
- 1、创建测试序列
- 2、创建测试用例
- 3、编写测试用例
- 〇、测试思路
- ①、测试用例1
- ②、测试用例2
- 四、执行测试用例
- 五、扩展分析
- 总结
前言
在之前的文章《LDRA Testbed(TBrun)软件单元测试_操作指南》中,已经讲解了如何使用TBrun进行软件单元测试的基本操作步骤。本篇文章将结合实例进一步讲解被测函数中包含多次调用其他函数时,如何对其打桩来实现测试目的(详细的操作流程本文不再重述,若有不清楚的,可以结合之前的操作指南一起来看)。
一、被测代码示例
本文以C语言编写的一个函数作为示例,被测代码如下:
int get_time_tick_now(void);
void file_operations(void);
int test_func()
{
int ret;
int time_tick_1,time_tick_2;
time_tick_1 = get_time_tick_now();//获取当前时间1
file_operations();//进行文件操作
time_tick_2 = get_time_tick_now();//获取当前时间2
if(time_tick_2 - time_tick_1 > 100)//如果文件操作的时间过长,则返回异常值-1,否则返回1
{
ret = -1;
}
else
{
ret = 1;
}
return ret;
}
这个示例的被测函数非常简单,分别获取文件操作前后的时间,计算文件操作的耗时。如果耗时过长,则返回-1;如果耗时正常,则返回1 。(示例代码,别纠结这段代码有没有具体意义😀)
我们都知道,做单元测试时,被测函数如果有调用其他函数,那么可以将其他被调函数打桩。从而使测试时不用关注原调用函数的具体功能,可以专注于被测函数本身的功能逻辑。常规的函数打桩比较好操作,比如有返回值的函数可以设置其返回值,或者void类型的函数可以直接打空桩等。上述代码中有点特别,get_time_tick_now()函数被调用了两次,每次都需要取其返回值。很显然,常规的打桩让其返回一个固定值无法达到测试目的,我们需要它每次返回不同的值。那么在Testbed(TBrun)中应该如何操作才能达到上述测试目的呢?下面就以此示例代码进行单元测试讲解。
二、单元测试配置
1、新建测试工程
在TBrun的上方菜单栏点击Source -> Single File(单个文件),在弹出的窗口中选择被测的源码文件:
在select file窗口选择被测源码文件:
导入被测源码文件后,TBrun会自动进行分析,分析完成后,会显示出file view和calls view窗口显示相关信息:
2、配置编译器
点击TBrun中上方菜单栏的Configure -> LDRA Testbed Configuration Options -> Switch Compiler进行编译器配置:
在弹出的Configure Compiler窗口中确认Default Compiler和Source Compiler,以选择MinGW200 GCC C/C++ v3.2编译器为例,切换编译器后点击OK即可:
需要注意的是:
1、Default Compiler和Source Compiler都应该选择目标编译器;
2、如果在列表中没有找到对应编译器,可以通过Add Compiler添加需要的编译器(需要先配置编译环境)。
三、编写测试用例
1、创建测试序列
在TBurn中是使用测试序列来管理测试用例和测试数据的,因此在新建测试用例前需要创建序列(为了方便管理,通常一个被测函数创建一个测试序列)。
在TBurn菜单中选择Sequence->New:
输入序列名称(为了方便管理,序列名以函数名命名,比如这里我们就命名为test_func),勾上Code Coverage选项(这样在运行测试用例后才会对代码覆盖率进行统计):
进行单元测试时,在Test Scenarios选项卡选择Isolate fully all code elements选项(完全隔离所有代码元素,即单元测试时,将本单元以外的调用全部默认打桩隔离):
点击“Continue”即可完成测试序列的创建。
2、创建测试用例
在TBurn界面的右上角文件视图窗口中,选中被测函数,鼠标右键->Create New Test Case创建测试用例:
弹出测试用例创建向导窗口,此时窗口会显示函数的相关信息,点击continue:
创建好测试用例后,会在左下角窗口中生成相应的测试用例条目,在右下角会显示该测试用例的默认输入输出列表,如下所示:
3、编写测试用例
〇、测试思路
首先我们需要先理清测试思路:为了要测到上述代码的所有逻辑,那么肯定要让get_time_tick_now()函数第1次和第2次被调用时返回不同的值,应该怎么办呢?
在对test_func()函数进行单元测试时,一般来说,我们需要对它调用的get_time_tick_now()函数打桩。为了让get_time_tick_now()函数在不同的调用次数时返回不同的值,我们可以在桩函数中插入测试代码。添加方式如下:
进入测试用例的桩函数管理界面,可在Variable I/O View界面双击Managed Stubs进入:
也可以选中测试用例,右键选择Stub Management进入:
进入Specify Stub Checking界面后,选中需要进行打桩的函数get_time_tick_now(),右键选择Set Code Segment:
在弹出的Code Segment设置窗口中,添加桩函数代码:
添加代码示例:
static int cnt = 0;
cnt++;
if(cnt == 1)
{
return 100;
}
else if(cnt == 2)
{
return 199;
}
对get_time_tick_now()打桩并添加上述桩函数代码后,第1次调用get_time_tick_now()时会返回100,第2次调用get_time_tick_now()函数时会返回199,以此类推,可按照此思路设置该函数被调用任意次数时的不同返回值或者进行其他逻辑操作。
使用上述思路,然后再根据白盒测试中最常使用的语句覆盖、判定(分支)覆盖、MC/DC覆盖(上述示例代码不涉及MCDC)的覆盖率要求,编写以下测试用例。
①、测试用例1
桩函数设置如下:
对file_operations()函数打空桩,对get_time_tick_now()函数打桩并插入如下代码:
输入输出列表如下:
②、测试用例2
桩函数设置如下:
对file_operations()函数打空桩,对get_time_tick_now()函数打桩并插入如下代码:
输入输出列表如下:
四、执行测试用例
执行上述2条测试用例,全部测试通过,语句、分支覆盖率均达到100%。
五、扩展分析
我们打开Testbed(TBrun)根据测试用例的配置自动生成出来的测试驱动程序,在其中找到被打桩后get_time_tick_now()函数如下:
我们可以看到,我们对用例1、用例2设置的桩代码都生成到了get_time_tick_now()桩函数中,并通过ldra_qq_test_case_number识别了用例编号,避免了冲突。
总结
本文以一个被测函数作为示例,讲解了如何使用Testbed(TBrun)对涉及到多次调用其他函数的被测函数进行单元测试。本文的示例可能比较简单,但是思路、方法和流程都是通用的,希望对大家有所帮助。后续文章将进一步讲解各种特殊场景的测试技巧。