你笑的时候全世界陪你一起笑,你哭的时候只有你一个人哭

Winrunner中的脚本和函数调用

上一篇 / 下一篇  2006-12-12 15:38:08 / 个人分类:Winrunner 技术

Winrunner与Robot不同,它的每一个脚本并不是以函数(Function)或子程序(Sub)来圈定的,就是说脚本从头到尾都是录制操作生成的语句,没有头和尾的具体划分,对于脚本和函数的调用方式与Robot有很大不同。

Robot对脚本的调用或者使用Callscrīpt,或者使用Call,一个是不需要传递参数的调用,纯粹是脚本调脚本,另一个则是对脚本中函数(Function)或子程序(Sub)的调用,可以传递参数(具体见我写的关于Robot函数调用的文章)。那么Winrunner中脚本和函数是又怎样调用的呢?下面我就WR8.2版本中调用的方法详细的说明一下。

脚本的模块化是应该始终坚持的一个方向,在WR8.2中我同样希望建立一个main脚本和若干个子脚本。但其中我们会涉及到如下几个不同的调用方式:

1.只是调用另一个脚本,不传递参数,需要一个脚本的返回值

2.调用另一个脚本,传递参数并需要多个脚本的返回值

3.调用另一个脚本中的函数,需要多个函数中的返回值

4.调用另一个脚本,给这个脚本传递参数,并根据参数判断执行脚本中的函数,需要函数的返回值

举一个最简单的例子,演示不同的情况。

第一种情况:只是调用另一个脚本,不传递参数。

新建一个主脚本:main,里面做GUI文件加载和开启记事本程序:

#############################################################################

GUI_close_all();
if (GUI_load(".\\notepad.gui")!=0)
{
 report_msg("gui load error");
}
else
{
 report_msg("gui load ok");
}


 if (invoke_application("c:\\windows\\system32\\notepad.exe","","",SW_SHOW)!=0)
 {
  report_msg("notepad error");
 }
 else
 {
  report_msg("notepad ok");
 }

re1 = call ".\\notepadinput"();  

#记住call函数的使用句式,给出相对路径下的子脚本名称,括号中不需要传递参数,re1将得到脚本notepadinput的返回值,如果不想取得返回值的话则只用call即可。

############################################################################

新建一个子脚本:notepadinput,录制对记事本的输入:

############################################################################


 set_window ("无标题 - 记事本", 1);
 edit_set_insert_pos ("Edit", 0, 0);
 obj_type ("Edit","123");
 obj_type ("Edit","<kReturn>");
 
 edit_get_text("Edit",text);
 
 treturn text;
 

#脚本的返回语句是treturn

############################################################################

 可以看到上面的这个例子是最简单的一个种调用,子脚本中都是录制生成的语句(没有开头和结尾的圈定,请与Robot对比),最后一个treturn语句是脚本的返回值。

 

第二种情况:调用另一个脚本,传递参数并需要多个脚本的返回值

对脚本进行参数的传递和返回需要在脚本属性中进行设置,具体操作是新建一个子脚本notepadinput在File-〉Test properties 在弹出的提示框中选择Parameters页签,这里可以设置这个脚本中的传入参数和传出参数。我们在“input parameters”中新建两个参数:notepadinput1,notepadinput2(最好给出描述),在“output parameters”中新建两个参数:result1,result2。保存设置并推出,接下来开始对主脚本main和子脚本notepadinput进行编辑。

主脚本:main

###########################################################################

GUI_close_all();
if (GUI_load(".\\notepad.gui")!=0)
{
 report_msg("gui load error");
}
else
{
 report_msg("gui load ok");
}


 if (invoke_application("c:\\windows\\system32\\notepad.exe","","",SW_SHOW)!=0)
 {
  report_msg("notepad error");
 }
 else
 {
  report_msg("notepad ok");
 }

re1 = call ".\\notepadinputscrīpt"(1,2,result1,result2);    #这里一定要写上result1,result2

pause (result1);
pause (result2);

#与第一种情况的不同之处就是call语句需要传递参数了,括号中的1,2分别对应我们在notepadinput脚本设置中新建的两个input parameters:notepadinput1,notepadinput2。下面的弹出框分别显示notepadinput中的两个output parameters:result1,result2。

###########################################################################

接下来我们看看子脚本notepadinput是怎样处理传入和返回参数的:

###########################################################################


 set_window ("无标题 - 记事本", 1);
 edit_set_insert_pos ("Edit", 0, 0);
 obj_type ("Edit",notepadinput1);
 obj_type ("Edit",notepadinput2);
 
 edit_get_text("Edit",text);
 result1 = text;
 result2 = result1+1;
 treturn result2+1;

