在嵌入式领域和大型软件领域,测试越来越彰显其重要性,公司会投入更多的人力来从事测试工作,在人力成本上升的今天,自动测试软件的需求开始变的越来越火,因为这显然已经直接跟成本挂钩了。
今天写这篇文章算是自己最近工作的一些感想和总结吧,可用于一些小型工程的自动测试软件设计。
首先来想一下自动测试软件的工作的内容,即软件需求。
我们的自动测试软件无论是真的硬件性能的测试或者真的软件功能模块稳健性的测试,对我们来说都可以把她抽象成一个个独立功能的Item(Process或者function),在每一项item里又会有其特定的执行过程,我们可以将这个过程抽象出一个个step,当然这些step对我们来说都是表象的step,没必要去考虑每个step具体的运行环境和执行流程,画个图吧:
对于复杂的系统,每个item采用注册机制是最好的,那需要新增一部分模块,我们对于固定的item和固定的step的设计实现思路,即将他们放入一个固定的数组或链表中进行统一的处理。
先阐述此软件实现需系统提供的基础:
1)定时器,用于实现回调
2)定位当前item是否进行step递进的资源,如场景ID (Screen ID)或某索引ID等
此处我们申请两个定时器,一个用于item的切换,一个用于step的切换,我们这里用伪函数来描述。
我们定义当前item索引为i,当前step索引为s,先阐述定时器的回调:
void ItemHandler(void)
{
items[i].DeInit();
i++;
if(i>ItemNum)i=0;
items[i].Init();//或者应命名为entry
s=0;//reset step index
}
void StepHandler(void)
{
switch(i)
{
case ItemX:
switch(s)
{
case StepX:
{
//do something let step going on
s++;
}
break;
……
}
break;
……
}
}
因为我们假设程序的运行对我们来说是黑盒的,所以下面我们增加timer的机制来增强整个软件的健壮性。
假设系统提供如下伪函数(假设time的单位为ms毫秒)
//申请timer handle
time_handle register_once_timer(int time_count,func callback_fun);
//重启timer handle,此函数用于避免重复申请导致资源消耗
bool restart_once_timer(time_handle th, int time_count,func callback_fun);
有上面的基础,我们实现系统的主要函数:
void ItemTimerStart(int time_count)
{
static time_handle ItemTimerId = 0;
if(0 == ItemTimerId )
{
ItemTimerId = register_once_timer (time_count,(func)ItemHandler);
}
else
{
restart_once_timer (ItemTimerId, time_count,(func)ItemHandler);
}
}
同理step的实现如下:
void StepTimerStart(int time_count)
{
static time_handle StepTimerId = 0;
if(0 == StepTimerId )
{
StepTimerId = register_once_timer (time_count,(func)StepHandler);
}
else
{
restart_once_timer (StepTimerId , time_count,(func)StepHandler);
}
}
假设我们的step是使用screen id来进行判定的,并假设系统提供如下伪函数来获取当前场景id int GetScreenID(void) ;
以此和timer为基础,优化上述handler如下:
void ItemHandler(void)
{
ItemTimerStart(30*60*1000);//设定30分钟超时,用于测试项出现不可预料异常不能正确完成时重启测试项测试
items[i].DeInit();
i++;
if(i>ItemNum)i=0;
items[i].Init();//或者应命名为entry
s=1;//reset step index
}
void StepHandler(void)
{
switch(i)
{
case ItemX:
switch(s)
{
case StepX:
{
if(XXXX_ScreenID == GetScreenID())
{//程序正确运行到此场景
//do something let step going on
s++;
StepTimerStart(5*1000);//5秒后检测是否执行到下一状态
}
else
{//程序还没有运行到此场景,则继续等待
//此处没有对s进行++
StepTimerStart(1000);//每1秒检测一次状态
}
}
break;
……
case StepEnd:
{//表示执行到了最好一步
ItemTimerStart(10);//立即切换至下一项测试
}
break;
}
break;
……
}
}
当然,里面每一项step切换到下一step需要等待的时间最好分具体情况来确定。
此策略的优点在于,用户任意的操作或者 系统其他的事件干扰都不会打断自动测试流程,直到用户手动关闭该软件。