博文共赏:SAP自动化准备测试数据:一个基于AutoIt VBS XML的实现思路

SAP是当前知名且领先的ERP系统,在对与 SAP 有交互的软件系统进行测试时,经常需要使用 SAP GUI Client 完成一定的常规操作,例如创建测试数据等。这些操作具备如下特点:需要一定的 SAP 知识和技能;步骤冗长;耗时耗力;重复性强等。为了提高工作效率,降低测试人员和开发人员的工作量,通过自动化的方式来完成数据准备是我们首先想到的方法。Script Center是我们自主开发的一款基于 AutoIt 的 SAP 自动化测试工具,通过它执行操作 SAP 的 VBS 脚本,可快速完成测试数据的准备。用户也可以通过Script Center方便的编辑要创建的数据值,以便创建若干不同的测试数据。

问题的提出

笔者所在的部门是负责开发和测试一个电子商务应用系统,这个系统和SAP交互频繁。我们往往需要在SAP中准备一些测试数据。以前,这些数据的准备工作,通常是手动的在SAP GUI Client中进行操作,参考帮助文档,一步一步执行完成。整个过程耗时耗力,且重复性强,很无趣。另外,这些操作往往比较复杂,通常是由熟悉SAP操作且了解电子商务应用系统的业务逻辑的少数人帮助大家来完成。在任务比较多的阶段,测试数据的需求也多,这些人本来的工作量就很大,所以对于其他人关于创建测试数据的请求有时会延迟处理。所以,项目组迫切需要一种方便、快捷的方式来在SAP中准备测试数据,减轻大家的工作压力,提高工作效率。

方案描述

自动化准备数据是我们首先想到的解决方法,SAP自带了录制和回放功能。最后录制形成的脚本是VBS格式,双击这个VBS文件即可回放。但是单纯的回放脚本并不能满足用户对数据的要求,我们需要参数化这些数据,用户可以根据自己的需要来填写自己想要的数据。因为XML编辑起来没有对软件的特殊要求,可以很方便的进行编辑,最终决定用XML格式来保存这些数据。鉴于用户直接编辑XML可能会导致错误,我们用AutoIt研发出的script center可以对这些数据字段进行友好访问及编辑。Script center还可以对脚本进行集中管理,使得用户有更易用的界面来运行自己需要的脚本。

总体架构设计

图1. 架构图

博文共赏:SAP自动化准备测试数据:一个基于AutoIt VBS XML的实现思路_第1张图片

从架构图可以看到我们Script Center的设计思路,下面从工作流的角度来解释该结构图:

  1. 用户的所有操作只需要在Script Center的GUI上完成;
  2. 通过Script Center查看所有自动化SAP的VBS脚本,并可以执行VBS脚本;
  3. 通过Script Center轻松查看和修改脚本所需的数据文件;
  4. 脚本读取对应数据文件,通过SAP GUI Client对SAP进行操作,完成SAP自动化;
  5. 为方便SAP登录用户的集中维护,Script需要从DB中读取SAP登录信息,脚本执行完成后, 将记录保存到DB,同时生成相应的日志文件。

系统实现

前提:

  1. 客户机需要安装Script Center,SAP GUI Client,AutoIt
  2. DB2 server 上部署Web Service,VBS 脚本通过Web Service和数据库进行交互

AutoIt简介

AutoIt 是用以编写并生成具有 BASIC 语言风格的脚本程序的免费软件,用来在Windows下实现各种自动化任务(比如自动安装目标程序、完成各种自动化操作等)。 通过它可以组合使用模拟键盘按键,鼠标移动和窗口/控件操作等来实现自动化任务, 而且可以利用它开发自己的GUI,以便获得更好的交互效果,另外,它可以把它的Script语言转换成exe可执行程序。

通过AutoIt建立Script Center用户界面

考虑到Script Center的主要功能比较简单,所以选择轻量级的AutoIt来开发主界面,而且AutoIt可以把脚本文件编译为独立的可执行文件,方便 Script Center在不同客户机上运行。 Script Center主界面主要是用于展示脚本文件,然后选择对应的脚本文件配置数据文件, 最后点击运行执行自动化脚本调用SAP GUI Client进行SAP自动化操作。

图2. Script Center主界面

