一、测试程序编写说明
我们做的终端设备上运行的是QT应用程序,使用自定义的键盘接口。经过测试人员长时间的人机交互测试,来确认系统的功能是否满足需求。现在需要编写一个自动化的测试程序,能够按照预设的脚本执行,比如某个按键需要连续执行10000次,或是通过连续几个按键动作执行特定的业务流程10W次。通过这样的自动测试,可以减轻测试人员的负担,还可以查看触发N次按键后,画面执行N次后的系统的稳定性,如内存使用率,cup使用率等等。
设备有4*4的键盘,包括0-9,C(Call),A,U(up),D(Down),F1,F2功能键,屏幕的不同画面上根据前述按键的动作执行相应的响应动作。
二、测试程序的结构分析
根据上述的简单要求,先分析测试程序的结构如下:
读入的脚本文件可以是TXT文件大概结构如下:
--------Script_Sample.txt------------
3
A 5
R 3 2
U 5
C 6
A 3
其中的第一行表示以下执行的5个动作,分别是按A 、U、C、A键并且每次按键后休息相应的秒数(即后面的数值),其中的R 5 1 行表示以下1行重复再重复5次。脚本文件中R可不写;若不写,表示依次顺序执行,没有循环操作。
测试程序根据这个脚本构造一个链表,链表中的节点表示相应的操作,操作序列中循环动作再列表中构成局部的单向循环列表。
三、测试程序实现主要逻辑
1、定义链表
typedef struct List
{
char operation;
int seconds;
FLAG c_flag;
int i_repeatCnt;
int i_repeatLines;
struct List *nextGp; //指针域
struct List *nextMemeber; //指针域
}List;
List *oprtData_Set;
2、上报输入事件
int reportkey(int fd, uint16_t type, uint16_t keycode, int32_t value)
{
struct input_event event;
event.type = type;
event.code = keycode;
event.value = value;
gettimeofday(&event.time, 0);
if (write(fd, &event, sizeof(struct input_event)) < 0) {
printf("report key error!\n");
return -1;
}
return 0;
}
3、使用尾插法按照脚本中的动作构造按键动作的链表
void TailCreatList(List *L,char * fname) //尾插法建立链表
{
List *tmpData;
List *tail ;
List *groupheader;
int i_repeatNums = 0;
int i_repeatLines = 0 ,i_repeatLines_tmp = 0;
char c_repeatID;
FLAG flag = HEADER;//flag = 1 header
char buffer[512];
char c_repeatFlag;
FILE *infile;
infile=fopen(fname,"r");
tail=L; //NULL
groupheader=tail->nextGp;//NULL
if(infile==NULL)
{
printf("\nFailed to open the file : %s \n",fname);
exit(0);
}
else
{
printf("open success! \n");
}
fgets( buffer, sizeof(buffer), infile );
sscanf( buffer,"%d",&i_stepMaxNum);
printf("i_stepMaxNum = %d \n",i_stepMaxNum);
memset(buffer,0,sizeof(buffer));
while ( fgets(buffer, sizeof(buffer), infile))
{
tmpData=(struct List*)malloc(sizeof(struct List));
if(!tmpData)
{
printf(exit(0);
}
memset(tmpData,0,sizeof(struct List));
tmpData->nextMemeber=NULL;
tmpData->nextGp=NULL;
sscanf(buffer,"%c",&c_repeatFlag);
if(c_repeatFlag == ‘R‘)
{
sscanf( buffer,"%c %d %d",&c_repeatID,&i_repeatNums,&i_repeatLines );
printf( "Repeat = %c , RepeatNums = %d,RepeatLines = %d \n",c_repeatID,i_repeatNums,i_repeatLines );
memset(buffer,0,sizeof(buffer));
continue;
}
else
{
sscanf( buffer,"%c %d",&(tmpData->operation),&(tmpData->seconds));
printf( "Operation = %c , seconds = %d\n",tmpData->operation,tmpData->seconds);
if(i_repeatLines > 0)
{
if(flag==HEADER)
{
groupheader=tmpData;
tmpData->c_flag=flag;
tmpData->i_repeatCnt = i_repeatNums;
flag = MEMBER;
tmpData->nextMemeber=groupheader;
tmpData->nextGp=NULL;
tail->nextGp=tmpData; // 注意连接臃绞?每个Group的头 用 nextGp 指针连接
}
else
{
tmpData->c_flag=flag;
tmpData->nextMemeber=groupheader;
tmpData->nextGp=NULL;
tail->nextMemeber=tmpData; //group中的成员用 nextMemeber 指针相连
}
tail=tmpData; //修改尾指针的位置。
i_repeatLines--;
}
else
{ //--OK!!
flag=HEADER;
groupheader = tmpData;
tmpData->c_flag = flag;
tmpData->nextMemeber=groupheader;
tmpData->nextGp=NULL;
tail->nextGp=tmpData;
tail=tmpData;
}
if(i_repeatLines==0)
{
flag=HEADER;
}
}
memset(buffer,0,sizeof(buffer));
}
tail->nextGp=NULL;
//tail->nextMemeber=NULL;
fclose(infile);
return ;
}
4、构造键盘事件,包括按下和抬起
void PressKeyEvent(char operation, int seconds)
{
uint16_t keycode;
printf("Key-%c ,%3d Sec |",operation,seconds);
keycode = KeyToVal(operation);
reportkey(KB_Fd, EV_KEY, keycode, KEYDOWN);
reportkey(KB_Fd, EV_KEY, keycode, KEYUP);
sleep(seconds);
}
5、按照链表中的数据逐条发送按键事件
void EmitEvent_Test(List *L)
{
List *p=L->nextGp;
int loop=0;
CYCLE_MODE mode_flag = FirstCycle;
printf("-------EmitEvent_Test-------\n");
while(p!=NULL)
{
//printf ("[** %d **,%c,%d,%d] ",p->c_flag, p->operation,p->seconds,p->i_repeatCnt);
PressKeyEvent(p->operation,p->seconds);
if(p->nextMemeber->c_flag != HEADER) //
{
p = p->nextMemeber;
}
else
{
/*
printf("p->nextMemeber Node is [** %d **,%c,%d,%d ]",
p->nextMemeber->c_flag,
p->nextMemeber->operation,
p->nextMemeber->seconds,
p->nextMemeber->i_repeatCnt);
*/
if(mode_flag == FirstCycle && p->nextMemeber->i_repeatCnt >0)
{
loop = p->nextMemeber->i_repeatCnt;
mode_flag = OtherCycle;
p = p->nextMemeber;
loop--;
printf("\n----------------\n");
continue;
}
if( loop > 0 && mode_flag == OtherCycle )//未重复完
{
p = p->nextMemeber;
loop--;
printf("\n----------------\n");
continue;
}
mode_flag = FirstCycle;//恢复默认值
p = p->nextGp;
printf("\n\n");
}
}
}
四、参考源码程序