本主题概述了与 SOAtest 和 Virtualize 的可扩展性(脚本)功能及其不同应用程序相关联的问题。本章包含:
了解可扩展功能
SOAtest & Virtualize 可扩展功能允许使用自定义脚本(使用 Java, JavaScript, Oracle Nashorn, Groovy, 或 Jython),以执行在您使用 SOAtest & Virtualize 时对您有帮助的任何特定功能。它还支持实现 JSR 223“Scripting for the Java Platform”规范的其他脚本引擎。该功能允许您在不了解应用程序特定语言的情况下,也可以根据特定需求自定义 SOAtest & Virtualize。
如果使用 SOAtest,您还可以使用脚本自定义您使用 RuleWizard 工具创建的规则。有关此功能的更多详情,请查阅 RuleWizard 用户指南。
设置脚本环境
如果正在使用 Jython 脚本,则可能需要在 Preferences 面板中的 Scripting 选项卡中指定 jython.home 和 jython.path 变量。这两个变量用于定位 Jython 模块,不会导入任何 Jython 模块的 Jython 代码可以在无需设置任何变量的情况下使用 Jython 脚本支持。jython.home 表示 Jython 安装目录,jython.path 用于添加在 jython.home/Lib directory 中没有的路径模块。jython.path 中可以列出多个路径,而 jython.home 必须是单个目录。如果设置 jython.home 和 jython.path 变量,您需要在变更生效之前重启 SOAtest 或 Virtualize。
如果正在使用脚本 Java,并希望使用 SOAtest 重编译修改的 Java 文件,请查阅 Using Eclipse Java Projects in SOAtest 以获得关于如何设置脚本环境的更多详情。
如果正在使用脚本 Java,并希望使用 Virtualize 重编译修改的 Java 文件,请查阅 Using Eclipse Java Projects in Virtualize 以获得关于如何设置脚本环境的更多详情。
指定脚本
若要在提供脚本选项的 SOAtest 或 Virtualize GUI 控件中定义脚本:
- 如果 Java 类来自 Eclipse 工作空间的 Java 项目,则将该 Java 项目添加到类路径中。
- 从 Language 框中,指明脚本将使用的语言。
- 在大文本字段中定义要实现的脚本。
- 对于 Java 方法,请在 Class 字段中指定合适的类。注意,所选定类必须在类路径上(可以单击 Modify Classpath 链接然后在显示的 Preferences 页面对其进行指定)。如果希望在修改和编译 Java 文件之后重新加载该类,则单击 Reload Class 。
- 对于其他脚本,可以使用现有文件作为方法的源代码,也可以在 SOAtest 或 Virtualize 中创建方法。
- 若要使用现有文件,请选择 File 单选按钮,然后单击 Browse。从打开的文件选择器中选择文件,然后单击 OK 完成选择。
- 若要在 SOAtest 或 Virtualize 中从头开始创建方法,请选择 Text 单选按钮,并将代码键入、剪切或粘贴到相关的文本框中。
- 若要检查指定脚本是否合法且可运行,请右键单击 File 或 Text 文本字段(单击要用来指定脚本的一个),然后从快捷菜单中选择 Evaluate 。SOAtest 或 Virtualize 将报告找到的任何问题。
使用脚本模板
如果使用 Jython 或 JavaScript 创建脚本, Script Template 则可以在 SOAtest 或 Virtualize Preferences 面板的字段(在 Scripting 页面)中指定一个脚本模板。该字段中指定的任何代码都将用作与该字段关联语言中的内联脚本的默认代码。这主要用于设置默认输入和通用全局变量。
脚本模板适用于扩展工具、SOAP 服务、脚本化 SOAP 输入中使用的脚本。
与 SOAtest 和 Virtualize 交互
如果需要脚本与 SOAtest 或 Virtualize 项目进行交互,则可以使用 SOAtest 或 Virtualize 扩展 API 来实现这一点。例如,可以使用 SOAtest 或 Virtualize 扩展 API 将脚本结果发送给 SOAtest 或 Virtualize 消息窗口,或者使用其向指定的 SOAtest 或 Virtualize 传递指定值。
关于扩展框架 API 的文档,可以通过 Parasoft> Help 菜单进行访问。(查询书名为“
访问所需 Jar 文件
如果 Java 代码使用扩展 API,并且您希望在下面的产品环境中编译代码:
SOAtest
或
Virtualize
,则使用 Java 项目向导。该向导将创建一个可以访问扩展 API 的新 Eclipse Java 项目。请查阅
或
在 Virtualize 中使用 Eclipse Java 项目以获得更多详情。
如果希望在下面的产品环境之外编译代码:
SOAtest
或
Virtualize
,则将需要以下 jar 文件:
- com.parasoft.api.jar
- webking.jar (只有在访问 soaptest.api 或 webking.api 包中的类时才需要)
这些 jar 文件可在以下路径使用:<SOAtest Installation Directory>\plugins\com.parasoft.xtest.libs.web_<SOAtest version>\root
和<Virtualize Installation Directory>\plugins\com.parasoft.xtest.libs.web_<Virtualize version>\root
此外,如果脚本需要这些 API 类之外的其他功能,则可能需要添加额外(第三方或开源)的 jar 到类路径中。例如:
- 对于 Xpath 处理,您也将需要 org.apache.xpath.XPathAPI 类。它位于 xalan.jar 中。
- 对于与 ISO 8583 相关的脚本,您也将需要来自 org.jpos.iso.* 的类,比如 ISOMsg、BaseChannel、 ISOChannel 和 ISOPackager。这些都位于 jpos.jar 中。
设置上下文类加载器
该扩展工具在类加载器中运行。某些类似 JNDI 这样的 API 对上下文类加载器很敏感。这可能是在您的代码执行特定 API 调用前必须显示设置上下文类加载器的原因。有关更多信息,请查阅 http://wiki.eclipse.org/Context_Class_Loader_Enhancements#Technical_Solution。
脚本变量
您可以在 SOAtest 和 Virtualize 脚本中声明并使用变量。
声明变量必须以关键字 "var”
开头,并且紧跟在等号 "=”
后,同时在它后面紧跟着变量值。每一个变量必须在单独的行中进行声明。变量可以在脚本中的任意位置进行声明,并在声明后可立即使用。若要给现有变量分配新值,请 “重新声明”
变量。
可以在脚本中引用变量,如下所示:${varName}
。
配置 Jython 首选项
Jython 版本
装载了 SOAtest 和 Virtualize 的 Jython 2.5.2 版本没有包含一些标准 Jython 库,比如 os 模块。如果习惯使用这些模块并希望可以在 SOAtest 或 Virtualize 访问到它们,则可以将 SOAtest 或 Virtualize 指向外部的 Jython 安装,如下所示:
- 将 Jython 安装到您所选定的位置;我们将引用该位置作为
<Jython Install Directory>
。 - 打开 SOAtest 或 Virtualize。
- 选择 Parasoft> Preferences 。
- 选择 Scripting。
- 在 Jython Home 字段中,输入
<Jython Install Directory>
。 - 重启 SOAtest 或 Virtualize。
Jython 语法优化
使用 PyDev 插件 (http://www.pydev.org/),以启用扩展工具的 Jython 语法优化。该插件必须为高级功能(如代码自动完成)配置 jython 解释器。有关更多详情信息,请查阅 http://www.pydev.org/manual_101_interpreter.html。
从脚本中访问数据源
如果使用 SOAtest,可以通过在工具配置面板顶部选择数据源,然后启用 Use Data Source 选项,以使数据源对脚本可用。
在脚本的其他方法中,或者使用 Virtualize 时在脚本的任何方法内,将数据源中的值保存到变量“x”中,并使用以下行:
x = context.getValue("Data Source Name", "Column Name")
有关脚本的更多信息,请查阅扩展框架 API 的文档。选择 Parasoft> Help,然后查询书名为 "Parasoft SOAtest 可扩展性 API"(适用于 SOAtest)的图书,或者 "Parasoft Virtualize 可扩展性 API" (适用于 Virtualize)。
SOAtest 示例和说明
例如,假设您有一个类似于下图的测试:
表数据源名称为 Data Source Name。下面这些重要的事实并没有被描绘出来:
- 表 Data Source Name 有一个标记为 Column Name的列。
- XML 数据库包含一个标记为 Test 1: Result的列。
- XML Data Bank 和 Writable Data Source 属于标记为 Generated Data Source的数据源。
为了使这些数据源的其中一个对脚本可用,请在扩展工具配置面板顶部选择数据源,然后选中 Use Data Source。
注意
在打开旧文件(SOAtest 6.1 之前创建)时,注意,Browser Data Bank Tool 列名会自动转换为 "Extracted:xyz",其中 "xyz” 时您所指定的列名。这为引用 "Extracted:xyz” 的传统脚本提供了支持。可以在需 Browser Data Bank 中列名更改为 "xyz" 或 "abc"。
有关脚本的更多信息,请查阅扩展框架 API 的文档。选择 Parasoft> Help,然后查询标题为“Parasoft SOAtest Extensibility API”的图书。
SOAtest 的可扩展示例
访问、操作和存储数据
扩展工具一个典型的使用是访问数据源中的数据,对它进行操作,然后自动将其保存在 XML Data Bank 或 Writable Data Source 中。在此脚本示例中,我们定义了一个名为 getKeywords 的方法,在这个方法中,我们使用名为“keywords”的数据源列访问来自名为“Books”的数据源的数据。然后返回该字符串的 XML 表现形式,以便可以将此脚本中的输出发送至 XML Data Bank。
注意,从扩展工具访问数据源要求额外的配置。有关更多详情,请查阅上一章节。
在这些示例中,方法采用两个参数作为输入:
- Object input: 代表从以前的测试用例传递给方法的输入。例如,如果将扩展工具链接到 SOAP 客户机工具的 SOAP 响应,则输入对象将是表示 SOAP 响应的字符串。
- ExtensionToolContext context: 方法 getValue 允许访问来自扩展工具的数据源。该方法可以与 Context 接口暴露出来的其他方法一起使用,以便在脚本和其他工具之间共享数据源值。
Jython 示例 1
from soaptest.api import * def getKeywords(input, context): title = context.getValue("Books", "keywords") return SOAPUtil.getXMLFromString([title])
Jython 示例 2
def methodName(): # code
def methodName(input): # code
def methodName(input, context): # code
在上面的示例中,"input" 指的是:
- 从该扩展工具的输出传递到该扩展工具的数据是链接在一起的。例如,Response SOAP Envelope of a SOAP Client OR
- 出现在扩展工具 Input 区域中的数据。 这可以在扩展工具界面的底部找到。
在绝大多数情况下,可以假定传递给 "input” 变量的值是一个基本的 Jython 字符串。
总的说来,"context” 变量由 SOAtest 动态确定,并且它将是一个可以在可扩展性 API 中找到的 Context 类实例。至于扩展工具,context 将是该指定工具(与测试套件中的其他扩展工具相比较)的 ExtensionToolContext 实例。
JavaScript 示例
var SOAPUtil = Packages.soaptest.api.SOAPUtil function getKeywords(input, context) { title = context.getValue("Books", "keywords") return SOAPUtil.getXMLFromString([title]) }
Java 示例
package examples; import soaptest.api.*; import com.parasoft.api.*; public class Keyword { public Object getKeywords(Object input, ExtensionToolContext context) throws com.parasoft.data.DataSourceException { String[] titles = new String[1]; titles[0] = context.getValue("Books", "keywords"); return SOAPUtil.getXMLFromString(titles); } }
注意
类似于此示例的 Java 代码必须在 SOAtest 外编译。为了访问来自 SOAtest 可扩展性 API(尤其是webking.jar
和 com.parasoft.api.jar
)的包,您将需要确保 Java 编译器的类路径上存在 SOAtest jar 文件。
对于这个 Keyword 示例,源代码和编译后的类文件可以在 SOAtestInstallRoot/build/examples 中找到。SOAtestInstallRoot/build 文件夹已存在于 SOAtest 的类路径上,因此您可以在测试套件中使用 Keyword 示例。也可以将自己的 Java 类文件放在这里,以便在 SOAtest 中使用 Java 类。使用 SOAtestInstallRoot/build 文件夹的其中一个选择是使用 Preferences 中的 System Properties 选项卡添加类文件。
将文件内容读入字符串
若要使用 Jython 脚本将文件内容读入字符串,则可以使用以下方法:
from java.lang import * from java.io import * from soaptest.api import * def getContents(input, context): contents = StringBuffer() reader = BufferedReader(FileReader(File("c:\Documents and Settings\jhendrick\Desktop\test.txt"))) line = String() while line != None: line = reader.readLine() if line != None: contents.append(line) contents.append(System.getProperty("line.separator")) reader.close() return contents.toString()
定义自定义断言
下面是一个示例 Java 脚本,它可以在 XML 断言器工具中用作自定义断言。此脚本从数据源获取一个值,打印该值和响应值,并根据响应值是否包含数据源值返回一个布尔值。
package examples; import com.parasoft.api.*; public class Comparison { //Compares a value from a database data source to a value returned in a SOAP response public boolean compareToDatabase(Object input, ScriptingContext context) throws com.parasoft.data.DataSourceException { //Gets values from database data source named "Books" String value = context.getValue("Books", "Book"); //Prints database data source values along with SOAP response values in a message to the console Application.showMessage("Value from database is " + value + ".\nValue from SOAP response is " + input.toString() + "."); //Verifies that the SOAP response value contains the database data source value return input.toString().contains(value); } }
使用提取的值进行字符串操作
下面是一个 Jython 脚本示例,它从各种源(数据库、测试套件变量和环境变量)中提取值,以用于字符串操作(如使用‘+’运算符的连接)。
from soaptest.api import * from com.parasoft.api import * # Gets a value from a data bank (line 10) or test suite variable (line 11), # appends an environment variable value to the front of that value, # and returns the modified value. Be sure to comment out line 11 # when using line 10 and vice versa. def getModifiedString(context): #value = context.getValue("Generated Data Source", "columnName") value = context.getValue("testSuiteVariableName") environmentVariableValue = context.getEnvironmentVariableValue("environmentVariableName") modifiedString = environmentVariableValue + value return modifiedString
此例子是针对一个相当特定的用例,但尽管如此,它仍然使用了来自 SOAtest 可扩展性 API 的一些常见方法。
访问窗口或框架的文档
这些示例用于将扩展工具链接到 Web 场景中使用的浏览器回放工具时使用。
重载 getDocument,如下所示:
getDocument(); // gets the document for the main window getDocument(String windowName); // gets the document for the window with the specified window name getDocument(String windowName, String frameName); // gets the document for a frame within a window
例如,下面的代码获取主窗口中名为“mainPane”的框架的内容然后使用该文档获取所选定框架的标题文本。
var Application = Packages.com.parasoft.api.Application; var WebBrowserUtil = Packages.webking.api.browser2.WebBrowserUtil; function getFrameDocument(input, context) { var document = input.getDocument("", "mainPane"); var titles = document.getElementsByTagName("title"); var title = titles.item(0); var value = WebBrowserUtil.getTrimmedText(title); Application.showMessage("title: " + value); return value; }
特定语言技巧
Java
- 当在任意脚本 Class 字段中指定一个 Java 类时,必须指定类路径上的已编译类。可以单击 Modify Classpath 链接,然后在显示的首选项页面中对其进行指定。
- 如果正使用的类是包的一部分,则需要指定完整的包名和类名(比如,
java.lang.String
)。 - 如果您的一个脚本使用一个类,该类在 SOAtest 或 Virtualize 中已变更且已重新编译,则 SOAtest 或 Virtualize 将重新加载该类,并在调用方法时使用最近的类来构造对象。对于包名以以下前缀开头的任何类,SOAtest 和 Virtualize 都不会以这种方式工作:
- sun.
- com.sun.
- org.omg.
- javax.
- sunw.
- java.
- com.parasoft.
- webtool.
- wizard.
- 若要手动提示 SOAtest 或 Virtualize 重新加载一个已变更并已重新编译的类,则单击 Reload Class。
JavaScript
- “传统”的 SOAtest 或 Virtualize JavaScript 模拟是基于 FESI 的。建议使用可选择的脚本引擎,比如 Oracle Nashorn。有关更多详情信息,请查阅:
- 可以从 JavaScript 方法或 JavaScript 工具内部调用类路径上的 Java 类和方法。
例如,如果正在使用 Nashorn,并希望从 JavaScript 内部调用 Application.report() (来自 SOAtest 或 Virtualize 可扩展性 API),则需要引用它作为
Java.type("com.parasoft.api.Application"): var Application = Java.type("com.parasoft.api.Application") Application.report("Message", "Result Window")
。如果决定使用传统的引擎(不推荐),并希望从 JavaScript 内部调用 Application.report() (来自 SOAtest 或 Virtualize 可扩展性 API),则需要引用它作为
Packages.com.parasoft.api.Application.report()
。也可以通过将Packages
及其 Jave 类所处包的包名进行前置,从而引用它,如下所示:var Application = Packages.com.parasoft.api.Application Application.report("Message", "Result Window")
。
- 若要检查指定的脚本是否合法且可运行(或向 Method 框添加方法条目),则右键单击 File 或 Text 文本字段(单击要用来指定脚本的一个),然后从快捷菜单中选择 Evaluate 。
Jython
关于 Jython(与 Java 集成的 Jython 实现)的更多详情,包括如何编写 Jython 以及如何从 Jython 内部调用 Java 类,请访问 http://www.jython.org。注意,装载了 Jython 2.5.2 的 SOAtest 和 Virtualize。
- 如果正在使用 Jython 脚本,则可能需要在 Preferences 面板中的脚本(Scripting)选项卡中指定 jython.home 和 jython.path 变量。这两个变量用于定位 Jython 模块,不会导入任何 Jython 模块的 Jython 代码可以在无需设置任何变量的情况下使用 Jython 脚本支持。jython.home 表示 Jython 安装目录,jython.path 用于添加在 jython.home/Lib directory 中没有的路径模块。jython.path 中可以列出多个路径,而 jython.home 必须是单个目录。如果要设置 jython.home 和 jython.path 变量,则需要在变更生效之前重启 SOAtest 或 Virtualize。
- 如果决定导入可选模块,并且没有安装 Jython 2.5.2,则从 jython.org中下载并安装 Jython 2.5.2。对于 Linux,请使用 java -jar jython_installer-2.5.2.jar。对于 Windows,请双击 jython_installer-2.5.2.jar。
- 若要检查指定的脚本是否合法且可运行(或向 Method 框添加方法条目),则右键单击 File 或 Text 文本字段(单击要用来指定脚本的一个),然后从快捷菜单中选择 Evaluate 。
Groovy
这是一个 Groovy 脚本示例:
import com.parasoft.api.*; boolean customAssertion(Object input, ScriptingContext context) { String value = context.getValue("Books", "title"); Application.showMessage("Value from data source is " + value) Application.showMessage("Value from SOAP response is " + input.toString()) return input.toString().contains(value); }
JSR 223 脚本语言
可以配置 SOAtest 和 Virtualize 以识别任何实现 JSR 223 "Scripting for the Java Platform” 规范的脚本引擎。 Oracle Nashorn 默认可用;其他的可以添加。
Oracle Nashorn JavaScript
Oracle Nashorn ECMAScript 引擎默认可用,因为它包含在 Java 中。这是一个 Oracle Nashorn 脚本示例:
var Application = Java.type("com.parasoft.api.Application") function customAssertion(input, context) { value = context.getValue("Books", "title"); Application.showMessage("Value from data source is " + value) Application.showMessage("Value from SOAP response is " + input.toString()) return input.toString().contains(value); }
Mozilla Rhino JavaScript
Mozilla Rhino 是在 Java 运行时包含的原始 ECMAScript 引擎。 它是 Oracle Nashorn 的前身,在 Java 8 中取代了 Mozilla Rhino。SOAtest 和 Virtualize 9.10 之前的版本装配了 Java 7,其中便包括 Mozilla Rhino。使用 Mozilla Rhino 引擎保存在 SOAtest 和 Virtualize 早期版本中的脚本现在将运行在新的 Oracle Nashorn 中,并加载 Mozilla 兼容性扩展。兼容性扩展是由 Oracle 作为 Nashorn 的一部分提供的,目的就是实现这些目的。通过加载兼容性扩展,脚本将继续像以前一样工作,但运行时性能将显著提高。
使用 Mozilla Rhino 原始保存的脚本现在将会把 JavaScript (Mozilla Rhino compatible) 显示在 Language 选择框中,表示脚本将使用 Nashorn 运行,但使用 Mozilla 兼容性扩展。如果创建一个新脚本,则 JavaScript (兼容 Mozilla Rhino) 选项将不可用;您将只会看到 JavaScript (Oracle Nashorn),它没有加载 Mozilla 兼容性扩展。如果需要在这种情况下加载兼容性扩展,仅需 add
load("nashorn:mozilla_compat.js")
; 到脚本顶部即可。有关更多详情,请查阅 https://wiki.openjdk.java.net/display/Nashorn/Rhino+Migration+Guide#RhinoMigrationGuide-Compatibility-script。
由于 Oracle Nashorn 代替了 Mozilla Rhino,所以不推荐使用 Mozilla Rhino。然而,Mozilla Rhino 可以像任何其他兼容 JSR 223 的脚本引擎一样,以同样的方式用于 SOAtest 和 Virtualize(请查阅 其他 JSR 223 脚本语言)。Mozilla Rhino 包括两个必须添加到首选项面板中类路径上的 jar:Rhino js.jar 和 js-engine.jar。有关更多详情信息,请查阅 https://wiki.openjdk.java.net/display/Nashorn/Using+Rhino+JSR-223+engine+with+JDK8。
预构建的 jar 也可以在 maven central 上找到:
http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.mozilla%22%20a%3A%22rhino%22
- http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22rhino-js-engine%22
其他 JSR 223 脚本语言
若要使另外的 JSR 223 脚本语言都可使用,请将合适引擎的脚本引擎添加到类路径上(跳转至 Parasoft Preferences 面板并将其添加到 System Properties 区域)。
例如,可以添加实现 JSR 223 的 JRuby 脚本引擎。为此,您可以从 http://jruby.org/ 中下载 JRuby,然后将 jruby.jar 添加到类路径上。
这是一个 JRuby 脚本示例:
require 'java' Application = com.parasoft.api.Application def doSomething(input, context) Application.showMessage("hello world") end
其他可扩展性资源
关于如何创建并应用执行已编写的自定义脚本的扩展工具的更多详情,请查阅 用于自定义脚本的扩展工具。