#obj_type函数中输入内容部分直接用脚本的传入参数代替。Edit_get_text函数取得的内容赋值给脚本的传出参数,最后脚本还可以使用treturn语句返回一个脚本的返回值。

###########################################################################

执行脚本后可以看到notepadinput1=1,notepadinput2=2,text=12,result1=12,result2=13,脚本的返回值赋给main中的re1=14。

从这个例子可以看出,如果我们希望给脚本传递并得到多个参数,可以使用脚本属性里的参数设置来达成,而无须像Robot一样对脚本中的Function或Sub Declare(Robot对脚本的调用Callscrīpt是不能有参数的)。这就是WR脚本调用的一个好处。

 

第三种情况:调用另一个脚本中的函数,需要多个函数中的返回值

脚本中不仅可以录制操作,同样也可以编写函数。还是新建一个子脚本Function,需要在脚本属性中设置test type为Compiled Module(试验了一下发现不设置也没有报错)不用设置传入传出参数。在Function中编写如下函数:

###########################################################################

function notepad1(in notepadinput,out result1,out result2)  #函数的参数有三种类型:in为传入参数,out为传出参数,inout为传入和传出参数
{
  static text;   #记住这里需要声明text,因为下面的edit_get_text函数用到了这个参数,但本函数中没有
 
# 无标题 - 记事本
 set_window ("无标题 - 记事本", 1);
 edit_set_insert_pos ("Edit", 0, 0);
 obj_type ("Edit",notepadinput);
 
 edit_get_text("Edit",text);
 
 result1 = text+1;
 result2 = text+2;

}

function notepad2(in notepadinput)
{
 static text;

# 无标题 - 记事本
 set_window ("无标题 - 记事本", 3);
 edit_set_insert_pos ("Edit", 0, 0);
 obj_type ("Edit",notepadinput);
 
 
 edit_get_text("Edit", text);
 
 return text;  #return为函数中的返回值

}
###########################################################################

主脚本main中同样需要做一些改动:

###########################################################################


GUI_close_all();
if (GUI_load(".\\notepad.gui")!=0)
{
 report_msg("gui load error");
}
else
{
 report_msg("gui load ok");
}


 if (invoke_application("c:\\windows\\system32\\notepad.exe","","",SW_SHOW)!=0)
 {
  report_msg("notepad error");
 }
 else
 {
  report_msg("notepad ok");
 }

load(".\\function");  #这个是加载编译模块,加载后就可以在主脚本中直接使用编译模块里的函数了

re1 = notepad1(15,result1,result2);   #直接使用Function中的函数notepad1,15为传入参数,result1和result2为传出参数。
re2 = result1;
re3 = result2;
re4 = notepad2(8);   #使用Function中的notepad2函数

###########################################################################

执行脚本可以正确得到数值,注意使用函数的时候一定要把函数的所有参数都写出,不管是传入的还是传出的。如果没有写传出参数,如主脚本中只是re1 = notepad(15);re2 = result1;re3 = result2;则result1和result2在主脚本中是无法得到数值的(在Function子脚本中可以有值)。切记!!

 

第四种情况:调用另一个脚本,给这个脚本传递参数,并根据参数判断执行脚本中的函数,需要函数的返回值

这种情况比较复杂,脚本参数和函数参数都使用到了。结合上面介绍的方法,我们先建立一个子脚本notepadinput,在脚本属性中建立两个input参数:mode(用来判断执行脚本中的哪个函数),notepadinput(用来给脚本中的函数传参),编写语句如下:

###########################################################################

function notepad1(in notepadinput)          #第一个函数,notepadinput是脚本中定义的传入参数
{
  static text;
 
# 无标题 - 记事本
 set_window ("无标题 - 记事本", 1);
 edit_set_insert_pos ("Edit", 0, 0);
 obj_type ("Edit",notepadinput);
 
    edit_get_text("Edit",text);

 return text;                 #第一个函数的函数返回值

}

function notepad2(in notepadinput)        #第二个函数,notepadinput是脚本中定义的传入参数
{
 static text;

# 无标题 - 记事本
 set_window ("无标题 - 记事本", 3);
 edit_set_insert_pos ("Edit", 0, 0);
 obj_type ("Edit",notepadinput);

 
 edit_get_text("Edit", text);

 return text;        #第二个函数的函数返回值

}

switch(mode)        #mode是脚本定义的传入参数,用来判断运行哪个函数
{
 case 0:
 {
  re = notepad1(notepadinput);   #函数在本脚本内,可以直接使用
  treturn re;                                      #将函数的返回值作为脚本返回值
  break;                                             #跳出switch
 }
 case 1:
 {
  re = notepad2(notepadinput);
  treturn re;
  break;
 }
}

###########################################################################

主脚本main修改如下:

###########################################################################


GUI_close_all();
if (GUI_load(".\\notepad.gui")!=0)
{
 report_msg("gui load error");
}
else
{
 report_msg("gui load ok");
}


 if (invoke_application("c:\\windows\\system32\\notepad.exe","","",SW_SHOW)!=0)
 {
  report_msg("notepad error");
 }
 else
 {
  report_msg("notepad ok");
 }

re1 = call ".\\notepadinput"("8",0);       #调用脚本,传递notepadinput和mode,这个调用将执行子脚本的第一个函数
pause (re1);           #re1得到的是子脚本的脚本返回值,即treturn的值

re2 = call ".\\notepadinput"("5",1);      #调用脚本,传递参数,执行第二个函数
pause (re2);

###########################################################################

执行脚本可以看到我们从主脚本中设置不同的参数将会影响到子脚本执行哪个函数,这对于实际操作中也是很常见的,但逻辑稍显混乱,维护起来有些麻烦。

WR的脚本和函数调用丰富多样,既可以脚本传参也可以脚本中的函数传参,对于学者来说很易混乱。我将常见的几种调用方法总结如上,算是使用上的归类,也许存在一些错误,希望能得到高手们的指点。


TAG:

双面人的个人空间 引用 删除 双面人   /   2008-01-07 16:57:55
问题已解决,再次谢谢dionysus
dionysus的个人空间 引用 删除 dionysus   /   2008-01-06 18:41:18
是不是你没有在脚本属性里设置对需要传递的参数?
双面人的个人空间 引用 删除 双面人   /   2008-01-04 15:35:57
我在调试第二种情况时,出现 Warning :Test .\notepadinputscript:too many arguments.
怎么解决,谢谢
dionysus的个人空间 引用 删除 dionysus   /   2007-08-06 22:02:56
mode和notepadinput需要你在子脚本的test properties中设置
你的WR没有正确识别notepad,这很奇怪,因为Windows的notepad是最基本的一个程序。你打开WR的时候可以吧pb和vb插件都勾选,并且保证gui map中有notepad和其edit的map文件,我运行过这个程序,可以正确传递参数
引用 删除 yuquan_32   /   2007-08-06 12:05:41
跟蹤執行,發現子腳本中沒有接到mode及notepadinput的值.故將
re1 = call ".\\notepadinput"("8",0);      
re2 = call ".\\notepadinput"("5",1);      
用下代碼替代
mode = 0;
notepadinput = 8;
re1 = call ".\\notepadinput"(mode,notepadinput);            
mode = 1;
notepadinput = 5;
re2 = call ".\\notepadinput"(mode,notepadinput);      

保存執行后,當運行到子腳本時,就要重新LEARN對象,LEARN后的結果為
原:
set_window ("未命名 - 記事本", 1);
edit_set_insert_pos ("Edit", 0, 0);
obj_type ("Edit",notepadinput);
edit_get_text("Edit",text);
LEARN后自動用"未命名 - 記事本"替換掉"Edit".
set_window ("未命名 - 記事本", 1);
edit_set_insert_pos ("未命名 - 記事本", 0, 0);
obj_type ("未命名 - 記事本",notepadinput);
edit_get_text("未命名 - 記事本",text);
請問這是什麼原因?我該如何做才能避免呢?
引用 删除 yuquan_32   /   2007-08-06 09:10:23
謝謝,好的,偶試一下.
dionysus的个人空间 引用 删除 dionysus   /   2007-08-05 19:14:40
你可以使用Ctrl_L+F8来单步跟踪一下,并对你要观测的变量插入到watch list中,看看每一步执行的时候变量是否正确赋值
引用 删除 yuquan_32   /   2007-08-03 16:00:17
第四種情況:调用另一个脚本,给这个脚本传递参数,并根据参数判断执行脚本中的函数,需要函数的返回值

根據上述描述練習,可我主函數種的返回值re1和re2怎碼會都是空呢.查找了半天也沒找到原因.可否提示一下下.
dionysus的个人空间 引用 删除 dionysus   /   2007-01-31 16:58:41
不用客气,参数传递在实际应用中较常见,而且刚接触的时候确实复杂
majesty的个人空间 引用 删除 majesty   /   2007-01-30 23:10:45
不错的文章,支持
fengyun407的个人空间 引用 删除 fengyun407   /   2007-01-28 21:15:14
谢谢你在bbs中解答,终于解决了
fengyun407的个人空间 引用 删除 fengyun407   /   2007-01-27 11:46:18
第二种情况:调用另一个脚本,传递参数并需要多个脚本的返回值

我按照你的步骤进行,但为什么再Main主脚本中的result1和result2都没有值?
 

评分:0

我来说两句

Open Toolbar