这几天使用Winrunner录制公司的软件,发现WR对公司Grid控件的支持不理想,WR将Grid映射为一个object类,并通过鼠标的坐标进行点击和输入等操作,脚本维护和移植性较差。于是我想另写一个函数,能绕过坐标这种方法。
首先大概介绍一下公司软件和Grid控件的一些情况。公司几乎所有的程序都主要以Gird表来表示,研发部门采用统一的平台处理,平台提供数据库和基本控件,所有项目组开发的软件都基于平台,或通过编辑器自定义界面显示(Grid中行高列宽以及是否可编辑都自定义显示)。
WR对公司Grid只能识别成一个object对象,但这个对象中没有行列和单元格的属性,更不要说单元格内的数据了。如果我点击某一个单元格,让其处于编辑状态,则WR会识别出这个单元格为一个Edit控件,即是说我对单元格进行编辑的时候Grid会生出一个Edit的子对象。当编辑完毕按回车后这个Edit对象又消失了。
我最初的思路是找到Grid的“后台数据库”,通过对数据库的读取判断单元格中数值是否正确。但与开发人员沟通后才知道公司Grid的数据库是自己编写的,只能通过特定的工具打开文件,且Grid中单元格的数据并不是实时保存到磁盘,当Edit控件将输入值提交给Grid后其数值还是保存在内存里。读取内存?不太可能,于是只能放弃这条路。
从“后台”的方法走不通,则只能从界面下手。前面说到各项目组可以通过编辑工具自定义Grid的行高列宽,以及显示哪些列,且各地区配置都会不同。如果在界面上以坐标计算来定位某个单元格会很不可靠,绕过坐标,我采用一个很笨的方法:键盘。首先定位到这个Grid表最左上角的那个单元格,之后通过横向和纵向的移动来找到某一个单元格,并输入或读取数据。
这里我编写了两个简单的函数:set_grid_value,get_grid_value。一个向单元格输入数据,一个从单元格读取数据。通过其他脚本调用,并传递想要横向和纵向移动的格数即可
脚本和函数如下(逻辑名称等有修改):
主脚本:
#########################################################################
set_window ("Grid表", 2);
load(".\\GridFunction"); #load模块GridFunction,那里定义了函数
set_grid_value("TGrid",2,1,"dionysus"); #TGrid为WR识别的公司Grid的逻辑名,2表示向右移动两格,1表示向下移动一格,输入dionysus
rc = get_grid_value("TGrid","TEdit",2,1); #TGrid表示Grid的逻辑名,TEdit表示处于编辑状态时生成的那个Edit对象逻辑名,2、1与上面那个函数一样
pause(rc); #最后看一下是否得到指定单元格的内容
#########################################################################
模块GridFunction
#########################################################################
function set_grid_value(in logicalname,in x,in y,in value)
{
# 传入参数说明:logicalname-grid控件的逻辑名称,左上角单元格坐标为0,0,向下、向右一格都相应加1,x、y为你要取得的单元格相对于它的坐标,value-这个单元格的数值
static i;
static j;
obj_type (logicalname,"<kHome_E><kPgUp_E>"); # 光标定位于左上角的单元格
for(i=0;i<x;i++) # 根据传入的x值做横向移动
{
obj_type (logicalname,"<kRight_E>");
}
for(j=0;j<y;j++) # 根据传入的y值做纵向移动
{
obj_type (logicalname,"<kDown_E>");
}
obj_type(logicalname,"<kReturn>"); #回车,处于编辑状态
obj_type(logicalname,value); #输入数值
obj_type(logicalname,"<kReturn>"); #回车确认
}
function get_grid_value(in logicalname1,in logicalname2,in x,in y)
{
# 传入参数说明:logicalname-grid控件的逻辑名称,左上角单元格坐标为0,0,向下、向右一格都相应加1,x、y为你要取得的单元格相对于它的坐标,value-这个单元格的数值
static i;
static j;
static text;
obj_type (logicalname1,"<kHome_E><kPgUp_E>"); # 光标定位于左上角的单元格
for(i=0;i<x;i++) # 根据传入的x值做横向移动
{
obj_type (logicalname1,"<kRight_E>");
}
for(j=0;j<y;j++) # 根据传入的y值做纵向移动
{
obj_type (logicalname1,"<kDown_E>");
}
obj_type(logicalname1,"<kReturn>"); #回车,处于编辑状态,同时让Grid生成子对象Edit
edit_get_info(logicalname2,"value",text); #使用edit函数得到value属性
return text; #返回value
}
#########################################################################
这个脚本和函数是可以运行成功的,其实思路很简单。但同时这里遇到几个问题:
1、无法判断移动到的单元格是否可编辑。
2、get_grid_value函数必须得到子对象Edit的逻辑名,如果不给出的话get_info函数不能得到value属性(如果这里用Grid的逻辑名代替,则取不出值,因为Grid没有value属性,只有子对象Edit有value属性),对比于set_grid_value函数,它输入数值时obj_type("Grid逻辑名",value)即可。
另一种方法是将单元格内容复制出来,这样就不用get_info等函数,WR中有没有函数能取得剪切板里的内容?还请高手提示
3、get_grid_value函数不能取得不可编辑单元格内的数值。这个是最大的缺陷!
已经和开发人员沟通,希望他们能添加一个功能,支持对焦点所在单元格数据的复制,如果能实现的话则会大大减轻自动化脚本的复杂度,并能通过WR验证更多的功能。这个还需要静等几天,未完待续...
ps:通过键盘定位单元格还有一种方法,就是首先找到某一个单元格,再根据其位置寻找另一个。如我首先定位到内容为“dionysus”的单元格,之后右移两格就到了该输入性别的单元格。这样定位要快于每次都从左上角开始移动,但我的机器总对obj_find_text函数支持不好,不是找不到就是桌面重启,于是只能用笨方法了。