博文共赏:SAP自动化准备测试数据:一个基于AutoIt VBS XML的实现思路_第2张图片

Script Center GUI创建的代码片段,前半部分完成控件的创建,后半部分通过消息循环机制实现操作部分。

清单1. Script Center GUI创建的代码片段
Local $mainwindow = GUICreate("ScriptCenter", 900, 600)
GUISetIcon("Config/scriptcenter.ico")
$label_Title = GUICtrlCreateLabel("Script Center v1", 10, 20, 900, 50)
GUICtrlCreateTab(10, 70, 880, 450)
;;;;;;;;;;;;;;;;;;;;;;;;;;Tab1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$tab1 = GUICtrlCreateTabItem("Execution")
GUICtrlCreateLabel("Script Type", 30, 108, 60, 20)
$comb_tab1_type = GUICtrlCreateCombo("", 95, 105, 80, 20,0x0003)
GUICtrlSetData(-1, "SAP|Web|Other", "SAP")
$bt_tab1_EditDataSource = GUICtrlCreateButton("Edit Data Source", 740,
 105, 100, 25)
$listview_tab1_Script = GUICtrlCreateListView("| Script Name| Key 
Info| Last Run| Author", 30, 140, 830, 320)
GUICtrlListView_SetExtendedListViewStyle($listview_tab1_Script, BitOR
($LVS_NOCOLUMNHEADER, $LVS_SHOWSELALWAYS, $LVS_SINGLESEL))
$bt_tab1_Execute = GUICtrlCreateButton("Execute", 610, 470, 80, 25)
$bt_tab1_Refresh = GUICtrlCreateButton("Refresh", 740, 470, 100, 25)
;;;;;;;;;;;;;;;;;;;;;;;;;;Tab1 End;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; GUI MESSAGE LOOP
GUISetState()
LoadViewList()

While 1
   $msg1 = GUIGetMsg() 
	Switch $msg1
		 Case $GUI_EVENT_CLOSE
			Exit
		 Case $bt_tab1_Execute
			Local $isselected = 0
			;$typeitem = ControlCommand ("ScriptCenter",
" ",$comb_tab1_type,"GetCurrentSelection")
			For $item = 0 To $count
				  $fielitem = $item + 1
				  $file = $FileList[$fielitem]
				  $path1 = GetDir()
				  IF $typeitem =="SAP" Then
					 _RunDos("wscript 
"&$path1&"\script\"&$file)
				  EndIf
			   EndIf
			Next
		 Case $bt_tab1_EditDataSource
			For $item = 0 To $count
			   If _GUICtrlListView_GetItemState
($listview_tab1_Script, $item, $LVIS_SELECTED) Then
			$xmlFile = $path1&"\xml\"&$filedatasource
				   $xmlNodePath = "data/"&$filename[1]
				   RunXMLEditor($xmlFile,$xmlNodePath)
				   GUISetState(@SW_ENABLE)
				   WinActivate("ScriptCenter")
				EndIf
			Next
			If $isselected == 0 Then
			   MsgBox(0,"Message","Please select one item
 before click button")
			EndIf
		 Case $bt_tab1_Refresh
			LoadViewList()	
	EndSwitch
WEnd

通过SAP Client自带工具录制脚本

SAP Client自带脚本录制工具,读者可以通过该工具录制生成vbs脚本。

清单2. 录制脚本范例
If Not IsObject(application) Then
   Set SapGuiAuto  = GetObject("SAPGUI")
   Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
   Set connection = application.Children(0)
End If
If Not IsObject(session) Then
   Set session    = connection.Children(0)
End If
If IsObject(WScript) Then
   WScript.ConnectObject session,     "on"
   WScript.ConnectObject application, "on"
End If
session.findById("wnd[0]").resizeWorkingPane 156,25,false
session.findById("wnd[0]/usr/txtRSYST-BNAME").text = "UserName"
session.findById("wnd[0]/usr/pwdRSYST-BCODE").text = "********"
session.findById("wnd[0]/usr/pwdRSYST-BCODE").setFocus
session.findById("wnd[0]/usr/pwdRSYST-BCODE").caretPosition = 8
session.findById("wnd[0]/tbar[0]/btn[0]").press
session.findById("wnd[0]/tbar[0]/okcd").text = "va03"
session.findById("wnd[0]/tbar[0]/btn[0]").press

通过AutoIt启动SAP Client

因为SAP录制的脚本只能在手动启动SAP Client以后才能通过脚本开始自动操作,所以我们需要利用AutoIt启动SAP Client,封装OpenSAP方法。

清单3. 封装OpenSAP方法
Function OpenSAP720()
	set autoIt = WScript.CreateObject("AutoItX3.Control")
	set wsh = createobject("wscript.shell")
	wsh.run Chr(34)&SAPPath&Chr(34)
	Log1("Open SAP system list")
	WScript.sleep 5000 	
	autoIt.WinWaitActive("SAP Logon 720") 
	autoIt.ControlClick "SAP Logon 720","","[CLASS:Button;
 INSTANCE:7]"
	if testingEnv="LC0" Then
		autoIt.ControlSend "SAP Logon 720","","[CLASS:Edit;
 INSTANCE:1]","lc0"
	end if
	if testingEnv="LC2" Then
		autoIt.ControlSend "SAP Logon 720","","[CLASS:Edit;
 INSTANCE:1]","lc2[d"
	end if	
	autoIt.send "{Enter}"		
	If IsObject(WScript) Then
		WScript.sleep 8000
		Set session = connection.Children(0)
		WScript.ConnectObject session,     "on"
		WScript.ConnectObject application, "on"
	End If
	WScript.sleep 5000 
	session.findById("wnd[0]").maximize
End Function

调整VBS脚本分离数据

根据总体架构的设计,需要把录制好的脚本进行数据和action分离,数据文件独立存入XML中, vbs脚本启动SAP Client,并从XML获得参数执行自动化。

清单4. 改进后的vbs脚本范例
''' include common functions
Dim currentScriptDir
currentScriptDir=getDirOfCurrentScript()
include currentScriptDir&"\"&"CommonFunctions.vbs" 
filename = Split(wscript.scriptname, ".")
' initialzie
Init(filename(0))  '开始执行脚本,并创建和脚本同名的log文件
xmlNode_this = "/data/"&filename(0)&"/" '定义在DataSource中找相同名节点
''''''''''''''''''''' common for all scripts''''''''''''''''''''''''

     '''''''''''''''''''''''' Login SAP''''''''''''''''''''''''''''''
CurrentRegion = GetTextFromXML(xmlNode_this,"CurrentRegion") 
'读所选区域
Log1("CurrentRegion:["&CurrentRegion&"]")
AccountNode = "/data/Account/"&CurrentRegion&"/"  
loginUser = GetTextFromXML(AccountNode,"Account1")  '读对应用户名
'Log in
call Login(loginUser)   '登录方法里call了openSAP方法
    ''''''''''''''''''''''''''''Login SAP''''''''''''''''''''''''''''
    '''''''''''''''''''''''''''Specific part'''''''''''''''''''''''''
session.findById("wnd[0]/tbar[0]/okcd").text = "zvd01"
session.findById("wnd[0]/tbar[0]/btn[0]").press
session.findById("wnd[1]/usr/cmbRF02D-KTOKD").key = "ZCTR"
Sales_Org = GetTextFromXML(xmlNode_this,"Sales_Org")
Log1("Sales_Org:["&Sales_Org&"]")
session.findById("wnd[1]/usr/ctxtRF02D-VKORG").text = Sales_Org
Distribution_
Channel = GetTextFromXML(xmlNode_this,"Distribution_Channel")
Log1("Distribution_Channel:["&Distribution_Channel&"]")
session.findById("wnd[1]/usr/ctxtRF02D-VTWEG").text =
 Distribution_Channel
    ''''''''''''''''''''''''''''Specific part'''''''''''''''''''''''''

    '''''''''''''''''''' common for all scripts''''''''''''''''''''''
KillSAP()
ReleaseOjbects()
Function getDirOfCurrentScript()
	Dim scriptName
	scriptName = wscript.scriptfullname
	dataDir= left(scriptName,instrrev(scriptName,"\")-8)
	getDirOfCurrentScript = dataDir
End Function
Function include(file)
ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile
(file,1).ReadAll
End Function
     '''''''''''''''''''' common for all scripts'''''''''''''''''''''

在Script Center读写数据文件

通过AutoIt生成数据文件(XML)的编辑界面,用户可以通过界面编辑脚本执行所需数据,通过XML的属性来决定在编辑界面上的显示风格。图3是Script Center的数据编辑页面,图4是对应的数据文件格式。

图3. 编辑数据

博文共赏:SAP自动化准备测试数据:一个基于AutoIt VBS XML的实现思路_第3张图片

图4. 数据文件格式

博文共赏:SAP自动化准备测试数据:一个基于AutoIt VBS XML的实现思路_第4张图片

XML格式要求:

  • 根节点命名为data。
  • 展示节点命名应和脚本名字一致,例如上图的CreatePAE节点。
  • 脚本所需用户节点为Account,里面根据不同region创建不同节点,如果一个脚本中需要多个用户多次登录,可以在对应的region下再创建多个用户节点。
  • XML中节点的值将会作为最终SAP脚本需要的值进行调入,完成自动化流程。

XML节点属性值对应的意义:

  • type属性: 如需在Script Center中展示为下拉选框,可以设置该属性值为 “type=combobox”,此属性必须附带items属性使用。
  • Items属性: 下拉选框中的预选值,每个值需要用竖线隔开,例如 items="JP|AM|EM|AP"
  • key属性: key值如果是true,将会在Script Center的list key info中展示出来,方便用户清晰看到本次脚本运行,关键的key值都是哪些。
  • Required属性: 设置Required="true",页面展示会提示红星号,并且要求必填。
  • Disable属性: 设置 disable="true",页面会把对应输入框置灰,不需要用户对此值再做任何修改时可用。
  • Help属性: 设置help属性可以为该节点添加对应的help截图,会在页面上显示问号,点击问号查看截图。例如设置help="CreatePAE\DisChannel.png"关联对应脚本的帮助截图, help="Common\Division.png"关联通用的帮助截图。

AutoIt调用SAP自动化脚本

AutoIt有丰富的函数库,其中包含RunDos的命令, 可以通过命令行直接执行vbs脚本,所以在Execute按钮中包含: _RunDos("wscript "&$path&$file)

在实际项目中的应用及其优势

根据该解决方案,作者开发了Script center,并且在作者所在的项目组得到广泛的应用,到目前为止,使用状况良好,使用前后生产率的提高也是非常显著的。如下图所示:
图5. 使用前后的效率对比

博文共赏:SAP自动化准备测试数据:一个基于AutoIt VBS XML的实现思路_第5张图片

该解决方案的优势在于:

  1. 将原本手工执行的 SAP 操作自动化,节省用户大量的时间和精力,并提高了工作效率;
  2. 将常用的业务场景模板化,可以极大提高脚本的复用性;
  3. 可灵活应对新的业务需求:新的业务场景出现,仅需要创建相应的VBSCRIPT脚本并添加相应的用户数据输入 UI 即可;
  4. 提供友好易用的用户界面,以隐藏底层实现,改善用户体验;
  5. 用户可以轻松实现 SAP 操作而不用了解复杂的 SAP 系统知识和技能。

展望

目前Script Center已经实现了调用VBS脚本在SAP中完成数据创建的操作,使用方便,执行速度快,对笔者所在的项目来说,在SAP中准备测试数据变成了一个简单的工作,不再费时费力。当然,我们也意识到Script Center还有可以提升的空间,例如:一次创建多条类似的数据;可以设置多个脚本的执行顺序,然后依次执行;等等。相信在不久的将来,Script Center会实现这些工作,给使用者带来更多的便利。

结束语

本文主要介绍了利用AutoIt开发出来的工具Script Center,以及通过Script Center调用VBS脚本以在SAP中创建各种测试数据的过程,提出了在SAP中准备测试数据的一种新想法,期望对读者有所启发。

作者简介

兰艳 IBM中国软件开发中心软件工程师。目前主要从事Web Application的自动化测试,功能测试等工作。

张俊 参与IBM软件产品的自动化测试和功能测试。

付荣 参与IBM软件产品的自动化测试和功能测试。

你可能感兴趣的:(博文共赏:SAP自动化准备测试数据:一个基于AutoIt VBS XML的实现思路)