Squish API

本节介绍了Squish除了支持的脚本语言的标准功能外还提供的API。Squish API提供了测试工程师测试GUI应用程序所需的设施,提供了从与AUT对象交互、记录测试日志信息,执行验证、控制AUT等功能在内的广泛功能。

Squish API函数

以下是Squish API函数的快速链接(不包括Squish对象或工具包特定的便利函数)

Squish API 函数参数

对于所有接受 objectOrName 参数的 Squish API 函数,它可以是对象的引用或对象名称。

一些 Squish API 函数可以接受一个表示在鼠标点击时按下的特殊键的 modifierState 参数。此外,一些函数接受一个表示哪个鼠标按钮被点击的 mouseButton 参数。

modifierState 可以是 0(Modifier.NoModifier,默认值),或者是以下之一:Modifier.AltModifier.ControlModifier.Shift。如果使用了多个修改键,它们必须通过 OR 连接。例如,Modifier.Alt|Modifier.Shift。这里所示的形式适用于 Python 和 JavaScript。对于 Perl 和 Ruby,请将点替换为两个冒号:Modifier::Control。对于 Tcl,使用 enum 函数:enum Modifier Control

mouseButton 可以是以下之一:MouseButton.LeftButtonMouseButton.MiddleButtonMouseButton.RightButtonMouseButton.NoButton

对于 Perl 使用: MouseButton::LeftButton 等。

对于 Ruby 使用: MouseButton::LEFT_BUTTON 等。

对于 Tcl 使用: enum MouseButton LeftButton 等。

注意:Windows 测试套件还支持两种额外的鼠标按钮指定器,MouseButton.PrimaryButtonMouseButton.SecondaryButton。这些值遵循全局 Windows 设置,用于交换鼠标按钮。如果未交换按钮(默认值),则左按钮为主按钮。否则,右按钮为主按钮。

确定对象

许多 API 函数适用于特定的对象,因此能够确定感兴趣的对象尤为重要。

Squish提供多种命名方案,但通常使用的是符号名实际名。符号名在面对自动测试单元(AUT)变化时最为稳健,但实际名有时候使用起来可能会更方便。有关名称的更多信息,请参阅如何识别和访问对象

对于Qt程序,在代码中对所有感兴趣的Object设置对象名称是识别对象的简单且可靠的方法(使用QObject::setObjectName方法),然后在测试脚本中使用真实的多属性名称指定对象的objectName和其type。例如

textEdit = findObject("{objectName='ConfigEditor' type='QTextEdit'}")
var textEdit = findObject("{objectName='ConfigEditor' type='QTextEdit'}");
my $textEdit = findObject("{objectName='ConfigEditor' type='QTextEdit'}");
textEdit = findObject("{objectName='ConfigEditor' type='QTextEdit'}")
set textEdit [findObject "{objectName='ConfigEditor' type='QTextEdit'}"]

在实践中,给每个单独的widget分配一个唯一对象名称会很繁琐(目前只有Qt支持它),因此这种方法通常在同一个表单中有两个或更多相同的widget时使用。对于那些没有对象名称的工具包,我们可以使用反思方法当有两个或更多相同的widgets时。两种方法的具体示例请参阅如何创建测试脚本如何测试应用程序 - 专用细节

最常见的场合是需要识别未命名的对象。这可以通过使用符号名或通过匹配对象的唯一属性值集来完成。必要的信息可以使用Spy工具(如何使用Spy)来获取。此工具可以提供对象的符号名和基于属性(真实)的名称。另一种方法是创建一个空测试,与感兴趣的object交互,然后查看Squish的对象映射以查看Squish使用的名称,并复制所需的任何名称。

以下是一个示例,展示了找到类型为QTextEdit的未命名对象的两种方法。这个对象在QMainWindow中,其标题是“我的应用”。

# symbolic name
textEdit = waitForObject(":MyApp_QTextEdit")
# real (multi-property) name
textEdit = waitForObject("{type='QTextEdit' unnamed='1' " +
        "visible='1' window=':MyApp_MainWindow'}")
// symbolic name
var textEdit = waitForObject(":MyApp_QTextEdit");
// real (multi-property) name
var textEdit = waitForObject("{type='QTextEdit' unnamed='1' " +
        "visible='1' window=':MyApp_MainWindow'}");
# symbolic name
my $textEdit = waitForObject(":MyApp_QTextEdit");
# real (multi-property) name
my $textEdit = waitForObject("{type='QTextEdit' unnamed='1' " .
        "visible='1' window=':MyApp_MainWindow'}");
# symbolic name
textEdit = waitForObject(":MyApp_QTextEdit")
# real (multi-property) name
textEdit = waitForObject("{type='QTextEdit' unnamed='1' " +
        "visible='1' window=':MyApp_MainWindow'}")
# symbolic name
set textEdit [waitForObject ":MyApp_QTextEdit"]
# real (multi-property) name
set textEdit [waitForObject "{type='QTextEdit' unnamed='1' \
        visible='1' window=':MyApp_MainWindow'}"]

Object waitForObject(objectOrName)函数等待识别的对象准备好(可见且可用),然后返回其对象的引用。

总的来说,最好使用符号名,因为它们在面对AUT变化时更为稳健,因为我们只需要更新对象映射而不是我们的测试脚本代码,如果对象的属性发生变化。(注意:对于大多数GUI工具包,在使用真实名称时,type属性是强制性的。)

构造函数、函数和属性

Squish对象与脚本语言的本地对象无缝集成。这意味着您可以使用标准语言特性来构造包装类型对象的实例,调用成员函数,获取、设置和遍历这些对象上的属性。

以下是一些简单示例

# create an object of type QPoint
point = QPoint(10, 20)

# read a widget's width property
width = widget.width

# set widget's y-coordinate property
widget.y = 240

# call a member function
widget.setWindowTitle("My Widget")

# call a static function
QApplication.setOverrideCursor(Qt.WaitCursor)
// create an object of type QPoint
var point = new QPoint(10, 20);

// read a widget's width property
var width = widget.width;

// set widget's y-coordinate property
widget.y = 240;

// call a member function
widget.setWindowTitle("My Widget");

// call a static function
QApplication.setOverrideCursor(Qt.WaitCursor);
# create an object of type QPoint
my $point = new QPoint(10, 20);

# read a widget's width property
my $width = widget->width;

# set widget's y-coordinate property
$widget->y(240);

# call a member function
$widget->setWindowTitle("My Widget");

# call a static function
QApplication::setOverrideCursor(Qt::WaitCursor);
# create an object of type QPoint
point = QPoint.new(10, 20)

# read a widget's width property
width = widget.width

# set widget's y-coordinate property
widget.y = 240

# call a member function
widget.setWindowTitle("My Widget")

# call a static function
QApplication.setOverrideCursor(Qt::WAIT_CURSOR)
# create an object of type QPoint
set point [construct QPoint 10 20]

# read a widget's width property
set width [property get $widget width]

# set widget's y-coordinate property
property set $widget y 240

# call a member function
invoke $widget setWindowTitle "My Widget"

# call a static function
invoke QApplication setOverrideCursor [enum Qt WaitCursor]

对于Tcl,我们必须使用enum函数获取枚举值。(参见Tcl笔记。)

函数和属性(macOS)

脚本语言API中的函数名遵循以下约定:选择器名称中的每个冒号(:)都替换为下划线(_)。例如,+stringWithCString:encoding:选择器变为脚本函数stringWithCString_encoding_(注意函数结尾的下划线)。

以下是一些示例,以说明用法。

# create an object of type NSString and initialize it with a value
s = NSString.stringWithUTF8String_("Ambient")

# read an object's intValue property
n = acontrol.intValue

# set an object's intValue property
acontrol.intValue = 33

# call an instance method
s.characterAtIndex_(1)

# call a class method
s = NSString.stringWithCString_encoding_("Zenith", 4)
// create an object of type NSString and initialize it with a value
var s = NSString.stringWithUTF8String_("Ambient");

// read an object's intValue property
var n = acontrol.intValue;

// set an object's intValue property
acontrol.intValue = 33;

// call an instance method
s.characterAtIndex_(1);

// call a class method
s = NSString.stringWithCString_encoding_("Zenith", 4);
# create an object of type NSString and initialize it with a value
my $s = NSString::stringWithUTF8String_("Ambient");

# read an object's intValue property
my $n = $acontrol->intValue;

# set an object's intValue property
$acontrol->intValue(33);

# call an instance method
$s->characterAtIndex_(1);

# call a class method
$s = NSString::stringWithCString_encoding_("Zenith", 4);
# create an object of type NSString and initialize it with a value
s = NSString.stringWithUTF8String_("Ambient");

# read an object's intValue property
n = acontrol.intValue

# set an object's intValue property
acontrol.intValue = 33

# call an instance method
s.characterAtIndex_(1)

# call a class method
s = NSString.stringWithCString_encoding_("Zenith", 4)
# create an object of type NSString and initialize it with a value
set s [invoke NSString stringWithUTF8String_ "Ambient"]

# read an object's intValue property
set n [property get $acontrol intValue]

# set an object's intValue property
property set $acontrol intValue 33

# call an instance method
invoke $s characterAtIndex_ 1

# call a class method
set s [invoke NSString stringWithCString_encoding_ "Zenith" 4]

对象访问函数

Object findObject(objectName)

此函数通过指定的符号名或真实(多属性)名 objectName 查找并返回(对象引用),如果找不到此类对象则抛出 LookupError 异常。该名称也可以是本地脚本字典(或哈希)值。此函数最适合用于不可见对象。对于可见对象,最好使用 Object waitForObject(objectOrName) 函数。

SequenceOfObjects findAllObjects(objectName)

此函数通过指定的符号名或真实(多属性)名 objectName 查找并返回对象引用的列表。因为它可以返回多个对象引用,所以名称中不能包含发生属性。该名称也可以是本地脚本字典(或哈希)值。

SequenceOfObjects object.children(object)

此函数接受一个 object 引用(由 Object findObject(objectName) 函数或 Object waitForObject(objectOrName) 函数返回),并返回该对象的子对象列表。返回类型根据脚本语言而定,例如 Python 中的元组,其他语言中的数组。下面是示例。

依赖于此列表中遇到的子对象顺序的测试用例,可能会发现由于许多不同的因素(例如

  • Squish 的增强功能
  • 工具包库的更新
  • AUT 的变化
obj = waitForObject(":MyWidget")
children = object.children(obj)
# iterate over tuple
for child in children:
    ...
var obj = waitForObject(":MyWidget");
var children = object.children(obj);
// iterate over array
for (var i = 0; i < children.length; ++i) {
    var child = children[i];
    ...
}
my $obj = waitForObject(":MyWidget");
my @children = object::children($obj);
# iterate over array
foreach $child (@children) {
    ...
}
obj = waitForObject(":MyWidget")
children = Squish::Object.children(obj)
# iterate over array
for child in children
    # ...
end
set obj [waitForObject ":MyWidget"]
set children [object children $obj]
foreach child $children {
    ...
}

Object object.convertTo(object, typeName)

此函数将给定的 object 转换为 typeName 字符串指定的类型对象。(可以使用 Object waitForObject(objectOrName) 函数或 Object findObject(objectName) 函数获取适当的对象。)例如

font = object.convertTo(variant, "QFont")

在此示例中,如果 variantQVariant 类型的变量并包含一个 QFont 对象,则返回底层 QFont 对象。如果 object 无效或为空或 typeName 不可识别或转换不可行(例如从 QFontint),则将引发可捕获的异常。

此函数还可以进行其他类型的转换,例如 intString。另请参阅 Object cast(object, type) 函数,它可以用于向下转换(这是 object.convertTo 所不能做的)。

注意:在 Qt5 中,如果使用 QMetaType 记录了自定义类,Squish 可以从 QVariant 中提取指向派生自 QObject 的类的指针,并将其转换为正确的类型。关键是不要使用上述示例中建议的 object.convertTo(myVariant, "CustomClassName")(这在其他情况下是有效的),而是使用 object.convertTo(myVariant, "QObject")

Object object.createNull(type)

此函数创建一个指定 type 类型的空指针或对象。

widget = object.createNull(QWidget)

Boolean object.exists(objectName)

如果存在具有符号名或真实(多属性)名 objectName 的对象,则此函数返回一个真值;否则返回一个假值。该名称也可以是本地脚本字典(或哈希)值。

如果您知道某个特定对象存在,并且只想访问它(例如,检查其属性或对其执行操作),则如果对象是可见的,请使用 Object waitForObject(objectOrName) 函数;如果对象是隐藏的,则使用 Object findObject(objectName) 函数。

Object object.parent(object)

此函数接受一个 object 引用(由 Object findObject(objectName) 函数或 Object waitForObject(objectOrName) 函数返回),并返回父对象。

如果给定对象没有父对象,则该函数返回一个空值 - 具体的类型取决于脚本语言(例如,Python 中的 None,JavaScript 中的 null,Ruby 中的 nil 等)。

KeyValueMap object.properties(object)

此函数接受一个 object 引用(由 Object findObject(objectName) 函数或 Object waitForObject(objectOrName) 函数返回),并返回一个键值映射,其中包含该对象的全部属性。键是属性名,值是属性值。返回类型特定于脚本语言,例如 Python 的 dict,JavaScript 的对象,或 Perl 的 hash。以下提供了示例。

对于 Tcl,数据将写入一个数组,其名称必须作为附加参数给出。除非在每次使用前调用 array unset,否则不应在第二次或随后的调用中使用同一个数组。

widget = waitForObject(":MyWidget")
properties = object.properties(widget)
# Best to use .iteritems(), .iterkeys(), or .itervalues() in Python 2
for name, value in properties.iteritems():
    test.log("%s = %s" % (name, value))
var widget = waitForObject(":MyWidget");
var properties = object.properties(widget);
for (var name in properties) {
    test.log(name + " = " + properties[name]);
}
my $widget = waitForObject(":MyWidget");
my %properties = object::properties($widget);
while (($name, $value) = each(%properties)) {
    test::log("$name = $value");
}
widget = waitForObject(":MyWidget")
properties = Squish::Object.properties(widget)
properties.each {|key, value| Test.log("#{key} = #{value}")}
set widget [waitForObject ":MyWidget"]
object properties $widget properties
foreach key [array names properties] {
    set value [toString $properties($key)]
    test log "$key = $value"
}

ScreenRectangle object.globalBounds(object)

此函数接受一个 object 引用(由 Object findObject(objectName) 函数或 Object waitForObject(objectOrName) 函数返回),并返回对象的屏幕坐标边界矩形,作为 ScreenRectangle 对象。

这些值与 Squish 在对象高亮时使用的值相同。然而,这些值可能不等于工具包特定的几何信息,因为 Squish 可能进一步限制全局边界矩形,以便仅包含实际屏幕上可见的内容(即如果对象的一部分被其父对象剪裁掉)。

var obj = waitForObject(":MyWidget");
var rect = object.globalBounds(obj);
test.verify(rect.width > 200);
y $obj = waitForObject(":MyWidget");
my $rect = object::globalBounds($obj);
test::verify($rect->width > 200);
obj = waitForObject(":MyWidget")
rect = object.globalBounds(obj)
test.verify(rect.width > 200)
obj = waitForObject(":MyWidget")
rect = Squish::Object.globalBounds(obj)
Test.verify(rect.width > 200)
set obj [waitForObject ":MyWidget"]
set rect [object globalBounds $obj]
test verify [expr [property get $rect width] > 200]

Image object.grabScreenshot(object, [parameterMap])

此函数接受一个 object 引用(由 Object findObject(objectName) 函数或 Object waitForObject(objectOrName) 函数返回),并返回其当前可视为 Image Object 对象的截图。

可以通过通过可选的 parameterMap 参数传递的条目配置截图行为。

  • delay - 在抓取截图之前的时间延迟(以毫秒为单位)。默认值为 1000(1秒),以允许 AUT 对最新输入做出反应,并在抓取截图之前达到稳定状态。将其减少到 0 可能有助于提高测试执行时间,尤其是在一系列连续的 grabScreenshot() 调用的情况下。
var obj = waitForObject(":MyWidget");
var img = object.grabScreenshot(obj, {delay: 0});
test.attachImage(img);
y $obj = waitForObject(":MyWidget");
my $img = object::grabScreenshot($obj, {"delay" => 0});
test::attachImage($img);
obj = waitForObject(":MyWidget")
img = object.grabScreenshot(obj, {"delay": 0})
test.attachImage(img)
obj = waitForObject(":MyWidget")
img = Squish::Object.grabScreenshot(obj, {"delay" => 0})
Test.attachImage(img)
set obj [waitForObject ":MyWidget"]
set img [object grabScreenshot $obj {delay 0}]
test attachImage $img

—已弃用— QImage grabWidget(object)

此函数抓取 object 窗口(或小部件)的截图,并将其作为 QImage 对象 返回。

注意: 使用 grabWidget 获取AUT端的 QImage 比较麻烦,而使用 Image Object 来捕获更加简单,方法为 Image.object.grabScreenshot(object, [parameterMap])Image.save(fileName) 函数允许您直接在 squishrunner 主机上保存文件。

SequenceOfObjects 对象.topLevelObjects()

此函数返回 AUT 中所有顶级对象的列表。返回类型取决于脚本语言,例如,在 Python 中为元组,在其他语言中为数组。以下给出了示例。

topLevels = object.topLevelObjects()
# iterate over tuple
for obj in topLevels:
    children = object.children(obj)
    ...
var topLevels = object.topLevelObjects();
// iterate over array
for (var i = 0; i < topLevels.length; ++i) {
    var obj = topLevels[i];
    var children = object.children(obj)
    ...
}
my @topLevels = object::topLevelObjects();
# iterate over array
foreach $obj (@topLevels) {
    my @children = object::children(obj)
    ...
}
topLevels = Squish::Object.topLevelObjects()
# iterate over array
for obj in topLevels
    children = Squish::Object.children(obj)
    #...
end
set topLevels [object topLevelObjects]
foreach obj $topLevels {
    set children [object children $obj]
    ...
}

ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion])

此函数将在显示的当前运行的应用程序上搜索存储在 imageFile 中的模板图像。如果成功,返回找到的图像的位置作为 ScreenRectangle。然后可以使用如 mouseClick()tapObject() 的函数在检测到的位置模拟用户交互。

搜索子图像是按从左到右、从上到下的顺序进行的。返回第一个成功的匹配。要选择其他匹配项,请使用以下描述的 occurrence 参数。

将搜索包括桌面在内的所有可用屏幕。至少在Windows和基于X11的系统上是这样。对于在macOS上多屏幕设置中的搜索,请咨询技术支持。

可以通过传递通过可选 parameterMap 参数传入的条目来配置搜索行为。

  • occurrence - 出现索引。默认情况下,将返回第一个匹配项(索引为1)。索引值2及以上将选择尽可能多的连续匹配项。
  • tolerant - 启用容错图像搜索模式的布尔开关。在此模式下,模板图像与桌面截图之间的某些差异是可以接受的。默认值是 testSettings.imageSearchTolerant 属性的值。
  • threshold - 模板图像与桌面截图之间的相关性的阈值,以百分比表示。相关性高于阈值的认为与模板图像匹配。此参数的有效值通常介于 99.0100.0 之间。默认值是 testSettings.imageSearchThreshold 属性的值。如果将 tolerant 参数设置为 false,则忽略此参数。
  • multiscale - 启用缩小图像搜索模式的布尔开关。在此模式下,模板图像将扩展为一系列不同大小的图像。随后,这些图像作为图像搜索的模板图像使用。默认值是 testSettings.imageSearchMultiscale 属性的值。如果将 tolerant 参数设置为 false,则忽略此参数。
  • minScale - 模板图像系列大小下限,以百分比表示。调整大小后的模板图像大小将介于原始图像大小的 minScalemaxScale 之间。默认值是 testSettings.imageSearchMinScale 属性的值。如果将 tolerantmultiscale 参数设置为 false,则忽略此参数。
  • maxScale 模板图像系列尺寸的上限,以百分比表示。调整后的模板图像尺寸将在原始图像尺寸的 minScalemaxScale 之间扩展。默认值是 testSettings.imageSearchMaxScale 属性的值。当 tolerantmultiscale 参数设置为 false 时,此参数将被忽略。
# Click on icon.png
mouseClick( findImage("icon.png") )
# Click on second occurrence of icon.png
mouseClick( findImage("icon.png", {"occurrence": 2}) )
// Click on icon.png
mouseClick( findImage("icon.png") );
// Click on second occurrence of icon.png
mouseClick( findImage("icon.png", {"occurrence": 2}) );
# Click on icon.png
mouseClick( findImage("icon.png") );
# Click on second occurrence of icon.png
mouseClick( findImage("icon.png", {"occurrence" => 2}) );
# Click on icon.png
mouseClick( findImage("icon.png") )
# Click on second occurrence of icon.png
mouseClick( findImage("icon.png", {"occurrence" => 2}) )
# Click on icon.png
invoke mouseClick [waitForImage "icon.png"]
# Click on second occurrence of icon.png
invoke mouseClick [waitForImage "icon.png" {occurrence 2 timeout 10000}]

此函数将仅对屏幕内容执行单次检查。如果无法找到子图,将抛出异常。如果以下情况之一成立,调用这个函数是很有用的:a) 几乎可以确定子图的存在;或 b) 需要进行快速的子图存在检查。在其他所有情况下,建议使用 ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion]) 函数进行时间无关的查找。

匹配算法执行逐像素的彩色值比较。因此,除非启用容错搜索模式,否则屏幕内容和子图像内容必须完全匹配 100%。

# Click on icon.png
mouseClick( findImage("icon.png", {'tolerant': True,
                                   'threshold': 99.7,
                                   'multiscale': True,
                                   'minScale': 100.0,
                                   'maxScale': 150.0}) )
// Click on icon.png
mouseClick( findImage("icon.png", {tolerant: true,
                                   threshold: 99.7,
                                   multiscale: true,
                                   minScale: 100.0,
                                   maxScale: 150.0}) );
# Click on icon.png
mouseClick( findImage("icon.png", {tolerant => true,
                                   threshold => 99.7,
                                   multiscale => true,
                                   minScale => 100.0,
                                   maxScale => 150.0}) );
# Click on icon.png
mouseClick( findImage("icon.png", {"tolerant" => true,
                                   "threshold" => 99.7,
                                   "multiscale" => true,
                                   "minScale" => 100.0,
                                   "maxScale" => 150.0}) )
# Check whether icon.png is displayed on screen
invoke mouseClick [ findImage "icon.png" {tolerant true \
                                          threshold 99.7 \
                                          multiscale true \
                                          minScale 100.0 \
                                          maxScale 150.0} ]

如果指定了搜索区域作为最后一个参数,则只在与之对应的区域内进行搜索。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。还可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

搜索区域还可以是一个 Image Object 对象。在这种情况下,不会捕获新的屏幕截图,而是使用指定的图片。目前尚无法将搜索范围限定在 Image 对象的某个部分;请使用 Image.copy() 来剪切相关部分。

# Find icon.png on the MyWidget object
findImage("icon.png", {}, waitForObject( names.MyWidget ) )

# Find icon.png on multiple objects
findImage("icon.png", {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] )

# Find icon.png on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
findImage("icon.png", {}, bounds )

# Find icon.png in the specified area
findImage("icon.png", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) )

# Find icon.png on all top-level objects
findImage("icon.png", {}, "all" )
// Find icon.png on the MyWidget object
findImage("icon.png", {}, waitForObject( names.MyWidget ) );

// Find icon.png on multiple objects
findImage("icon.png", {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] );

// Find icon.png on the left half of the MyWidget object
var bounds = object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
findImage("icon.png", {}, bounds );

// Find icon.png in the specified area
findImage("icon.png", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) );

// Find icon.png on all top-level objects
findImage("icon.png", {}, "all" );
# Find icon.png on the MyWidget object
findImage("icon.png", {}, waitForObject( names::MyWidget ) );

# Find icon.png on multiple objects
findImage("icon.png", {}, ( waitForObject( names::MyWidget ),
                            waitForObject( names::MyOtherWidget ) ) );

# Find icon.png on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
findImage("icon.png", {}, bounds );

# Find icon.png in the specified area
findImage("icon.png", {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) );

# Find icon.png on all top-level objects
findImage("icon.png", {}, "all" )
# Find icon.png on the MyWidget object
findImage("icon.png", {}, waitForObject( names.MyWidget ) );

# Find icon.png on multiple objects
findImage("icon.png", {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] );

# Find icon.png on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
findImage("icon.png", {}, bounds );

# Find icon.png in the specified area
findImage("icon.png", {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) );

# Find icon.png on all top-level objects
findImage("icon.png", {}, "all" );
# Find icon.png on the MyWidget object
findImage "icon.png" {} [ waitForObject $names::MyWidget ]

# Find icon.png on multiple objects
findImage "icon.png" {} { [ waitForObject $names::MyWidget ],
                          [ waitForObject $names::MyOtherWidget ] }

# Find icon.png on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
findImage "icon.png" {} $bounds

# Find icon.png in the specified area
findImage "icon.png" {} [ construct ScreenRectangle 100 100 200 300 ]

# Find icon.png on all top-level objects
findImage "icon.png" {} "all"

String getOcrText([parameterMap], [searchRegion])

此函数将执行显示内容的光学字符识别,并返回所有文本行。

OCR 将在组成桌面的所有可用屏幕上执行。至少在 Windows 和基于 X11 的系统上是如此。对于在 macOS 上实现多屏设置的 OCR,请联系技术支持。

可以通过传递通过可选 parameterMap 参数传入的条目来配置搜索行为。

  • language - OCR 引擎的语言提示。使用空字符串将使用 OCR 引擎的默认值。默认值是 testSettings.defaultOcrLanguage 属性的值。
  • profiles - OCR 引擎特定配置文件名称的数组。此参数仅在支持配置文件的引擎中使用。
  • options - 引擎特定选项名称和值的映射。这些选项在加载指定的配置文件后传递给 OCR 引擎。
  • scaleFactor - 图像放大因子。在传递给 OCR 引擎之前,源图像通过该因子放大。默认值为 3.5。如果文本使用大字体渲染,可以将其设置为一个较低的值以提高 OCR 性能。
# Get all text using German language hint
test.log( getOcrText( { "language": "German" } ) )
// Get all text using German language hint
test.log( getOcrText( { language: "German" } ) )
# Get all text using German language hint
test::log( getOcrText( { language => "German" } ) )
# Get all text using German language hint
Test.log( getOcrText( { "language" => "German" } ) )
# Get all text using German language hint
test log [ getOcrText { language "German" } ]

如果将搜索区域指定为最后一个参数,则仅在与之对应的区域内执行 OCR。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。也可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

搜索区域还可以是一个 Image Object 对象。在这种情况下,不会捕获新的屏幕截图,而是使用指定的图片。目前尚无法将 OCR 范围限定在 Image 对象的某个部分;请使用 Image.copy() 来剪切相关部分。

# Find all text on the MyWidget object
test.log( getOcrText( {}, waitForObject( names.MyWidget ) )

# Find all text on multiple objects
test.log( getOcrText( {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] ) )

# Find all text on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
test.log( getOcrText( {}, bounds ) )

# Find all text in the specified area
test.log( getOcrText( {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ) )

# Find all text on all top-level objects
test.log( getOcrText( {}, "all" ) )
# Find all text on the MyWidget object
test.log( getOcrText( {}, waitForObject( names.MyWidget ) ) );

// Find all text on multiple objects
test.log( getOcrText( {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] ) );

// Find all text on the left half of the MyWidget object
var bounds = object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
test.log( getOcrText( {}, bounds ) );

// Find all text in the specified area
test.log( getOcrText( {}, new UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ) );

// Find all text on all top-level objects
test.log( getOcrText( {}, "all" ) );
# Find all text on the MyWidget object
test::log( getOcrText( {}, waitForObject( names::MyWidget ) ) );

# Find all text on multiple objects
test::log( getOcrText( {}, ( waitForObject( names::MyWidget ),
                            waitForObject( names::MyOtherWidget ) ) ) );

# Find all text on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
test::log( getOcrText( {}, bounds ) );

# Find all text in the specified area
test::log( getOcrText( {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) ) );

# Find all text on all top-level objects
test::log( getOcrText( {}, "all" ) )
# Find all text on the MyWidget object
Test.log( getOcrText( {}, waitForObject( names.MyWidget ) ) );

# Find all text on multiple objects
Test.log( getOcrText( {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] ) );

# Find all text on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
Test.log( getOcrText( {}, bounds ) );

# Find all text in the specified area
Test.log( getOcrText( {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) ) );

# Find all text on all top-level objects
Test.log( getOcrText( {}, "all" ) );
# Find all text on the MyWidget object
test log [ getOcrText {} [ waitForObject $names::MyWidget ] ]

# Find all text on multiple objects
test log [ getOcrText {} { [ waitForObject $names::MyWidget ],
                           [ waitForObject $names::MyOtherWidget ] } ]

# Find all text on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
test log [ getOcrText {} $bounds ]

# Find all text in the specified area
test log [ getOcrText {} [ construct ScreenRectangle 100 100 200 300 ] ]

# Find all text on all top-level objects
test log [ getOcrText {} "all" ]

ScreenRectangle findOcrText(text, [parameterMap], [searchRegion])

此函数将对显示进行光学字符识别,同时显示当前运行的应用程序,并在结果集中搜索特定文本。它将返回一个与文本位置相对应的 ScreenRectangle 对象。

OCR 将在组成桌面的所有可用屏幕上执行。至少在 Windows 和基于 X11 的系统上是如此。对于在 macOS 上实现多屏设置的 OCR,请联系技术支持。

可以通过传递通过可选 parameterMap 参数传入的条目来配置搜索行为。

  • occurrence - 出现索引。默认情况下,将返回第一个文本匹配项(索引为1)。索引值2及以上将选择连续的匹配项,直到可用。
  • language - OCR 引擎的语言提示。使用空字符串将使用 OCR 引擎的默认值。默认值是 testSettings.defaultOcrLanguage 属性的值。
  • profiles - OCR 引擎特定配置文件名称的数组。此参数仅在支持配置文件的引擎中使用。
  • options - 引擎特定选项名称和值的映射。这些选项在加载指定的配置文件后传递给 OCR 引擎。
  • scaleFactor - 图像放大因子。在传递给 OCR 引擎之前,源图像通过该因子放大。默认值为 3.5。如果文本使用大字体渲染,可以将其设置为一个较低的值以提高 OCR 性能。
# Click on text
mouseClick( findOcrText( "Test Text" ) )
# Click on text in German
mouseClick( findOcrText( "Test Text", { "language": "German" } ) )
// Click on text
mouseClick( findOcrText( "Test Text" ) );
// Click on text in German
mouseClick( findOcrText( "Test Text", { language: "German" } ) );
# Click on text
mouseClick( findOcrText( "Test Text" ) );
# Click on text in German
mouseClick( findOcrText( "Test Text", { "language" => "German" } ) );
# Click on text
mouseClick( findOcrText( "Test Text" ) )
# Click on text in German
mouseClick( findOcrText( "Test Text", { "language" => "German" } ) )
# Click on text
invoke mouseClick[ findOcrText "Test Text" ]
# Click on text in German
invoke mouseClick[ findOcrText "Test Text" { language "German" } ]

此函数只对屏幕内容执行单个OCR。如果未找到指定的文本,则会抛出异常。调用此函数在以下情况下很有用:a) 文本存在儿乎肯定或b) 需要快速检查是否存在。在其他所有情况下,首选使用 ScreenRectangle waitForOcrText(text, [parameterMap], [searchRegion]) 函数进行时间无关的查找。

如果将搜索区域指定为最后一个参数,则仅在与之对应的区域内执行 OCR。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。也可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

搜索区域还可以是一个 Image Object 对象。在这种情况下,不会捕获新的屏幕截图,而是使用指定的图片。目前尚无法将 OCR 范围限定在 Image 对象的某个部分;请使用 Image.copy() 来剪切相关部分。

# Click on text on the MyWidget object
mouseClick( findOcrText( "Click me", {}, waitForObject( names.MyWidget ) )

# Click on text on multiple objects
mouseClick( findOcrText( "Click me", {}, [ waitForObject( names.MyWidget ),
                                                   waitForObject( names.MyOtherWidget ) ] ) )

# Click on text on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
mouseClick( findOcrText( "Click me", {}, bounds ) )

# Click on text in the specified area
mouseClick( findOcrText( "Click me", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ) )

# Click on text on all top-level objects
mouseClick( findOcrText( "Click me", {}, "all" ) )
# Click on text on the MyWidget object
mouseClick( findOcrText( "Click me", {}, waitForObject( names.MyWidget ) ) );

// Click on text on multiple objects
mouseClick( findOcrText( "Click me", {}, [ waitForObject( names.MyWidget ),
                                                   waitForObject( names.MyOtherWidget ) ] ) );

// Click on text on the left half of the MyWidget object
var bounds = object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
mouseClick( findOcrText( "Click me", {}, bounds ) );

// Click on text in the specified area
mouseClick( findOcrText( "Click me", {}, new UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ) );

// Click on text on all top-level objects
mouseClick( findOcrText( "Click me", {}, "all" ) );
# Click on text on the MyWidget object
mouseClick( findOcrText( "Click me", {}, waitForObject( names::MyWidget ) ) );

# Click on text on multiple objects
mouseClick( findOcrText( "Click me", {}, ( waitForObject( names::MyWidget ),
                                                   waitForObject( names::MyOtherWidget ) ) ) );

# Click on text on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
mouseClick( findOcrText( "Click me", {}, bounds ) );

# Click on text in the specified area
mouseClick( findOcrText( "Click me", {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) ) );

# Click on text on all top-level objects
mouseClick( findOcrText( "Click me", {}, "all" ) )
# Click on text on the MyWidget object
mouseClick( findOcrText( "Click me", {}, waitForObject( names.MyWidget ) ) );

# Click on text on multiple objects
mouseClick( findOcrText( "Click me", {}, [ waitForObject( names.MyWidget ),
                                                   waitForObject( names.MyOtherWidget ) ] ) );

# Click on text on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
mouseClick( findOcrText( "Click me", {}, bounds ) );

# Click on text in the specified area
mouseClick( findOcrText( "Click me", {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) ) );

# Click on text on all top-level objects
mouseClick( findOcrText( "Click me", {}, "all" ) );
# Click on text on the MyWidget object
invoke mouseClick [ findOcrText "Click me" {} [ waitForObject $names::MyWidget ] ]

# Click on text on multiple objects
invoke mouseClick [ findOcrText "Click me" {} { [ waitForObject $names::MyWidget ],
                                                        [ waitForObject $names::MyOtherWidget ] } ]

# Click on text on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
invoke mouseClick [ findOcrText "Click me" {} $bounds ]

# Click on text in the specified area
invoke mouseClick [ findOcrText "Click me" {} [ construct ScreenRectangle 100 100 200 300 ] ]

# Click on text on all top-level objects
invoke mouseClick [ findOcrText "Click me" {} "all" ]

SequenceOfObjects findAllOcrText(text, [parameterMap], [searchRegion])

此函数将对显示进行光学字符识别,同时显示当前运行的应用程序,并在结果集中搜索特定文本。它将返回一个与指定文本位置相对应的 ScreenRectangle 对象序列。

OCR 将在组成桌面的所有可用屏幕上执行。至少在 Windows 和基于 X11 的系统上是如此。对于在 macOS 上实现多屏设置的 OCR,请联系技术支持。

可以通过传递通过可选 parameterMap 参数传入的条目来配置搜索行为。

  • language - OCR 引擎的语言提示。使用空字符串将使用 OCR 引擎的默认值。默认值是 testSettings.defaultOcrLanguage 属性的值。
  • profiles - OCR 引擎特定配置文件名称的数组。此参数仅在支持配置文件的引擎中使用。
  • options - 引擎特定选项名称和值的映射。这些选项在加载指定的配置文件后传递给 OCR 引擎。
  • scaleFactor - 图像放大因子。在传递给 OCR 引擎之前,源图像通过该因子放大。默认值为 3.5。如果文本使用大字体渲染,可以将其设置为一个较低的值以提高 OCR 性能。
# Check whether 'Test Text' is displayed on screen 3 times
test.compare( len( findAllOcrText( "Test Text", { "language": "German" } ) ), 3 )
// Check whether 'Test Text' is displayed on screen 3 times
test.compare( findAllOcrText( "Test Text", { "language": "German" } ).length, 3 )
# Check whether 'Test Text' is displayed on screen 3 times
my @locations = findAllOcrText( "Test Text", { language => "German" } );
test::compare( scalar @locations, 3 )
# Check whether 'Test Text' is displayed on screen 3 times
Test.compare( findAllOcrText( "Test Text", { "language" => "German" } ).length, 3 );
# Check whether 'Test Text' is displayed on screen 3 times
test compare [ llength [ findAllOcrText "Test Text" { language "German" } ] ] 3

如果将搜索区域指定为最后一个参数,则仅在与之对应的区域内执行 OCR。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。也可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

搜索区域还可以是一个 Image Object 对象。在这种情况下,不会捕获新的屏幕截图,而是使用指定的图片。目前尚无法将 OCR 范围限定在 Image 对象的某个部分;请使用 Image.copy() 来剪切相关部分。

# Check whether 'Test Text' is displayed on MyWidget 3 times
test.compare( len( findAllOcrText( "Test Text", {}, waitForObject( names.MyWidget ) ) ), 3 )

# Check whether 'Test Text' is displayed on multiple widgets 3 times
test.compare( len( findAllOcrText( "Test Text", {}, [ waitForObject( names.MyWidget ),
                                                               waitForObject( names.MyOtherWidget ) ] ) ), 3 )

# Check whether 'Test Text' is displayed on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
test.compare( len( findAllOcrText( "Test Text", {}, bounds ) ), 3 )

# Check whether 'Test Text' is displayed on the specified area
test.compare( len( findAllOcrText( "Test Text", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ) ), 3 )

# Check whether 'Test Text' is displayed on all top-level objects
test.compare( len( findAllOcrText( "Test Text", {}, "all" ) ), 3 )
// Check whether 'Test Text' is displayed on MyWidget 3 times
test.compare( findAllOcrText( "Test Text", {}, waitForObject( names.MyWidget ) ).length , 3 )

// Check whether 'Test Text' is displayed on multiple widgets 3 times
test.compare( findAllOcrText( "Test Text", {}, [ waitForObject( names.MyWidget ),
                                                          waitForObject( names.MyOtherWidget ) ] ).length, 3 )

// Check whether 'Test Text' is displayed on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
test.compare( findAllOcrText( "Test Text", {}, bounds ) .length, 3 )

// Check whether 'Test Text' is displayed on the specified area
test.compare( findAllOcrText( "Test Text", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ).length, 3 )

// Check whether 'Test Text' is displayed on all top-level objects
test.compare( findAllOcrText( "Test Text", {}, "all" ).length, 3 )
# Check whether 'Test Text' is displayed on MyWidget 3 times
my @locations = findAllOcrText( "Test Text", {}, waitForObject( names::MyWidget ) );
test::compare( scalar @locations, 3 )

# Check whether 'Test Text' is displayed on multiple widgets 3 times
my @locations = findAllOcrText( "Test Text", {}, ( waitForObject( names::MyWidget ),
                                                            waitForObject( names::MyOtherWidget ) ) );
test::compare( scalar @locations, 3 )

# Check whether 'Test Text' is displayed on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
my @locations = findAllOcrText( "Test Text", {}, $bounds );
test::compare( scalar @locations, 3 )

# Check whether 'Test Text' is displayed on the specified area
my @locations = findAllOcrText( "Test Text", {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) );
test::compare( scalar @locations, 3 )

# Check whether 'Test Text' is displayed on all top-level objects
my @locations = findAllOcrText( "Test Text", {}, "all" );
test::compare( scalar @locations, 3 )
# Check whether 'Test Text' is displayed on MyWidget 3 times
Test.compare( findAllOcrText( "Test Text", {}, waitForObject( names.MyWidget ) ).length, 3 );

# Check whether 'Test Text' is displayed on multiple widgets 3 times
Test.compare( findAllOcrText( "Test Text", {}, [ waitForObject( names.MyWidget ),
                                                          waitForObject( names.MyOtherWidget ) ] ).length, 3 );

# Check whether 'Test Text' is displayed on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
Test.compare( findAllOcrText( "Test Text", {}, bounds ).length, 3 );

# Check whether 'Test Text' is displayed on the specified area
Test.compare( findAllOcrText( "Test Text", {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) ).length, 3 );

# Check whether 'Test Text' is displayed on all top-level objects
Test.compare( findAllOcrText( "Test Text", {}, "all" ).length, 3 );
# Check whether 'Test Text' is displayed on MyWidget 3 times
test compare [ llength [ findAllOcrText "Test Text" {} [ waitForObject $names::MyWidget ] ] ] 3

# Check whether 'Test Text' is displayed on multiple widgets 3 times
test compare [ llength [ findAllOcrText "Test Text" {} { [ waitForObject $names::MyWidget ],
                                                                  [ waitForObject $names::MyOtherWidget ] } ] ] 3

# Check whether 'Test Text' is displayed on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
test compare [ llength [ findAllOcrText "Test Text" {} $bounds ] ] 3

# Check whether 'Test Text' is displayed on the specified area
test compare [ llength [ findAllOcrText "Test Text" {} [ construct ScreenRectangle 100 100 200 300 ] ] ] 3

# Check whether 'Test Text' is displayed on all top-level objects
test compare [ llength [ findAllOcrText "Test Text" {} "all" ] ] 3

同步函数

Boolean waitFor(condition)

condition 是要评估的代码片段,作为字符串或函数引用传递,并返回布尔值。waitFor 函数循环一次或多次,并在每次迭代中执行 condition 代码并读取其返回值。每次执行后,如果 condition 代码的返回值为 true,则 waitFor 将结束并返回 true。否则,waitFor 函数将执行另一个迭代,即再次执行 condition 代码,并检查其返回值,循环无限期地进行——或者直到 condition 代码返回 true,在这种情况下 waitFor 将结束并返回 true

此函数设计为快速简单地轮询适用程序中的条件,其中每次 condition 执行都非常短(通常是几秒钟的几分之一),并且总是返回 truefalse。如果需要将脚本执行同步到适用程序中的某个特定状态,则非常有用。

请参阅 如何创建和使用同步点 中的使用示例。

Boolean waitFor(condition, timeoutMSec)

condition 是要评估的代码片段,作为字符串或函数引用传递,并返回布尔值。waitFor 函数循环一次或多次,并在每次迭代中执行 condition 代码并读取其返回值。每次执行后,如果 condition 代码的返回值为 true,则 waitFor 将结束并返回 true。如果 condition 代码返回 false,则 waitFor 函数检查它已运行的时间是否超过了 timeoutMSec——如果是,则 waitFor 结束并返回 false;否则它将进行另一个迭代,从再次执行 condition 代码开始。

此函数设计为快速简单地轮询适用程序中的条件,其中每次 condition 执行都非常短(通常是几秒钟的几分之一),并且总是返回 truefalse。如果需要将脚本执行同步到适用程序中的某个特定状态,则非常有用。

请参阅 如何创建和使用同步点 中的使用示例。

ApplicationContext waitForApplicationLaunch()

ApplicationContext waitForApplicationLaunch(timeoutSecs)

等待新的应用程序启动,Squish随后将其钩入。如果钩入成功,则返回一个表示启动的应用程序的 ApplicationContext 对象。这被Squish用于测试脚本,这些脚本访问由AUT启动的多个应用程序。(另见,应用程序上下文。)

可以指定可选参数 timeoutSecs(以秒为单位的整数)来告诉Squish在抛出错误之前应该准备等待应用程序出现的最长时间。如果指定了此值,则它将覆盖squishrunner的默认AUT超时。如果没有指定,则使用squishserver的默认值——这是20秒,除非已更改;请参阅Squish服务器设置对话框

Object waitForObject(objectOrName)

Object waitForObject(objectOrName, timeoutMSec)

等待直到 objectOrName 对象可访问(即它存在、可见且启用)。如果成功,则返回对象的引用,或者在失败时(即函数超时)抛出一个可捕获的 LookupError 异常。此函数等待由 testSettings.waitForObjectTimeout 属性定义的时间,或如果使用了可选的 timeoutMSec 参数,则等待指定这么多的毫秒。此函数在您想要同步脚本执行时很有用。

给定的名称也可以是本地脚本字典(即哈希)值。

此函数仅适用于可见的(或变得可见的)对象;对于不可见对象,请考虑使用Object waitForObjectExists(name) 函数。如果您只想知道对象是否存在,请使用Boolean object.exists(objectName) 函数。

可以在用户定义的回调函数中对等待的对象进行额外处理。有关详细信息,请参阅waitUntilObjectReady(anObject)

Object waitForObjectExists(name)

Object waitForObjectExists(name, timeoutMSec)

等待直到由 name 标识的对象存在。给定的名称可以是本地脚本字典(即哈希)值。如果成功,则返回对象的引用,或者在失败时(即函数超时)抛出一个可捕获的 LookupError 异常。该函数等待由 testSettings.waitForObjectTimeout 属性定义的时间,或如果使用了可选的 timeoutMSec 参数,则等待这么多的毫秒。

Object waitForObjectItem(objectOrName, itemOrIndex)

Object waitForObjectItem(objectOrName, itemOrIndex, timeoutMSec)

等待直到 objectOrName 对象可访问(即它存在、可见且启用),并且包含一个由 itemOrIndex 标识且自身可访问的项目。

给定的名称也可以是本地脚本字典(即哈希)值。

此函数通常用于访问容器内部的项目,例如列表、表格和树。

表中的 itemOrIndex 可以是一个 行/列 字符串,例如 "4/21"。在树中,它可以是点 (.) 分隔的路径字符串,例如 Mammals.Felines.Cats。在字符串可能重复出现的列表中,可以通过在非唯一字符串后附加 (_),然后是项目的出现索引来选择一个特定的项。例如,"itemtext_3" 会检索包含 "itemtext" 字符串的列表中的第三个项。

注意:当将字符串字面量传递给实际包含之前段落中提到的字符((/)(.)(_))的 waitForObjectItem() 函数时,这些字符需要由 (\\)(两个反斜杠)转义,以使 waitForObjectItem() 函数正常工作。如果没有转义,waitForObjectItem() 函数将截断作为 itemOrIndex 传入的给定字符串,将任何在识别分隔符后面的内容视为 '行/列','索引' 或 '路径' 参数!

返回值取决于 Squish 版本

  • Java、Qt 和 Windows:返回值是对 item 的引用。(引用可以与其他 Squish 函数一起使用。)
  • Web 和其他 Squish 版本:返回值是对 objectOrName(不是项)的引用。

当失败时,即超时时,函数抛出(可捕获的)LookupError 异常。

函数等待由 testSettings.waitForObjectTimeout 属性定义的时间或如果使用了可选的 timeoutMSec 参数,则为那么多毫秒。

可以通过提供用户定义的回调函数在函数返回之前在对象项上进行附加处理。有关详细信息,请参阅 waitUntilObjectItemReady(item)

ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion])

此函数等待指定的 imageFile 在屏幕上出现,通过重复调用 ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion]) 直到达到超时。在成功的情况下,将在屏幕上找到图像的位置作为 ScreenRectangle 返回。可以使用交互函数,如 mouseClick(screenPoint, modifierState, button)doubleClick(screenPoint, modifierState, button)tapObject(screenPoint, modifierState, button) 来在检测到的位置上点击或轻触。

搜索的行为可以通过传递到可选的 parameterMap(键值对)的附加参数进行定制,其中键可以是以下之一

  • interval - 在图像搜索重试之间等待的毫秒数。默认值是 1000(1 秒)。
  • timeout - 在报告图像未找到之前搜索图像的时间,以毫秒为单位。默认值是 20000(20 秒)。
  • occurrence - 出现索引。默认情况下,将返回第一个匹配项(索引为1)。索引值2及以上将选择尽可能多的连续匹配项。
  • tolerant - 启用容错图像搜索模式的布尔开关。在此模式下,模板图像与桌面截图之间的某些差异是可以接受的。默认值是 testSettings.imageSearchTolerant 属性的值。
  • threshold - 模板图像与桌面截图之间的相关性的阈值,以百分比表示。相关性高于阈值的认为与模板图像匹配。此参数的有效值通常介于 99.0100.0 之间。默认值是 testSettings.imageSearchThreshold 属性的值。如果将 tolerant 参数设置为 false,则忽略此参数。
  • multiscale - 启用缩小图像搜索模式的布尔开关。在此模式下,模板图像将扩展为一系列不同大小的图像。随后,这些图像作为图像搜索的模板图像使用。默认值是 testSettings.imageSearchMultiscale 属性的值。如果将 tolerant 参数设置为 false,则忽略此参数。
  • minScale - 模板图像系列大小下限,以百分比表示。调整大小后的模板图像大小将介于原始图像大小的 minScalemaxScale 之间。默认值是 testSettings.imageSearchMinScale 属性的值。如果将 tolerantmultiscale 参数设置为 false,则忽略此参数。
  • maxScale 模板图像系列尺寸的上限,以百分比表示。调整后的模板图像尺寸将在原始图像尺寸的 minScalemaxScale 之间扩展。默认值是 testSettings.imageSearchMaxScale 属性的值。当 tolerantmultiscale 参数设置为 false 时,此参数将被忽略。
# Click on icon.png
mouseClick(waitForImage("icon.png"))
// Click on icon.png
mouseClick(waitForImage("icon.png"));
# Click on icon.png
mouseClick(waitForImage("icon.png"));
# Click on icon.png
mouseClick(waitForImage("icon.png"))
# Click on icon.png
invoke mouseClick [waitForImage "icon.png"]

默认情况下,此函数将反复抓取屏幕内容,直到成功或直到 20 秒过去。可以通过通过 parameterMap 传递的 timeout 值设置更长时间(或更短时间)的等待期,以毫秒为单位。为了执行单个图像搜索,请使用 ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion]) 函数。

# Click on second icon.png, wait maximum 10 seconds
mouseClick(waitForImage("icon.png", {"occurrence": 2, "timeout": 10000})
// Click on second icon.png, wait maximum 10 seconds
mouseClick(waitForImage("icon.png", {occurrence: 2, timeout: 10000}));
# Click on second icon.png, wait maximum 10 seconds
mouseClick(waitForImage("icon.png", {"occurrence" => 2, "timeout" => 10000}));
# Click on second icon.png, wait maximum 10 seconds
mouseClick(waitForImage("icon.png", {"occurrence" => 2, "timeout" => 10000}))
# Click on second icon.png, wait maximum 10 seconds
invoke mouseClick [waitForImage "icon.png" {occurrence 2 timeout 10000}]

匹配算法执行逐像素的彩色值比较。因此,除非启用容错搜索模式,否则屏幕内容和子图像内容必须完全匹配 100%。

# Click on icon.png, found with tolerance of 99.7
mouseClick(waitForImage("icon.png", {'tolerant': True,
                                     'threshold': 99.7,
                                     'multiscale': True,
                                     'minScale': 100.0,
                                     'maxScale': 150.0})
// Click on icon.png, found with tolerance of 99.7
mouseClick(waitForImage("icon.png", {tolerant: true,
                                     threshold: 99.7,
                                     multiscale: true,
                                     minScale: 100.0,
                                     maxScale: 150.0}));
# Click on icon.png, found with tolerance of 99.7
mouseClick(waitForImage("icon.png", {tolerant => true,
                                     threshold => 99.7,
                                     multiscale => true,
                                     minScale => 100.0,
                                     maxScale => 150.0}));
# Click on icon.png, found with tolerance of 99.7
mouseClick(waitForImage("icon.png", {"tolerant" => true,
                                     "threshold" => 99.7,
                                     "multiscale" => true,
                                     "minScale" => 100.0,
                                     "maxScale" => 150.0}))
# Click on icon.png, found with tolerance of 99.7
invoke mouseClick [waitForImage "icon.png" {tolerant true \
                                            threshold 99.7 \
                                            multiscale true \
                                            minScale 100.0 \
                                            maxScale 150.0}]

如果指定了搜索区域作为最后一个参数,则只在与之对应的区域内进行搜索。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。还可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

搜索区域也可以是图像对象对象。在这种情况下不会捕获新的截图,而是使用指定的图像。目前无法将搜索范围限制在图像对象的一个部分内;请使用Image.copy()来剪切相关部分。由于作为搜索区域的图像对象不可能随时间改变,因此该函数不会重复执行图像搜索,并将立即返回结果。

# Find icon.png on the MyWidget object
waitForImage("icon.png", {}, waitForObject( names.MyWidget ) )

# Find icon.png on multiple objects
waitForImage("icon.png", {}, [ waitForObject( names.MyWidget ),
                               waitForObject( names.MyOtherWidget ) ] )

# Find icon.png on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
waitForImage("icon.png", {}, bounds )

# Find icon.png in the specified area
waitForImage("icon.png", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) )

# Find icon.png on all top-level objects
waitForImage("icon.png", {}, "all" )
// Find icon.png on the MyWidget object
waitForImage("icon.png", {}, waitForObject( names.MyWidget ) );

// Find icon.png on multiple objects
waitForImage("icon.png", {}, [ waitForObject( names.MyWidget ),
                               waitForObject( names.MyOtherWidget ) ] );

// Find icon.png on the left half of the MyWidget object
var bounds = object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
waitForImage("icon.png", {}, bounds );

// Find icon.png in the specified area
waitForImage("icon.png", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) );

// Find icon.png on all top-level objects
waitForImage("icon.png", {}, "all" );
# Find icon.png on the MyWidget object
waitForImage("icon.png", {}, waitForObject( names::MyWidget ) );

# Find icon.png on multiple objects
waitForImage("icon.png", {}, ( waitForObject( names::MyWidget ),
                               waitForObject( names::MyOtherWidget ) ) );

# Find icon.png on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
waitForImage("icon.png", {}, bounds );

# Find icon.png in the specified area
waitForImage("icon.png", {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) );

# Find icon.png on all top-level objects
waitForImage("icon.png", {}, "all" )
# Find icon.png on the MyWidget object
waitForImage("icon.png", {}, waitForObject( names.MyWidget ) );

# Find icon.png on multiple objects
waitForImage("icon.png", {}, [ waitForObject( names.MyWidget ),
                               waitForObject( names.MyOtherWidget ) ] );

# Find icon.png on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
waitForImage("icon.png", {}, bounds );

# Find icon.png in the specified area
waitForImage("icon.png", {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) );

# Find icon.png on all top-level objects
waitForImage("icon.png", {}, "all" );
# Find icon.png on the MyWidget object
waitForImage "icon.png" {} [ waitForObject $names::MyWidget ]

# Find icon.png on multiple objects
waitForImage "icon.png" {} { [ waitForObject $names::MyWidget ],
                             [ waitForObject $names::MyOtherWidget ] }

# Find icon.png on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
waitForImage "icon.png" {} $bounds

# Find icon.png in the specified area
waitForImage "icon.png" {} [ construct ScreenRectangle 100 100 200 300 ]

# Find icon.png on all top-level objects
waitForImage "icon.png" {} "all"

ScreenRectangle waitForOcrText(text, [parameterMap], [searchRegion])

此函数将对显示进行光学字符识别,同时显示当前运行的应用程序,并在结果集中搜索特定文本。它将返回一个与文本位置相对应的 ScreenRectangle 对象。

OCR 将在组成桌面的所有可用屏幕上执行。至少在 Windows 和基于 X11 的系统上是如此。对于在 macOS 上实现多屏设置的 OCR,请联系技术支持。

可以通过传递通过可选 parameterMap 参数传入的条目来配置搜索行为。

  • interval - OCR 搜索重试之间的最小毫秒数。默认值为 1000(1秒)。不同 OCR 尝试之间的实际间隔取决于 OCR 引擎的性能,可能会显著更长。
  • timeout - 搜索指定文本并在报告找不到文本之前的时间(毫秒数)。默认值为 20000(20秒)。
  • occurrence - 出现索引。默认情况下,将返回第一个文本匹配项(索引为1)。索引值2及以上将选择连续的匹配项,直到可用。
  • language - OCR 引擎的语言提示。使用空字符串将使用 OCR 引擎的默认值。默认值是 testSettings.defaultOcrLanguage 属性的值。
  • profiles - OCR 引擎特定配置文件名称的数组。此参数仅在支持配置文件的引擎中使用。
  • options - 引擎特定选项名称和值的映射。这些选项在加载指定的配置文件后传递给 OCR 引擎。
  • scaleFactor - 图像放大因子。在传递给 OCR 引擎之前,源图像通过该因子放大。默认值为 3.5。如果文本使用大字体渲染,可以将其设置为一个较低的值以提高 OCR 性能。
# Click on second 'Hier klicken' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Hier klicken", {"occurrence": 2, "language": "German"})
// Click on second 'Hier klicken' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Hier klicken", {occurrence: 2, language: "German"}));
# Click on second 'Hier klicken' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Hier klicken", {"occurrence" => 2, "language" => "German"}));
# Click on second 'Hier klicken' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Hier klicken", {"occurrence" => 2, "language" => "German"}))
# Click on second 'Hier klicken' occurrence, wait maximum 10 seconds
invoke mouseClick [waitForOcrText "Hier klicken" {occurrence 2 language "German"}]

默认情况下,此函数将反复捕获屏幕内容,直到成功或直到20秒过去。可以通过传递到 parameterMaptimeout 值来设置较长的(或较短的)等待时间(毫秒)。为了执行一次 OCR 搜索,请使用ScreenRectangle findOcrText(text, [parameterMap], [searchRegion])函数。

# Click on second 'Click me' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Click me", {"occurrence": 2, "timeout": 10000})
// Click on second 'Click me' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Click me", {occurrence: 2, timeout: 10000}));
# Click on second 'Click me' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Click me", {"occurrence" => 2, "timeout" => 10000}));
# Click on second 'Click me' occurrence, wait maximum 10 seconds
mouseClick(waitForOcrText("Click me", {"occurrence" => 2, "timeout" => 10000}))
# Click on second 'Click me' occurrence, wait maximum 10 seconds
invoke mouseClick [waitForOcrText "Click me" {occurrence 2 timeout 10000}]

如果将搜索区域指定为最后一个参数,则仅在与之对应的区域内执行 OCR。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。也可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

搜索区域也可以是图像对象对象。在这种情况下不会捕获新的截图,而是使用指定的图像。目前无法将 OCR 范围限制在图像对象的一个部分内;请使用Image.copy()来剪切相关部分。由于作为搜索区域的图像对象不可能随时间改变,此函数不会重复执行 OCR 并将立即返回结果。

# Click on text on the MyWidget object
mouseClick( waitForOcrText( "Click me", {}, waitForObject( names.MyWidget ) )

# Click on text on multiple objects
mouseClick( waitForOcrText( "Click me", {}, [ waitForObject( names.MyWidget ),
                                              waitForObject( names.MyOtherWidget ) ] ) )

# Click on text on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
mouseClick( waitForOcrText( "Click me", {}, bounds ) )

# Click on text in the specified area
mouseClick( waitForOcrText( "Click me", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ) )

# Click on text on all top-level objects
mouseClick( waitForOcrText( "Click me", {}, "all" ) )
# Click on text on the MyWidget object
mouseClick( waitForOcrText( "Click me", {}, waitForObject( names.MyWidget ) ) );

// Click on text on multiple objects
mouseClick( waitForOcrText( "Click me", {}, [ waitForObject( names.MyWidget ),
                                              waitForObject( names.MyOtherWidget ) ] ) );

// Click on text on the left half of the MyWidget object
var bounds = object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
mouseClick( waitForOcrText( "Click me", {}, bounds ) );

// Click on text in the specified area
mouseClick( waitForOcrText( "Click me", {}, new UiTypes.ScreenRectangle( 100, 100, 200, 300 ) ) );

// Click on text on all top-level objects
mouseClick( waitForOcrText( "Click me", {}, "all" ) );
# Click on text on the MyWidget object
mouseClick( waitForOcrText( "Click me", {}, waitForObject( names::MyWidget ) ) );

# Click on text on multiple objects
mouseClick( waitForOcrText( "Click me", {}, ( waitForObject( names::MyWidget ),
                                              waitForObject( names::MyOtherWidget ) ) ) );

# Click on text on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
mouseClick( waitForOcrText( "Click me", {}, bounds ) );

# Click on text in the specified area
mouseClick( waitForOcrText( "Click me", {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) ) );

# Click on text on all top-level objects
mouseClick( waitForOcrText( "Click me", {}, "all" ) )
# Click on text on the MyWidget object
mouseClick( waitForOcrText( "Click me", {}, waitForObject( names.MyWidget ) ) );

# Click on text on multiple objects
mouseClick( waitForOcrText( "Click me", {}, [ waitForObject( names.MyWidget ),
                                              waitForObject( names.MyOtherWidget ) ] ) );

# Click on text on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
mouseClick( waitForOcrText( "Click me", {}, bounds ) );

# Click on text in the specified area
mouseClick( waitForOcrText( "Click me", {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) ) );

# Click on text on all top-level objects
mouseClick( waitForOcrText( "Click me", {}, "all" ) );
# Click on text on the MyWidget object
invoke mouseClick [ waitForOcrText "Click me" {} [ waitForObject $names::MyWidget ] ]

# Click on text on multiple objects
invoke mouseClick [ waitForOcrText "Click me" {} { [ waitForObject $names::MyWidget ],
                                                   [ waitForObject $names::MyOtherWidget ] } ]

# Click on text on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
invoke mouseClick [ waitForOcrText "Click me" {} $bounds ]

# Click on text in the specified area
invoke mouseClick [ waitForOcrText "Click me" {} [ construct ScreenRectangle 100 100 200 300 ] ]

# Click on text on all top-level objects
invoke mouseClick [ waitForOcrText "Click me" {} "all" ]

交互函数

doubleClick(screenPoint, modifierState, button)

doubleClick(screenRectangle, modifierState, button)

此函数在由screenPoint指定的位置或在由screenRectangle指定的矩形的中心执行鼠标双击。这两个位置都在屏幕全局坐标中。可选的modifierStatebutton参数指定在点击时按下的键盘修饰符和鼠标按钮。请参阅Squish API 函数参数,以获取有效的modifierState和button值的列表。

keyPress(key)

此函数执行指定key键盘键的按键。此key参数是单个字符或写在尖括号之间的特殊键,例如,对于控制键为"<Ctrl>",对于转换键为"<Alt>",对于转换键为"<Shift>",对于回车键为"<Return>",对于制表键为"<Tab>"

keyRelease(key)

此函数执行指定key键盘键的释放。此key参数是单个字符或写在尖括号之间的特殊键,请参阅keyPress(key)

mouseClick(screenPoint, modifierState, button)

mouseClick(screenRectangle, modifierState, button)

该函数在由 screenPoint 指定的位置或由 screenRectangle 指定矩形的中心位置上执行鼠标点击。这两个位置都在屏幕全局坐标中。可选的 modifierStatebutton 参数指定了点击时按下的键盘修饰符和鼠标按钮。有关有效的修饰符状态和按钮值的列表,请参阅 Squish API 函数参数

mouseMove(x, y)

mouseMove(objectOrName)

mouseMove(objectOrName, x, y)

如果指定了 objectOrName,此函数将鼠标移动到相对于该小部件顶部左边的 xy 位置,否则相对于当前屏幕。

如果没有指定坐标,鼠标将移动到 objectOrName 小部件的中间位置。

如果想要触发需要鼠标处于特定位置的事件,此函数非常有用。例如,工具提示通常只在鼠标位于某个区域上方时出现。

mousePress()

mousePress(mouseButton)

mousePress(mouseButton, modifierState)

mousePress(x, y, mouseButton)

mousePress(x, y, mouseButton, modifierState)

mousePress(objectOrName)

mousePress(objectOrName, mouseButton)

mousePress(objectOrName, mouseButton, modifierState)

mousePress(objectOrName, x, y, mouseButton)

mousePress(objectOrName, x, y, mouseButton, modifierState)

此函数执行鼠标点击。所有参数都是可选的,但坐标 (x,y) 必须同时存在或都不存在。

如果提供了 xy 坐标,则按下操作将在这些坐标处执行,或者在指定了 objectOrName 对象的情况下相对于该对象执行,否则相对于当前屏幕。如果没有提供坐标,则按下操作将在选择有 objectOrName 对象的情况下在对象中间执行,否则在鼠标当前位置执行。

默认情况下使用 MouseButton.LeftButton,但可以通过指定可选的 mouseButton 参数来更改。同样,使用无修饰符的默认修饰符状态,但可以通过指定 modifierState 参数来更改。有关 mouseButton 参数和 modifierState 参数的有效值的详细信息,请参阅 Squish API 函数参数

注意:在 Windows 系统上执行测试时,默认使用 MouseButton.PrimaryButton 而不是 MouseButton.LeftButton。这意味着如果 Windows 鼠标按钮配置为相反,Squish 将使用右鼠标按钮进行点击。

此函数有一个特定于工具包的版本,可能具有不同的参数: mousePress()(Windows)。

mouseRelease()

mouseRelease(mouseButton)

mouseRelease(mouseButton, modifierState)

mouseRelease(x, y, mouseButton)

mouseRelease(x, y, mouseButton, modifierState)

mouseRelease(objectOrName)

mouseRelease(objectOrName, mouseButton)

mouseRelease(objectOrName, mouseButton, modifierState)

mouseRelease(objectOrName, x, y, mouseButton)

mouseRelease(objectOrName, x, y, mouseButton, modifierState)

此函数执行鼠标释放操作。所有参数都是可选的,除非坐标必须同时提供或都不提供。

如果提供了 xy 坐标,释放操作将在这些坐标进行,是相对于指定的 objectOrName 对象的,如果指定了该对象,否则相对于当前屏幕。如果没有提供坐标,则在指定了 objectOrName 对象的情况下,在对象中间进行释放,否则在鼠标所在的位置进行释放。

默认情况下使用 MouseButton.LeftButton,但可以通过指定可选的 mouseButton 参数来更改。同样,使用无修饰符的默认修饰符状态,但可以通过指定 modifierState 参数来更改。有关 mouseButton 参数和 modifierState 参数的有效值的详细信息,请参阅 Squish API 函数参数

注意:在 Windows 系统上执行测试时,默认使用 MouseButton.PrimaryButton 而不是 MouseButton.LeftButton。这意味着如果 Windows 鼠标按钮配置为相反,Squish 将使用右鼠标按钮进行点击。

此函数有一个特定于工具包的版本,可能具有不同的参数: mouseRelease() (Windows)。

tapObject(screenPoint, modifierState, button)

tapObject(screenRectangle, modifierState, button)

此函数在 screenPoint 指定的位置或 screenRectangle 指定的矩形的中心执行触摸点击。这两个位置都在屏幕全局坐标中。可选的 modifierStatebutton 参数指定了在点击期间按下的键盘修饰符和鼠标按钮。有关有效 modifierState 和 button 值的列表,请参阅 Squish API 函数参数

调试函数

str className(object)

此函数返回对象的类名作为字符串。(可以使用 Object waitForObject(objectOrName) 函数或 Object findObject(objectName) 函数获取合适的对象。)

注意:此函数仅适用于 Python 测试脚本。对于其他脚本语言,请使用 String typeName(object) 函数。

highlightObject(objectOrName, [msec])

此函数通过红色矩形突出显示由 objectOrName 指定的屏幕位置。如果对是否通过 Object waitForObject(objectOrName)ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion]) 和相关函数找到的对象是否是正确的对象有疑问,这种可视化确认可能很有用。

除非有可选的 timeout 参数覆盖,否则红色叠加将在屏幕上保持 3 秒。

Boolean isNull(object)

该函数在对象object为null(例如,C++中的空指针)时返回true值;否则返回false值。(可以使用Object waitForObject(objectOrName)函数或Object findObject(objectName)函数来获取一个合适的对象。)

String typeName(object)

该函数返回对象的类名作为字符串。(可以使用Object waitForObject(objectOrName)函数或Object findObject(objectName)函数来获取一个合适的对象。)对于在测试脚本中创建的对象,这里是它们的实际类型名称。对于小部件和其他应用程序对象,Squish会尝试返回正确的类型名称,如果无法实现,则返回"Squish"的通用对象类型名称"Object"。

JavaScript、Perl、Ruby和Tcl脚本应始终返回正确的类型名称。Python脚本通常对于应用程序对象返回"Object",但Squish的Python API包括str className(object)函数,该函数返回给定对象的正确类名,无论该对象是在测试脚本中创建的还是应用程序对象。

test.breakpoint()

该函数会导致调试器在本位置停止。

test.attachFile(pathToFile, message)

该函数会将pathToFile引用的文件复制到启动Squish时指定的测试报告目录,并在如果报告生成器支持此功能的情况下创建一个指向文件副本的条目。可选的message允许指定附件的简短描述,并将包含在报告中。

pathToFile可以指定使用绝对路径或相对路径附加的文件。在使用相对路径的情况下,它将被添加到当前正在执行测试的脚本的脚本解释器的当前工作目录。

目前,只有XML3、HTML和JSON报告生成器支持附件。其他生成器可以与test.attachFile一起使用,但只会生成包含附加文件路径和提供的message的正常日志消息。

复制的文件将出现在名为"attachments"的子目录中,该目录位于以测试用例命名的目录内。反之,测试用例目录位于以套件命名的目录内,该目录位于测试报告目录。复制的文件名称将与原始指定文件的文件名相匹配。如果报告中已存在同名文件,将添加一个数字以使文件名唯一。

对于不需要指定测试报告目录但需要文件(如xml2、xml或xmljunit)的报告生成器,您可以在调用squishrunner时指定--resultdir以指定测试报告目录,或者当调用test.attachFile时,Squish将回退到在测试用例执行时在当前正在执行的测试用例中生成附件目录。

test.attachDesktopScreenshot(message)

该函数将从当前活动AUT运行系统的桌面创建屏幕截图并将其存储在测试报告目录中。此外,在测试报告中还会记录一个条目,指示截图文件的路径以及包含指定的message

屏幕截图将以无损PNG格式保存在与使用test.attachFile(pathToFile, message)函数附加的文件相同的附件子目录下,因此对该报告生成器使用的限制和注释也适用于此函数。

此API是test.attachImage(grabDesktopScreenshot(), message)的简写。

test.attachImage(image, message)

该函数将指定的图像存储在测试报告目录中。此外,在测试报告中还将记录一个条目,其中包含图像文件的路径以及指定的message

图像将以无损PNG格式保存在与使用test.attachFile(pathToFile, message)函数附加的文件相同的附件子目录下,因此对该报告生成器使用的限制和注释也适用于此函数。

test.startVideoCapture(message)

此函数将在测试应用运行的系统上启动桌面视频捕获。视频文件将成为测试报告的一部分,并使用指定的message记录在测试报告中。message是可选的:如果没有指定,将添加包含应用程序名称的默认消息到报告中。

在脚本中的任何时刻,对于给定应用程序上下文,只有一个视频捕获。在同一应用程序上下文中尝试启动另一个视频捕获将导致错误。

当测试应用终止或断开连接时(无论是通过测试脚本命令还是作为测试用例结束的一部分),将停止视频捕获。如果测试应用意外终止,视频文件可能不完整。

可以在启动后任何时刻使用test.stopVideoCapture(message)显式终止视频捕获。

如果通过--enable-video-capture命令行选项启用了所有应用的视频捕获,则此函数将只在测试报告中添加一个日志消息(另请参阅回放选项 –enable-video-capture)。

注意:视频捕获功能有一些技术限制,见我们知识库中的已知视频捕获限制

test.stopVideoCapture(message)

此函数将在测试应用运行的系统上停止桌面视频捕获。使用指定的message将视频捕获的结束记录在测试报告中。message是可选的:如果没有指定,将添加包含应用程序名称的默认消息到报告中。

尝试在没有任何视频捕获活动的地方停止视频捕获会导致抛出异常。视频捕获是通过test.startVideoCapture(message)启动的,或者通过在命令行上使用--enable-video-capture选项启用(另请参阅回放选项 –enable-video-capture)。

如果通过--enable-video-capture命令行选项启用了所有应用的视频捕获,则此函数将只在测试报告中添加一个日志消息。当应用程序已经终止时,视频捕获将自动终止。

转换函数

Object cast(object, type)

将该object转换为指定的type,并返回该对象或不可变类型的对象的新副本的引用。 (可以使用Object waitForObject(objectOrName)函数或Object findObject(objectName)函数来获取合适的对象。)所需的type可以通过名称(作为字符串)或使用类型对象指定。

对于可变对象,将修改对象本身。

如果转换失败,则返回未更改的对象引用。

注意:Python程序员应该注意,整数类型转换,如int(x)不会工作;请使用x = cast(x, int)x = cast(x, "int")代替。 或者如果您喜欢,导入import __builtin__(Python 2)或import builtins(Python 3),然后使用x = __builtin__.int(x)(Python 2)或x = builtins.int(x) (Python 3)。 这是必要的,因为Squish在Python中实现了自己的int对象。

此函数可以通过下标转换(例如,从QWidgetQTextEdit)。 有关用法示例,请参阅特定对象的处理程序。 还请参阅Object object.convertTo(object, typeName)函数。

验证函数

比较、验证和异常函数用于将应用于正在运行的AUT的测试结果记录到Squish的测试日志中,作为通过或失败。 其他函数可用于以编程方式将任何类型的测试结果记录到测试日志中。 参见验证点创建视图如何创建和使用验证点

grabDesktopScreenshot()

此函数捕获AUT正在运行的屏幕上的图像,并返回一个Image Object

var img = grabDesktopScreenshot();
test.attachImage(img);
my $img = grabDesktopScreenshot();
test::attachImage($img);
img = grabDesktopScreenshot()
test.attachImage(img)
img = grabDesktopScreenshot()
Test.attachImage(img)
set img [grabDesktopScreenshot]
test attachImage $img

saveDesktopScreenshot(filename)

此函数捕获AUT正在运行的屏幕上的图像,并将其存储在squishide(或squishrunner)正在执行的计算机上。

如果没有指定路径,则文件将存储在squishrunner进程的工作目录中。(squishrunner的默认工作目录是它当前正在执行的测试用例的路径。)

如果指定了相对路径,则相对于squishrunner进程的工作目录。(squishrunner的默认工作目录是它当前正在执行的测试用例的路径。)

如果指定了绝对路径,则直接使用该路径。

文件名应具有表示用于的图像格式的后缀。以下是一个在JavaScript、Python、Ruby和Perl中有效的使用示例

saveDesktopScreenshot("screen.png");

对于Tcl

saveDesktopScreenshot "screen.png"

可用的格式可能会有所不同,但始终至少包括以下格式

  • .bmp — Windows位图
  • .png — 可便携网络图形
  • .ppm — 可便携像素图
  • .xbm — X11位图(单色)
  • .xpm — X11像素图

此API是调用grabDesktopScreenshot()并随后在结果图像上调用Image.save(fileName)的简写。

saveObjectSnapshot(objectNameOrReference, snapshotImageFile.xml)

此函数捕获一个对象的快照并将它以xml格式保存到指定的文件中。对象快照表示对象的状态,包括所有属性和子对象及其属性。

如果指定了快照的相对路径,它相对于squishrunner进程的工作目录。(squishrunner的默认工作目录是当前执行的测试用例的路径。)

如果指定了绝对路径,则直接使用该路径。

快照中实际保存的内容可以通过修改位于/etc/edition_snapshot_filter.xml(其中<edition>是您正在使用的Squish版本,例如java、qt、web、windows、mac、ios或android)的.xml文件进行定制。使用本功能,您可以排除某些类或类的属性,并决定在输出中包含实际名称或符号名称。

以下是一个在JavaScript、Python、Ruby和Perl中合法使用的示例。

saveObjectSnapshot( objectNameOrReference, "objectSnapshot.xml" );

对于Tcl

saveObjectSnapshot objectNameOrReference "objectSnapshot.xml"

Boolean test.compare(value1, value2)

Boolean test.compare(value1, value2, message)

此函数比较value1value2,如果它们相等,将在测试日志中添加类型为PASS的测试结果,并返回true值。否则,在测试日志中添加类型为FAIL的测试结果,并返回false值。

如果存在可选的message参数(类型为字符串,例如注释、问题编号或测试计划引用),则无论测试是否通过,它都会添加到测试结果中。

可以使用testSettings.breakOnFailure属性,在验证失败时使调试器停止。

可以使用testSettings.throwOnFailure属性,在验证失败时使此函数引发脚本异常。

Boolean test.exception(code)

Boolean test.exception(code, message)

此函数执行通过字符串code传递的代码,期望它引发异常。如果引发异常,则在测试日志中添加类型为PASS的测试结果,并返回true值;否则,在测试日志中添加类型为FAIL的测试结果,并返回false值。

如果存在可选的message参数(类型为字符串,例如注释、问题编号或测试计划引用),则无论测试是否通过,它都会添加到测试结果中。

可以使用testSettings.breakOnFailure属性,在给定代码没有引发异常的情况下使调试器停止。

可以使用testSettings.throwOnFailure属性,在给定代码没有引发异常的情况下使此函数引发脚本异常。

test.fail(message)

test.fail(message, detail)

此函数无条件地将指定的message字符串(如果有的话,还包括detail字符串)添加到Squish的测试日志中的FAIL条目。

可以使用testSettings.breakOnFailure属性,在此函数处停止调试器。

可以使用testSettings.throwOnFailure属性,使此函数额外地引发脚本异常。

test.fatal(message)

test.fatal(message, detail)

该函数无条件地将具有给定 message 字符串和(如果提供)detail 字符串的 FATAL 条目添加到 Squish 的测试日志中。

可以使用testSettings.breakOnFailure属性,在此函数处停止调试器。

可以使用testSettings.throwOnFailure属性,使此函数额外地引发脚本异常。

test.log(message)

test.log(message, detail)

该函数无条件地将具有给定 message 字符串和(如果提供)detail 字符串的 LOG 条目添加到 Squish 的测试日志中。

test.pass(message)

test.pass(message, detail)

该函数无条件地将具有给定 message 字符串和(如果提供)detail 字符串的 PASS 条目添加到 Squish 的测试日志中。

注意:由于 pass 是 Python 中的保留字,因此该函数的 Python 版本称为 test.passes

test.resultCount(resultCategory)

此函数返回当前测试用例给定 resultCategory 的结果数量。必须使用以下字符串之一:"errors""fails""fatals""passes""testcases""tests""warnings""xfails""xpasses"

结果计数仅在当前运行的测试用例上收集。

布尔型 test.verify(condition)

布尔型 test.verify(condition, message)

此函数评估 condition,如果评估为真值(例如,true 或 1),则在测试日志中添加类型为 PASS 的测试结果。否则,在测试日志中添加类型为 FAIL 的结果。在两种情况下,该函数返回评估 condition 的结果(即在 PASS 上为真值,在 FAIL 上为假值)。

如果存在可选的 message 参数(字符串类型——例如,注释、缺陷编号或测试计划引用),无论测试是通过还是失败,都会将其添加到测试结果中。

可以使用testSettings.breakOnFailure属性,在验证失败时使调试器停止。

可以使用testSettings.throwOnFailure属性,在验证失败时使此函数引发脚本异常。

布尔型 test.vp(name)

布尔型 test.vp(name, message)

此函数执行名为 name 的验证点。如果验证点的比较成功,则将类型为 PASS 的测试结果添加到测试日志中,并返回一个真值。否则,将类型为 FAIL 的结果添加到测试日志,并返回一个假值。

如果验证点引用的对象找不到,则该函数将返回一个假值,如果 Squish 被配置为这样做,则可能还会弹出对象未找到对话框。

如果存在可选的 message 参数(字符串类型——例如,注释、缺陷编号或测试计划引用),无论测试是通过还是失败,都会将其添加到测试结果中。

在发生 FAIL 的情况下,除非 squishrunner 被配置为 --abortOnFail,否则测试用例将转到下一个测试语句。

可以使用testSettings.breakOnFailure属性,在验证失败时使调试器停止。

可以使用testSettings.throwOnFailure属性,在验证失败时使此函数引发脚本异常。

布尔型 test.vpWithObject(name, objectNameOrReference)

此函数执行名为name的验证点,此处执行与对象objectNameOrReference的比较,而不是与VP文件中存在的对象进行比较。如果验证点的比较成功,则将类型为PASS的测试结果添加到测试日志,并且此函数返回一个true值。否则,将类型为FAIL的结果添加到测试日志,并返回一个false值。如果VP包含/验证多个对象,test.vpWithObject()将记录一个ERROR

可以使用testSettings.breakOnFailure属性,在验证失败时使调试器停止。

可以使用testSettings.throwOnFailure属性,在验证失败时使此函数引发脚本异常。

Boolean test.vpWithImage(name, imageOrFilePath)

此函数执行名为name的截图验证点,此处执行与imageOrFilePath的比较,而不是获取验证点文件中指定对象的截图。获得imageOrFilePath可以是Image对象或图像文件的路径。如果验证点的比较成功,则将类型为PASS的测试结果添加到测试日志,并返回一个true值。否则,将类型为FAIL的结果添加到测试日志,并返回一个false值。如果VP包含/验证多个对象或不是截图VP,test.vpWithImage()将记录一个ERROR

可以使用testSettings.breakOnFailure属性,在验证失败时使调试器停止。

可以使用testSettings.throwOnFailure属性,在验证失败时使此函数引发脚本异常。

test.warning(message)

test.warning(message, detail)

此函数无条件将带有给定message字符串的WARNING条目添加到Squish的测试日志中,如果提供了detail字符串,也可以添加该字符串。

test.skip(message)

test.skip(message, detail)

此函数通过抛出异常并将带有给定message字符串的SKIPPED条目添加到Squish的测试日志中,并如果提供了detail字符串则添加该字符串,来跳过当前脚本测试用例或当前BDD场景的进一步执行(或BDD场景轮廓迭代)。如果测试用例在跳过之前记录了验证失败,则它仍然被视为失败。

Boolean test.xcompare(value1, value2)

Boolean test.xcompare(value1, value2, message)

此函数用于处理测试脚本中的预期失败。用于测试有一天应该修复的错误。

该函数比较value1value2,如果它们不相等,则在测试日志中添加类型为XFAIL(期望失败)的测试结果并返回一个false值。否则,在测试日志中添加类型为XPASS(意外的PASS)的测试结果并返回一个true值。

“预期失败”结果用于确切知道由于AUT中的错误,比较或验证将现在出错的情况。

在您想要确保属性永远不会具有特定值的测试用例中,我们建议使用test.verify(),或者直接使用if结构与test.fail()一起使用。

如果存在可选的 message 参数(字符串类型——例如,注释、缺陷编号或测试计划引用),无论测试是通过还是失败,都会将其添加到测试结果中。

可以使用testSettings.breakOnFailure属性在验证意外通过时停止调试器。

可以使用testSettings.throwOnFailure属性在验证意外通过时使此函数引发脚本异常。

test.xfail(message)

test.xfail(message, detail)

此函数无条件地将带有指定message字符串的XFAIL(预期的失败)条目添加到Squish的测试日志中,如果提供了detail字符串,也会添加。预期的失败结果适用于已知由于自治程序(AUT)中的错误,比较或验证将立即错误的情况。

test.xpass(message)

test.xpass(message, detail)

此函数无条件地将带有指定message字符串的XPASS(意外的通过)条目添加到Squish的测试日志中,如果提供了detail字符串,也会添加。

注意:此函数的Python版本名为test.xpasses,以确保与Python API中test.passes的命名保持一致。

布尔测试.test.xverify(condition)

布尔测试.test.xverify(condition, message)

此功能用于在测试脚本中测试预期的失败。用于处理应有一天修复的错误。

该函数评估condition,如果它评估为假值(例如,任何不是true或非零的东西),则将在测试日志中添加类型为XFAIL(预期失败)的测试结果。否则,将添加类型为XPASS(意外通过)的测试结果。在两种情况下,该函数都返回评估condition的结果(即在XFAIL上为假值,在XPASS上为真值)。

如果存在可选的 message 参数(字符串类型——例如,注释、缺陷编号或测试计划引用),无论测试是通过还是失败,都会将其添加到测试结果中。

可以使用testSettings.breakOnFailure属性在验证意外通过时停止调试器。

可以使用testSettings.throwOnFailure属性在验证意外通过时使此函数引发脚本异常。

布尔测试.test.xvp(name)

布尔测试.test.xvp(name, message)

此功能用于测试预期的验证点失败。用于处理应有一天修复的错误。

此功能执行名为name的验证点。如果验证点的比较失败,则将在测试日志中添加类型为XFAIL(预期失败)的测试结果,并返回真值。否则,在测试日志中添加类型为XPASS(意外通过)的结果,并返回假值。

如果验证点引用的对象找不到,则该函数将返回一个假值,如果 Squish 被配置为这样做,则可能还会弹出对象未找到对话框。

如果存在可选的 message 参数(字符串类型——例如,注释、缺陷编号或测试计划引用),无论测试是通过还是失败,都会将其添加到测试结果中。

XPASS的情况下,除非squishrunner被配置为--abortOnFail,否则测试用例将进入下一个测试语句。

可以使用testSettings.breakOnFailure属性在验证意外通过时停止调试器。

可以使用testSettings.throwOnFailure属性在验证意外通过时使此函数引发脚本异常。

StackTrace test.stackTrace()

StackTrace test.stackTrace(startFrame)

StackTrace test.stackTrace(startFrameIndex, maxFrameCount)

此功能返回一个表示当前活动函数调用的堆栈跟踪的列表。列表中的第一个元素包含有关StackTrace test.stackTrace()调用位置的信息,第二个元素包含调用者的信息,依此类推。列表中的最后一个元素通常是main函数调用。

返回列表中的每个堆栈跟踪值具有两个字段

  • fileName:执行函数调用的源文件名称。
  • line:执行函数调用的脚本文件中的行号。

如果提供了可选的 startFrameIndex 参数(一个数字),则会跳过最近给定数量的帧。这在从框架函数检索堆栈跟踪时很有用,在这种情况下,堆栈跟踪可能不应该包括框架本身的内部代码。如果没有提供此参数,则默认为零,即不跳过任何帧。

如果同时提供了 startFrameIndexmaxFrameCount,则堆栈跟踪将限制在 maxFrameCount 帧内,即不会回溯到对 main 函数的初始调用。这在深层嵌套脚本框架中可以提高性能。

test.fixateResultContext()

test.fixateResultContext(ancestorFrameIndex)

test.restoreResultContext()

这些函数临时强制其他 Squish 函数(如 布尔 test.xcompare(value1, value2)布尔 test.verify(condition))创建的测试结果将重写其报告条目的位置,以便结果条目的位置不再是 text.xcompare 被调用的位置,而是当前函数的祖先帧中的任何位置。

test.fixateResultContext 函数调整生成测试结果条目时使用的调用堆栈帧;默认情况下,它将重写所有结果条目的位置,使它们看起来是从父堆栈帧发出的。通过传递可选参数 1 可以达到相同的效果。您可以选择其他值来引用其他祖先堆栈帧,例如,2 将引用祖父堆栈帧(调用者的调用者)。

使用 test.restoreResultContext 来撤销之前的 test.fixateResultContext 调用的效果。请注意,调用可以是嵌套的,即,对 fixateResultContext 的多次后续调用需要多次调用 restoreResultContext

这里有一些示例;请注意,由 test.compare 调用触发的测试结果条目将以指向 main 函数的位置进行记录,而不是指向 libraryFunction 函数。

def libraryFunction():
  test.fixateResultContext(1)
  test.compare("Apples", "Oranges")
  test.restoreResultContext()

def main():
  libraryFunction()
function libraryFunction()
{
  test.fixateResultContext(1);
  test.compare("Apples", "Oranges");
  test.restoreResultContext();
}

function main()
{
  libraryFunction();
}
sub libraryFunction
{
  test::fixateResultContext(1);
  test::compare("Apples", "Oranges");
  test::restoreResultContext();
}

sub main
{
  libraryFunction();
}
require 'squish'

include Squish

def libraryFunction
  Test.fixateResultContext(1)
  Test.compare("Apples", "Oranges")
  Test.restoreResultContext()
end

def main
  libraryFunction()
end
proc libraryFunction {} {
  test fixateResultContext 1
  test compare "Apples" "Oranges"
  test restoreResultContext
}

proc main {} {
  libraryFunction
}
  • 当不使用 fixateResultContext/restoreResultContext 时,与比较相关的脚本文件位置。这是默认设置 - 测试结果与相应的 test 语句的位置相关联。
  • 使用 fixateResultContext/restoreResultContext 时的比较相关的脚本文件位置,如在此处所示。由于 fixateResultContext 调用,由 test.compare 语句生成的测试结果在调用位置记录,即 libraryFunction 被调用的地方。

注意:在使用 test.fixateResultContext 后省略对 test.restoreResultContext 的调用,可能会导致测试报告非常误导。

布尔 test.imagePresent(imageFile, [parameterMap], [searchRegion])

布尔 test.imageNotPresent(imageFile, [parameterMap], [searchRegion])

此函数将在显示上也显示当前正在运行的应用程序的情况下,对存储在 imageFile 中的模板图像进行搜索。如果成功,则将添加类型为 PASS 的测试结果到测试日志中,并返回 true。否则,将在测试日志中添加类型为 FAIL 的测试结果,并返回 false

函数的imageNotPresent()变体与imagePresent()完全相同,只不过它等待找到图像的反面情况。它可用于验证图像不存在。

子图像搜索是按从左到右、从上到下的顺序进行的。首先成功的匹配被选中。若要选择其他匹配项,请使用以下描述的occurrence参数。

将搜索包括桌面在内的所有可用屏幕。至少在Windows和基于X11的系统上是这样。对于在macOS上多屏幕设置中的搜索,请咨询技术支持。

可以通过传递通过可选 parameterMap 参数传入的条目来配置搜索行为。

  • occurrence - 发生索引。默认情况下将选择第一个匹配项(索引为1)。索引值2及以上将选择连续的匹配项。
  • interval - 在图像搜索重试之间等待的毫秒数。默认值是 1000(1 秒)。
  • timeout - 在报告图像未找到之前搜索图像的时间,以毫秒为单位。默认值是 20000(20 秒)。
  • tolerant - 启用容错图像搜索模式的布尔开关。在此模式下,模板图像与桌面截图之间的某些差异是可以接受的。默认值是 testSettings.imageSearchTolerant 属性的值。
  • threshold - 模板图像与桌面截图之间的相关性的阈值,以百分比表示。相关性高于阈值的认为与模板图像匹配。此参数的有效值通常介于 99.0100.0 之间。默认值是 testSettings.imageSearchThreshold 属性的值。如果将 tolerant 参数设置为 false,则忽略此参数。
  • multiscale - 启用缩小图像搜索模式的布尔开关。在此模式下,模板图像将扩展为一系列不同大小的图像。随后,这些图像作为图像搜索的模板图像使用。默认值是 testSettings.imageSearchMultiscale 属性的值。如果将 tolerant 参数设置为 false,则忽略此参数。
  • minScale - 模板图像系列大小下限,以百分比表示。调整大小后的模板图像大小将介于原始图像大小的 minScalemaxScale 之间。默认值是 testSettings.imageSearchMinScale 属性的值。如果将 tolerantmultiscale 参数设置为 false,则忽略此参数。
  • maxScale 模板图像系列尺寸的上限,以百分比表示。调整后的模板图像尺寸将在原始图像尺寸的 minScalemaxScale 之间扩展。默认值是 testSettings.imageSearchMaxScale 属性的值。当 tolerantmultiscale 参数设置为 false 时,此参数将被忽略。
  • message - 一个可选的详细描述(字符串类型),无论测试是否通过,都会添加到测试结果中,类似于Boolean test.compare(value1, value2)message参数。
# Verify the icon.png is displayed
test.imagePresent("icon.png")
# Verify the icon.png is displayed at least twice
test.imagePresent("icon.png", {"occurrence": 2})
// Verify the icon.png is displayed
test.imagePresent("icon.png");
// Verify the icon.png is displayed at least twice
test.imagePresent("icon.png", {"occurrence": 2});
# Verify the icon.png is displayed
test::imagePresent("icon.png")
# Verify the icon.png is displayed at least twice
test::imagePresent("icon.png", {"occurrence" => 2})
# Verify the icon.png is displayed
Test.imagePresent("icon.png")
# Verify the icon.png is displayed at least twice
Test.imagePresent("icon.png", {"occurrence" => 2})
# Verify the icon.png is displayed
test imagePresent "icon.png"
# Verify the icon.png is displayed at least twice
test imagePresent "icon.png" {"occurrence": 2}

默认情况下,此函数将反复捕获屏幕内容,直到找到图像或经过20秒。通过parameterMap传入的timeout值可以设置更长的(或更短的)等待时间,单位为毫秒。

匹配算法执行逐像素的彩色值比较。因此,除非启用容错搜索模式,否则屏幕内容和子图像内容必须完全匹配 100%。

# Verify the icon.png is displayed
test.imagePresent( "icon.png", {'tolerant': True,
                                'threshold': 99.7,
                                'multiscale': True,
                                'minScale': 100.0,
                                'maxScale': 150.0})
// Verify the icon.png is displayed
test.imagePresent("icon.png", {tolerant: true,
                               threshold: 99.7,
                               multiscale: true,
                               minScale: 100.0,
                               maxScale: 150.0});
# Verify the icon.png is displayed
test::imagePresent("icon.png", {tolerant => true,
                                threshold => 99.7,
                                multiscale => true,
                                minScale => 100.0,
                                maxScale => 150.0}) );
# Verify the icon.png is displayed
Test.imagePresent("icon.png", {"tolerant" => true,
                               "threshold" => 99.7,
                               "multiscale" => true,
                               "minScale" => 100.0,
                               "maxScale" => 150.0}) )
# Verify the icon.png is displayed
test imagePresent "icon.png" {tolerant true \
                              threshold 99.7 \
                              multiscale true \
                              minScale 100.0 \
                              maxScale 150.0}

如果指定了搜索区域作为最后一个参数,则只在与之对应的区域内进行搜索。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。还可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

searchRegion也可以是一个Image Object对象。在这种情况下,不会捕获新的屏幕截图,而是使用指定的图像。目前无法将搜索范围限制为图像的某部分;请使用Image.copy()剪切相关部分。由于用作搜索区域的Image对象不可能随时间变化,此功能不会反复进行图像搜索,将立即返回结果。

# Verify the icon.png is displayed on the MyWidget object
test.imagePresent("icon.png", {}, waitForObject( names.MyWidget ) )

# Verify the icon.png is displayed on multiple objects
test.imagePresent("icon.png", {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] )

# Verify the icon.png is displayed on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
test.imagePresent("icon.png", {}, bounds )

# Verify the icon.png is displayed in the specified area
test.imagePresent("icon.png", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) )

# Verify the icon.png is displayed on all top-level objects
test.imagePresent("icon.png", {}, "all" )
// Verify the icon.png is displayed on the MyWidget object
test.imagePresent("icon.png", {}, waitForObject( names.MyWidget ) );

// Verify the icon.png is displayed on multiple objects
test.imagePresent("icon.png", {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] );

// Verify the icon.png is displayed on the left half of the MyWidget object
var bounds = object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
test.imagePresent("icon.png", {}, bounds );

// Verify the icon.png is displayed in the specified area
test.imagePresent("icon.png", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) );

// Verify the icon.png is displayed on all top-level objects
test.imagePresent("icon.png", {}, "all" );
# Verify the icon.png is displayed on the MyWidget object
test::imagePresent("icon.png", {}, waitForObject( names::MyWidget ) );

# Verify the icon.png is displayed on multiple objects
test::imagePresent("icon.png", {}, ( waitForObject( names::MyWidget ),
                            waitForObject( names::MyOtherWidget ) ) );

# Verify the icon.png is displayed on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
test::imagePresent("icon.png", {}, bounds );

# Verify the icon.png is displayed in the specified area
test::imagePresent("icon.png", {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) );

# Verify the icon.png is displayed on all top-level objects
test::imagePresent("icon.png", {}, "all" )
# Verify the icon.png is displayed on the MyWidget object
Test.imagePresent("icon.png", {}, waitForObject( names.MyWidget ) );

# Verify the icon.png is displayed on multiple objects
Test.imagePresent("icon.png", {}, [ waitForObject( names.MyWidget ),
                            waitForObject( names.MyOtherWidget ) ] );

# Verify the icon.png is displayed on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
Test.imagePresent("icon.png", {}, bounds );

# Verify the icon.png is displayed in the specified area
Test.imagePresent("icon.png", {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) );

# Verify the icon.png is displayed on all top-level objects
Test.imagePresent("icon.png", {}, "all" );
# Verify the icon.png is displayed on the MyWidget object
test imagePresent "icon.png" {} [ waitForObject $names::MyWidget ]

# Verify the icon.png is displayed on multiple objects
test imagePresent "icon.png" {} { [ waitForObject $names::MyWidget ],
                                   [ waitForObject $names::MyOtherWidget ] }

# Verify the icon.png is displayed on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
test imagePresent "icon.png" {} $bounds

# Verify the icon.png is displayed in the specified area
test imagePresent "icon.png" {} [ construct ScreenRectangle 100 100 200 300 ]

# Verify the icon.png is displayed on all top-level objects
test imagePresent "icon.png" {} "all"

布尔测试 Boolean test.ocrTextPresent(text, [parameterMap], [searchRegion])

布尔测试 Boolean test.ocrTextNotPresent(text, [parameterMap], [searchRegion])

此函数将对显示进行光学字符识别,并搜索结果显示集中的特定文本。如果指定文本存在,将在测试日志中添加类型为PASS的测试结果,并且函数返回true。否则,将在测试日志中添加类型为FAIL的测试结果,并且函数返回false

函数的ocrTextNotPresent()变体与ocrTextPresent()完全相同,只不过它等待找到文本的反面情况。它可用于验证文本不存在。

OCR 将在组成桌面的所有可用屏幕上执行。至少在 Windows 和基于 X11 的系统上是如此。对于在 macOS 上实现多屏设置的 OCR,请联系技术支持。

可以通过传递通过可选 parameterMap 参数传入的条目来配置搜索行为。

  • interval - OCR 搜索重试之间的最小毫秒数。默认值为 1000(1秒)。不同 OCR 尝试之间的实际间隔取决于 OCR 引擎的性能,可能会显著更长。
  • timeout - 搜索指定文本并在报告找不到文本之前的时间(毫秒数)。默认值为 20000(20秒)。
  • occurrence - 出现索引。默认情况下,将返回第一个文本匹配项(索引为1)。索引值2及以上将选择连续的匹配项,直到可用。
  • language - OCR 引擎的语言提示。使用空字符串将使用 OCR 引擎的默认值。默认值是 testSettings.defaultOcrLanguage 属性的值。
  • profiles - OCR 引擎特定配置文件名称的数组。此参数仅在支持配置文件的引擎中使用。
  • options - 引擎特定选项名称和值的映射。这些选项在加载指定的配置文件后传递给 OCR 引擎。
  • scaleFactor - 图像放大因子。在传递给 OCR 引擎之前,源图像通过该因子放大。默认值为 3.5。如果文本使用大字体渲染,可以将其设置为一个较低的值以提高 OCR 性能。
  • message - 一个可选的详细描述(字符串类型),无论测试是否通过,都会添加到测试结果中,类似于Boolean test.compare(value1, value2)message参数。
# Verify the 'Hier klicken' German text is displayed at least twice
test.ocrTextPresent("Hier klicken", {"occurrence": 2, "language": "German"})
// Verify the 'Hier klicken' German text is displayed at least twice
test.ocrTextPresent("Hier klicken", {occurrence: 2, language: "German"});
# Verify the 'Hier klicken' German text is displayed at least twice
test::ocrTextPresent("Hier klicken", {"occurrence" => 2, "language" => "German"});
# Verify the 'Hier klicken' German text is displayed at least twice
Test.ocrTextPresent("Hier klicken", {"occurrence" => 2, "language" => "German"})
# Verify the 'Hier klicken' German text is displayed at least twice
test ocrTextPresent "Hier klicken" {occurrence 2 language "German"}

默认情况下,此函数将反复捕获屏幕内容,直到找到指定的文本或经过20秒。通过parameterMap传入的timeout值可以设置更长的(或更短的)等待时间,单位为毫秒。

如果将搜索区域指定为最后一个参数,则仅在与之对应的区域内执行 OCR。搜索区域可以是 AUT 对象、一个 ScreenRectangle 对象或此类对象的数组。也可以是一个特殊的字符串值 "all",在这种情况下,将使用所有顶层对象。

搜索区域也可以是图像对象对象。在这种情况下不会捕获新的截图,而是使用指定的图像。目前无法将 OCR 范围限制在图像对象的一个部分内;请使用Image.copy()来剪切相关部分。由于作为搜索区域的图像对象不可能随时间改变,此函数不会重复执行 OCR 并将立即返回结果。

# Verify the 'Click me' text is displayed on the MyWidget object
test.ocrTextPresent( "Click me", {}, waitForObject( names.MyWidget )

# Verify the 'Click me' text is displayed on multiple objects
test.ocrTextPresent( "Click me", {}, [ waitForObject( names.MyWidget ),
                                       waitForObject( names.MyOtherWidget ) ] )

# Verify the 'Click me' text is displayed on the left half of the MyWidget object
bounds = object.globalBounds( waitForObject( names.MyWidget ) )
bounds.width = bounds.width / 2
test.ocrTextPresent( "Click me", {}, bounds )

# Verify the 'Click me' text is displayed in the specified area
test.ocrTextPresent( "Click me", {}, UiTypes.ScreenRectangle( 100, 100, 200, 300 ) )

# Verify the 'Click me' text is displayed on all top-level objects
test.ocrTextPresent( "Click me", {}, "all" )
# Verify the 'Click me' text is displayed on the MyWidget object
test.ocrTextPresent( "Click me", {}, waitForObject( names.MyWidget ) );

// Verify the 'Click me' text is displayed on multiple objects
test.ocrTextPresent( "Click me", {}, [ waitForObject( names.MyWidget ),
                                       waitForObject( names.MyOtherWidget ) ] );

// Verify the 'Click me' text is displayed on the left half of the MyWidget object
var bounds = object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
test.ocrTextPresent( "Click me", {}, bounds );

// Verify the 'Click me' text is displayed in the specified area
test.ocrTextPresent( "Click me", {}, new UiTypes.ScreenRectangle( 100, 100, 200, 300 ) );

// Verify the 'Click me' text is displayed on all top-level objects
test.ocrTextPresent( "Click me", {}, "all" );
# Verify the 'Click me' text is displayed on the MyWidget object
test::ocrTextPresent( "Click me", {}, waitForObject( names::MyWidget ) );

# Verify the 'Click me' text is displayed on multiple objects
test::ocrTextPresent( "Click me", {}, ( waitForObject( names::MyWidget ),
                                              waitForObject( names::MyOtherWidget ) ) );

# Verify the 'Click me' text is displayed on the left half of the MyWidget object
my $bounds = object::globalBounds( waitForObject( names::MyWidget ) );
$bounds->width = $bounds->width / 2;
test::ocrTextPresent( "Click me", {}, bounds );

# Verify the 'Click me' text is displayed in the specified area
test::ocrTextPresent( "Click me", {}, new UiTypes::ScreenRectangle( 100, 100, 200, 300 ) );

# Verify the 'Click me' text is displayed on all top-level objects
test::ocrTextPresent( "Click me", {}, "all" );
# Verify the 'Click me' text is displayed on the MyWidget object
Test.ocrTextPresent( "Click me", {}, waitForObject( names.MyWidget ) );

# Verify the 'Click me' text is displayed on multiple objects
Test.ocrTextPresent( "Click me", {}, [ waitForObject( names.MyWidget ),
                                       waitForObject( names.MyOtherWidget ) ] );

# Verify the 'Click me' text is displayed on the left half of the MyWidget object
bounds = Squish::Object.globalBounds( waitForObject( names.MyWidget ) );
bounds.width = bounds.width / 2
Test.ocrTextPresent( "Click me", {}, bounds );

# Verify the 'Click me' text is displayed in the specified area
Test.ocrTextPresent( "Click me", {}, UiTypes::ScreenRectangle.new( 100, 100, 200, 300 ) );

# Verify the 'Click me' text is displayed on all top-level objects
Test.ocrTextPresent( "Click me", {}, "all" );
# Verify the 'Click me' text is displayed on the MyWidget object
test ocrTextPresent "Click me" {} [ waitForObject $names::MyWidget ]

# Verify the 'Click me' text is displayed on multiple objects
test ocrTextPresent "Click me" {} { [ waitForObject $names::MyWidget ],
                                    [ waitForObject $names::MyOtherWidget ] }

# Verify the 'Click me' text is displayed on the left half of the MyWidget object
set bounds [object globalBounds [ waitForObject $names::MyWidget ] ]
property set $bounds width [ expr [ property get $bounds width ] / 2 ]
test ocrTextPresent "Click me" {} $bounds

# Verify the 'Click me' text is displayed in the specified area
test ocrTextPresent "Click me" {} [ construct ScreenRectangle 100 100 200 300 ]

# Verify the 'Click me' text is displayed on all top-level objects
test ocrTextPresent "Click me" {} "all"

确保函数始终成双成对调用

一些函数需要成对调用才能正确工作。例如,fixateResultContext & restoreResultContext应该一起使用,就像startsection & endSection一样。为了确保在脚本异常抛出时(或通过其他方式绕过其中一个语句的控制流,例如return;语句)也能保持这种情况,建议将函数对调用包装到辅助函数中,确保它们始终一起使用。

以下是确保fixateResultContextrestoreResultContext始终一起使用的一些示例。同样的方法也适用于startSection & endSection

#
# Python 2.5 or newer
#
def resultsReportedAtCallsite(ancestorLevel = 1):
    class Ctx:
        def __enter__(self):
            test.fixateResultContext(ancestorLevel + 1)
        def __exit__(self, exc_type, exc_value, traceback):
            test.restoreResultContext()
    return Ctx()

def libraryFunction():
    with resultsReportedAtCallsite():
        test.compare("Apples", "Oranges")
#
# Python 2.4 or earlier; these versions don't have the 'with' statement yet.
#
def withResultsReportedAtCallsite(callable, ancestorLevel = 1):
    test.fixateResultContext(ancestorLevel + 1)
    try:
        return callable()
    finally:
        test.restoreResultContext()

def libraryFunction():
    def go():
        test.compare("Apples", "Oranges")
    withResultsReportedAtCallsite(go)
function withResultsReportedAtCallsite(f)
{
    test.fixateResultContext(2);
    try {
        return f();
    } finally {
        test.restoreResultContext();
    }
}

function libraryFunction()
{
    withResultsReportedAtCallsite(function() {
        test.compare("Apples", "Oranges");
    });
}
sub withResultsReportedAtCallsite {
    my $code = shift;
    test::fixateResultContext(2);
    $code->();
    test::restoreResultContext();
}

sub libraryFunction
{
    withResultsReportedAtCallsite sub {
        test::compare("Apples", "Oranges");
    };
}
require 'squish'

include Squish

def withResultsReportedAtCallsite
  Test.fixateResultContext( 2 )
  begin
    yield
  ensure
    Test.restoreResultContext()
  end
end

def libraryFunction
  withResultsReportedAtCallsite do
    Test.compare("Apples", "Oranges")
  end
end
proc withResultsReportedAtCallsite {body} {
    test fixateResultContext 2
    uplevel 1 $body
    test restoreResultContext
}

proc libraryFunction {} {
    withResultsReportedAtCallsite {
        test compare "Apples" "Oranges"
    }
}

将测试结果分组

test.startSection(标题)

test.startSection(标题, 描述)

test.endSection()

这些函数可用于将测试结果分组为逻辑单元。一组比较或日志/警告语句可以包含在startSection/endSection中,以便将其作为单独的结果部分记录。当使用squishide显示结果部分时,它将结果部分以嵌套的测试结果集合的形式展示。在命令行上执行测试时,除非使用XML3报告生成器,否则每当一个部分开始或结束时,都会将日志消息添加到测试报告中。

注意:在调用test.startSection之后省略调用test.endSection可能会导致非常误导或不规范测试报告。关于可能的解决方案,请参阅确保函数总是成对调用

比较文件

布尔型 test.compareTextFiles(预期文件路径, 实际文件路径)

布尔型 test.compareTextFiles(预期文件路径, 实际文件路径, 选项)

此函数将根据预期文件路径指定的预期文件与根据实际文件路径指定的实际文件进行比较。如果它们相等,则将类型为PASS的测试结果添加到测试日志,并返回一个true值。否则,将类型为FAIL的测试结果添加到测试日志,并返回一个false值。如果文件不同,将创建一个diff,其中显示了哪些行已更改,并在测试结果消息的详细信息中可以找到。

选项参数可以指定为映射或字典。到目前为止,可以设置以下选项

  • strictLineEndings:如果将其设置为true,该函数将检测两个文件是否使用不同的换行符(例如,在Windows上的CR+LF或Unix上的LF)。默认设置为false
//example 1: no options
test.compareTextFiles("expected.txt", "actual.txt");

//example 2: with options
test.compareTextFiles("expected.txt", "actual.txt", {'strictLineEndings': true});
#example 1: no options
test::compareTextFiles("expected.txt", "actual.txt");

#example 2: with options
test::compareTextFiles("expected.txt", "actual.txt", {"strictLineEndings" => 1});
#example 1: no options
test.compareTextFiles("expected.txt", "actual.txt")

#example 2: with options
test.compareTextFiles("expected.txt", "actual.txt", {'strictLineEndings': True})
#example 1: no options
Test.compareTextFiles("expected.txt", "actual.txt")

#example 2: with options
Test.compareTextFiles("expected.txt", "actual.txt", {'strictLineEndings' => True})
#example 1: no options
test compareTextFiles "expected.txt" "actual.txt"

#example 2: with options
test compareTextFiles "expected.txt" "actual.txt" [dict create strictLineEndings 1]

布尔型 test.compareXMLFiles(预期文件路径, 实际文件路径)

布尔型 test.compareXMLFiles(预期文件路径, 实际文件路径, 选项)

此函数将根据预期文件路径指定的预期XML文件与根据实际文件路径指定的实际XML文件进行比较。如果它们相等,则将类型为PASS的测试结果添加到测试日志,并返回一个true值。否则,将类型为FAIL的测试结果添加到测试日志,并返回一个false值。如果文件不同,结果消息详细信息将显示比较失败的行号和原因。

选项参数可以指定为映射或字典。到目前为止,可以设置以下选项

  • ignoreNodeOrder:如果将其设置为true,该函数将忽略同一级别上的元素顺序,即具有相同父元素的元素。默认设置为false
  • ignoreAttributeOrder:如果将其设置为true,该函数将忽略元素内的属性顺序。默认设置为true
  • ignoreComments:如果将其设置为true,该函数将忽略所有注释。如果设置为false,则比较所有注释。默认设置为true
  • 文本中的空白处理:此选项可用于控制文本元素内部空白的处理方式。可以设置为 保留规范化修剪。如果设置为 保留,则保留所有空白字符;如果设置为 规范化,则将所有空白字符规范化为空格;如果设置为 修剪,则移除文本元素开头和结尾的空白字符。默认设置为 规范化
  • 属性值中的空白处理:此选项可用于控制属性值内部空白的处理方式。可以设置为 保留规范化修剪。如果设置为 保留,则保留所有空白字符;如果设置为 规范化,则将所有空白字符规范化为空格;如果设置为 修剪,则移除属性值开头和结尾的空白字符。默认设置为 保留
  • 忽略CDATA:如果设置为 true,则仅比较 CDATA 标签内的文本。标签本身将被忽略。如果设置为 false,则也会比较标签。默认设置为 true
  • 比较特殊标签:如果设置为 true,则声明、处理指令和 DOCTYPE 标签的值也将进行比较。默认设置为 false
  • 过滤元素:此选项接受代表标签名的字符串列表/数组。如果标签名包含在过滤元素列表中,则在比较两个文档时将忽略该标签。
  • 过滤属性:此选项接受代表属性名的字符串列表/数组。如果属性名包含在过滤属性列表中,则在比较两个文档时将忽略该属性。

您还可以使用 Boolean test.compareTextFiles(expectedFilePath, actualFilePath) 函数比较 XML 文件,但此函数的优点是不考虑文件格式。相反,它直接查看文件结构,并比较节点和属性。

//example 1: no options
test.compareXMLFiles("expected.xml", "actual.xml");

//example 2: you only need to specify the options you need
test.compareXMLFiles("expected.xml", "actual.xml", {'ignoreNodeOrder': false});

//example 3: with filtered attributes and elements
filteredAttributes = ["version", "xmlns"];
filteredElements = ["uri"];
options = {'ignoreNodeOrder': false,
           'ignoreAttributeOrder': true,
           'filteredAttributes': filteredAttributes,
           'filteredElements': filteredElements,
           'whitespaceInTextHandling':'trim'};
test.compareXMLFiles("expected.xml", "actual.xml", options);
#example 1: no options
test::compareXMLFiles("expected.xml", "actual.xml");

#example 2: you only need to specify the options you need
test::compareXMLFiles("expected.xml", "actual.xml", {"ignoreNodeOrder" => 0});

#example 3: with filtered attributes and elements
my $filteredAttributes = ["version", "xmlns"];
my $filteredElements = ["uri"];
my $options = {"ignoreNodeOrder" => 0,
               "ignoreAttributeOrder" => 1,
               "filteredAttributes" => $filteredAttributes,
               "filteredElements" => $filteredElements,
               "whitespaceInTextHandling" => "trim"};
test::compareXMLFiles("expected.xml", "actual.xml", $options);
#example 1: no options
test.compareXMLFiles("expected.xml", "actual.xml")

#example 2: you only need to specify the options you need
test.compareXMLFiles("expected.xml", "actual.xml", {'ignoreNodeOrder': False})

#example 3: with filtered attributes and elements
filteredAttributes = ["version", "xmlns"]
filteredElements = ["uri"]
options = {'ignoreNodeOrder': False,
           'ignoreAttributeOrder': True,
           'filteredAttributes': filteredAttributes,
           'filteredElements': filteredElements,
           'whitespaceInTextHandling':'trim'}
test.compareXMLFiles("expected.xml", "actual.xml", options)
#example 1: no options
Test.compareXMLFiles("expected.xml", "actual.xml")

#example 2: you only need to specify the options you need
Test.compareXMLFiles("expected.xml", "actual.xml", {'ignoreNodeOrder' => false})

#example 3: with filtered attributes and elements
filteredAttributes = ["version", "xmlns"]
filteredElements = ["uri"]
options = {'ignoreNodeOrder' => false,
           'ignoreAttributeOrder' => true,
           'filteredAttributes' => filteredAttributes,
           'filteredElements' => filteredElements,
           'whitespaceInTextHandling' => 'trim'}
Test.compareXMLFiles("expected.xml", "actual.xml", options)
#example 1: no options
test compareXMLFiles "expected.xml" "actual.xml"

#example 2: you only need to specify the options you need
test compareXMLFiles "expected.xml" "actual.xml" [dict create ignoreNodeOrder 0]

#example 3: with filtered attributes and elements
set filteredAttributes [list version xmlns]
set filteredElements [list uri]
set options [dict create ignoreNodeOrder 0 \
                         ignoreAttributeOrder 1 \
                         filteredAttributes $filteredAttributes \
                         filteredElements $filteredElements \
                         whitespaceInTextHandling trim]
test compareXMLFiles "expected.xml" "actual.xml" $options

Boolean test.compareJSONFiles(expectedFilePath, actualFilePath)

此函数将指定的 expectedFilePath 的预期 JSON 文件与指定的 actualFilePath 的实际 JSON 文件进行比较。如果它们相等,则将添加测试结果类型为 PASS 的记录到测试日志,并返回该函数 true 值。否则,将添加类型为 FAIL 的测试结果记录到测试日志,并返回 false 值。如果文件不同,结果消息将显示比较失败的原因以及文本差异。

注意:由于使用的 JSON 库的功能和限制,可能不符合标准或不需要的 JSON 可能通过测试。在调用 test.compareJSONFiles 之前,验证 JSON 文件并确保它们名称唯一。

基于脚本的视觉验证点创建

createVisualVP(objectNameOrReference, vpFile)

此函数创建一个名为 vpFile视觉验证点,可在之后的测试运行中使用 Boolean test.vp(name)Boolean test.xvp(name)。而此操作通常通过 squishide 的点与点击来完成。

通过内部调用 saveObjectSnapshot(objectNameOrReference, snapshotImageFile.xml) 确定期望的视觉状态,其中 objectNameOrReference 表示对象。

新创建的验证点将启用所有内容、几何和截图检查。稍后可以使用视觉验证点编辑器修改这些检查。

如果vpFile已经存在,函数将抛出一个可捕获的脚本异常。

测试数据函数

Squish可以处理表格数据(行和列——或者在数据库术语中,记录和字段)。就Squish的数据处理函数而言,我们将“行”和“记录”视为同义词,同样,“列”和“字段”也是如此。

Squish可以从.tsv(制表符分隔值格式)、.csv(逗号分隔值格式)、.xls.xlsx(Microsoft Excel工作表格式)文件中读取测试数据。在.csv.tsv文件的情况下,Squish假设它们使用Unicode UTF-8编码——与所有测试脚本相同的编码。

注意:squishide中,第一行数据用于标题,行索引从1开始计数。然而,本节中列出的函数使用基于0的索引,因此第一个记录位于行0,第二个记录位于行1,依此类推。实际上,标题在行索引-1是可以访问的。

测试数据函数用于数据驱动和关键字驱动测试。有关数据驱动测试的示例,请参阅教程;有关关键字驱动测试的示例,请参阅如何进行关键字驱动测试

String testData.create(where, filename)

此函数返回可以写入的文件名。如果where参数为"shared",则文件名将包含位于测试套件的共享测试数据目录(test_suite/shared/testdata/filename)的路径,如果where"local",则文件名将包含位于测试套件、测试用例的测试数据目录(test_suite/tst_case/testdata/filename)的路径。

此函数旨在在以“学习”模式运行脚本时使用,并希望动态创建测试数据。

Dataset testData.dataset(filename)

(以及testData.fieldNamestestData.fieldtestData.datasetExcel函数)用于数据驱动和关键字驱动测试。

testData.dataset函数返回一个数据集对象,该对象引用一个记录数组或元组。数据从由filename指定的文件中检索——如果数据格式是Squish可以识别的格式。

通常,不包含路径的filename会被给出(例如,mydata.csv)。在这种情况下,Squish首先尝试在测试用例的数据中查找文件(例如,如果测试用例有一个testdata文件夹,则在测试用例的testdata文件夹中)。如果失败,Squish接下来尝试在测试套件的共享数据文件夹中查找(例如,在测试套件的shared/testdata文件夹中)。如果找不到文件(或者找到但无法读取或理解),Squish会抛出一个可捕获的异常。如果指定了具有路径的filename(例如,C:\mydata\mydata.csv),则Squish会尝试读取该特定文件,如果文件不存在或不在Squish可以理解的格式中,则会抛出一个可捕获的异常。

可以使用下面的函数检索字段名称和字段值。

Dataset testData.datasetExcel(filename, sheetname)

该函数(以及 testData.fieldNamestestData.fieldtestData.dataset 函数)用于数据驱动和关键字驱动测试。

testData.datasetExcel 函数返回一个数据集对象,该对象指向一个记录数组或元组。数据从由 filenamesheetname 指定的文件中检索。当数据位于 Excel 格式中(即具有 .xls 或 .xlsx 扩展名)时,这是可能的。此函数是 testData.dataset 函数的一个规范。

有关函数行为的详细说明,请参阅上面的 testData.dataset 信息。唯一具体的是函数的第二个参数,即 sheetname。这是 Excel 文档中特定工作表的名字。此参数是可选的。默认情况下,将使用第一个工作表。

布尔值 testData.exists(filename)

这是一个旧的 API,通常最好使用 布尔值 RemoteSystem.exists(path) 替代。

如果名为 filename 的文件存在于 AUT 的当前工作目录中,则此函数返回一个真值;否则返回一个假值。

字符串 testData.field(record, fieldName)

字符串 testData.field(record, fieldIndex)

该函数返回由给定的字符串 fieldName 或给定的 fieldIndex 整数指定的字段的值,该值是从指定的 record(即从由 testData.dataset 函数返回的 数据集 中的特定行)中获得的。

有关用法示例,请参阅 如何进行数据驱动测试

字符串序列 testData.fieldNames(record)

此函数返回特定 record(即从 testData.dataset 函数返回的 数据集 中的特定行)的字段名称数组或元组。

testData.get(filename)

此函数将名为 filename 的文件从 AUT 的当前工作目录复制到 squishrunner 的当前工作目录。通常,对于将远程文件复制到本地机器,最好使用 布尔值 RemoteSystem.download(remotePath, localPath) 替代。

testData.remove(filename)

此函数从 AUT 的当前工作目录中删除名为 filename 的文件。

testData.put(filename)

如果没有指定路径,则该函数将测试数据文件 filename 从测试用例目录复制到 AUT 的当前工作目录。如果指定了路径,则该函数将指定的文件复制到 AUT 的当前工作目录。当 AUT 终止时,复制的测试数据文件将自动删除

该函数返回复制的文件的完整路径,或者在发生错误时抛出可以由测试脚本捕获的异常。

请注意,如果涉及多个 AUT(例如,如果一个 AUT 启动另一个程序),则在由在调用 testData.put 函数时的程序终止时发生删除。

对象映射函数

有关使用 squishide 操作对象映射的信息,请参阅对象映射视图。有关使用中的对象映射更多信息,请参阅对象映射

注意:这些函数由 Squish 用于 基于文本的对象映射。当使用 基于脚本的对象映射 时,对象名称是普通的脚本变量或本地字典,因此没有等效的 API 用于添加/加载。但是,当使用基于脚本的对象映射时,代码 realNamesymbolicName 函数对于调试/演示仍然很有用。

objectMap.add(object)

此函数将给定的 object 添加到对象映射中。(可以使用 Object waitForObject(objectOrName) 函数或 Object findObject(objectName) 函数获取一个合适的对象。)

objectMap.load(filename)

此函数从给定的 filename 加载对象映射,并使用它来 替换 当前对象映射。如果文件不存在,将抛出异常并保持当前对象映射不变。

String objectMap.realName(object)

String objectMap.realName(symbolicName)

此函数返回给定 object 或具有给定 symbolicName 的对象的实际(多属性)名称。

String objectMap.symbolicName(object)

String objectMap.symbolicName(objectOrRealName)

此函数尝试返回对象映射中指定对象或真实名称的符号名称。

如果 objectOrRealName 是真实名称,并且不匹配任何现有对象,它将被简单地返回;不会抛出错误。

如果 objectOrRealName 是无效的真实名称,它将被简单地返回;不会抛出错误。

如果 objectOrRealName 是对对象的引用,并且对象映射不包含匹配此对象的对象名称,则将返回该对象的实际名称。

SequenceOfStrings objectMap.symbolicNames()

此函数返回一个包含所有映射符号名称的数组(Python 中的元组)。返回的名称是任意顺序的。

应用程序上下文

由 Squish 启动的每个 AUT 都有一个对应的 ApplicationContext 对象。这些对象提供以下属性和函数。(有关使用示例,请参阅如何使用 ApplicationContext 对象。)

以下是到与应用程序上下文相关函数、方法和属性的相关快速链接

ApplicationContext applicationContext(name)

此函数返回匹配给定 name 的 ApplicationContext 对象或不存在此类上下文的有效 ApplicationContext 对象。

注意:当使用 Tcl 脚本语言时,此函数称为 getApplicationContext

String applicationContext.commandLine

此只读属性包含启动应用程序时使用的命令行。

String applicationContext.cwd

此只读属性包含应用程序的当前工作目录。

String applicationContext.environmentVariable(name)

此函数返回名为 name 的 AUT 进程环境变量的值或不存在此类环境变量时的空字符串。

String applicationContext.host

每个应用程序上下文都与一个 squishserver 进程相连。此只读属性包含 squishserver 进程运行的计算机/主机名或 TCP/IP 地址,以及连接到该应用程序上下文的计算机。

如果此应用程序上下文是由 ApplicationContext startApplication(autName) 创建的,则此属性也代表 AUT 运行的计算机/主机名或 TCP/IP 地址。

bool applicationContext.isFrozen(timeout)

如果应用程序在超时(以秒计)到期之前响应,则此函数返回 false 值;否则它返回 true 值。

bool applicationContext.isRunning

此只读属性为 true 如果 squishserver 和 AUT 中的 Squish Hook 之间的通信仍然活动,否则为 false

当 Squish Hook 关闭时,squishserver 和 Squish Hook 之间的通信正在关闭。反过来,当 AUT 关闭时,Squish Hook 正在关闭。(例如,在 Qt 情况下,当主要 Qt 事件循环退出时。)

然而,AUT 的关闭可能不是立即的:AUT 可以在最终退出前的短时间内执行长时间操作,因此即使 AUT 进程仍然存在,一段时间内 isRunning 也可能为 false

applicationContext.detach()

此函数从之前启动(或附加)的应用程序断开连接。

如果相应应用程序已通过 ApplicationContext startApplication(autName) 启动,Squish 将尝试关闭它,并最终(如果仍然运行)强制关闭它。

如果通过 ApplicationContext attachToApplication(autName) 将相应应用程序附加到,则 Squish 将使其运行但断开连接,从而留下应用程序在运行。然后可以使用 ApplicationContext attachToApplication(autName) 再次将其附加。

从应用程序脱钩后,不应再访问其任何对象。(这通常是通过使用在脱钩之前检索的引用对象来完成的。)

如果 applicationContext.detach() 的应用程序上下文是当前应用程序上下文,则当前应用程序上下文将更改为另一个(随机)应用程序上下文。所以,在继续之前,必须确保要操作的应用程序上下文是当前的一个。(见 SequenceOfApplicationContexts applicationContextList()ApplicationContext currentApplicationContext()setApplicationContext(contextHandle)。)

String applicationContext.name

这个只读属性表示应用程序的名称。在绝大多数平台和GUI工具包中,这是应用程序的进程名称。

int applicationContext.pid

这个只读属性表示应用程序的进程标识符。

int applicationContext.port

每个应用程序上下文都连接到一个 squishserver 进程。这个只读属性表示连接到应用程序上下文的 squishserver 进程的 TCP 端口号。

String applicationContext.readStderr()

此函数读取并返回自上次调用 readStderr 或自应用程序启动以来应用程序写入 stderr 流的所有内容。

注意:在没有分配控制台的情况下,Windows 自动化测试单元(AUT)不支持此功能。

String applicationContext.readStdout()

此函数读取并返回自上次调用 readStdout 或自应用程序启动以来应用程序写入 stdout 流的所有内容。

注意:在没有分配控制台的情况下,Windows 自动化测试单元(AUT)不支持此功能。

time applicationContext.startTime

这个只读属性表示应用程序启动时的时间。(属性的数据类型取决于所使用的脚本语言。)

int applicationContext.totalTime

这个只读属性表示 AUT 进程在用户和内核模式下被调度的总时间,用毫秒表示。

int applicationContext.usedMemory

这个只读属性表示 AUT 进程使用的内存量。对于 Windows 操作系统,值对应于工作集大小(以字节为单位)。对于 Linux 操作系统,值对应于常驻集合大小(RSS),以字节为单位。对于 macOS,它也是 RSS,但以千字节为单位。

SequenceOfApplicationContexts applicationContextList()

此函数返回一个数组(Python 中的元组)所有现有应用程序上下文的句柄。

ApplicationContext attachToApplication(autName)

ApplicationContext attachToApplication(autName, squishserver_host)

ApplicationContext attachToApplication(autName, squishserver_host, squishserver_port)

ApplicationContext attachToApplication(autName, squishserver_host, squishserver_port, timeoutSecs)

此函数使 Squish 连接到名为 autName 的应用程序,并返回其应用程序上下文的句柄。autName 必须是已与 squishserver 注册并可作为附加对象的 AUT 的应用程序名称。参见 配置 squishserver。由于应用程序应该已经运行,因此不能提供任何命令行选项。

squishserver_hostsquishserver_port 指的是运行所需 squishserver 的计算机及其 TCP 端口。(这 不是 可附加 AUT 的主机和端口号。可附加 AUT 的主机和端口号在将可附加 AUT 注册到 squishserver 时指定(参见 注册可附加 AUT)。

在建立与可附加 AUT 的套接字连接后,使用参数 timeoutSecs。如果可附加 AUT 需要超过指定时间来响应附加尝试,则会抛出错误。如果没有指定 timeoutSecs,则使用 squishserver 的(最大启动时间)默认值——这是 20 秒,除非已更改;参见 Squish 服务器设置对话框

如果您想指定超时,但不想更改主机或端口,可以通过将主机传递为空字符串(这将使 Squish 使用配置的主机—默认为 localhost),并通过将端口号传递为 -1 来做到这一点。

如果在附加过程中失败(例如,因为 AUT 没有运行),则此函数会抛出一个异常,该异常可以在测试脚本中捕获。如果没有捕获到异常,则在测试脚本执行过程中记录一个错误。

有关更多信息,请参见 附加到正在运行的应用程序

ApplicationContext currentApplicationContext()

此函数返回当前应用程序上下文的句柄。

ApplicationContext defaultApplicationContext()

此函数返回默认应用程序上下文的句柄。最好使用 ApplicationContext currentApplicationContext() 函数。

setApplicationContext(contextHandle)

此函数可用于更改当前应用程序上下文。《contextHandle》对象是任何返回句柄的函数的句柄——SequenceOfApplicationContexts applicationContextList()ApplicationContext attachToApplication(autName)ApplicationContext defaultApplicationContext()ApplicationContext currentApplicationContext()ApplicationContext startApplication(autName)。如果省略参数,则激活默认上下文。

如果 contextHandle 对象无效——例如,如果它引用了一个已崩溃的应用程序——则会抛出一个可捕获的异常(Python 中的 TypeError)。

注意:更改应用程序上下文确定测试脚本在某个时刻与哪个 AUT 交互,但这不会更改当前显示的活动的 GUI 窗口。为此,我们使用 setForeground 函数。

text getClipboardText()

设置剪贴板文本(setClipboardText(text))

这些函数可用于在AUT运行所在的机器上获取和设置剪贴板文本内容。

当处理包含换行符的剪贴板内容时,请注意它们的表示(\n\r\n)是特定于操作系统的。

注意:对于非Qt X11应用程序,该功能确实需要安装xsel工具。对于使用替代窗口系统的非Qt应用程序,该功能还不可用。

ApplicationContext startApplication(autName)

ApplicationContext startApplication(autName, host)

ApplicationContext startApplication(autName, host, port)

ApplicationContext startApplication(autName, host, port, timeoutSecs)

此函数启动指定的应用程序并返回其应用程序上下文的句柄。autName 参数应该是已通过 squishserver 注册路径的应用程序名称。请参见 配置 squishserver

也可以为 autName 使用可执行文件或 .jar 文件的绝对路径。此外,还可以在此处提供命令行选项。

可选地,作为第二个和第三个参数,可以指定 hostport。如果使用这些参数,则不是连接到默认主机和端口(如 squishide 的设置或 squishrunner 的命令行中指定的),而是连接到指定主机上监听指定端口的 squishserver。这使得能够从单个测试脚本中控制多台计算机上的多个应用程序。

第四个参数 timeoutSecs(秒的整数)也可以指定。这告诉 Squish 在抛出错误之前应该准备等待应用程序多长时间。如果没有指定,则使用 squishserver 的默认值——这是 20 秒,可以通过 服务器设置 > 应用程序行为 > 最大启动时间 来更改,或者通过执行 squishserver --config AUTTimeout numSeconds

如果您想指定超时,但不想指定主机或端口,可以通过将主机作为空字符串传递(这将使 Squish 使用配置的主机——默认为 localhost),并通过将端口作为 -1 传递来实现。

有关如何使用应用程序上下文对象的信息,请参阅 如何使用 ApplicationContext 对象。(另请参阅 ApplicationContext waitForApplicationLaunch() 函数。)

String applicationContext.osName

此只读属性包含 AUT 运行的操作系统名称。可能包括以下名称:

  • "Android" — Android
  • "Darwin" — macOS 和 iOS
  • "Linux" — Linux
  • "QNX" — QNX
  • "SunOS" — Solaris
  • "Windows" — Windows

ApplicationContext connectTo(target)

ApplicationContext connectTo(target, host)

ApplicationContext connectTo(target, host, port)

该函数启动与远程桌面(例如,VNC)服务器的连接,并返回其应用程序上下文的句柄。其中target指定了连接参数。

连接目标可以是URL或参数映射。要连接到VNC服务器,URL和参数映射的参数都需要符合RFC 7869规范,该规范指定了以下字段

  • scheme - 连接方案 "vnc";
  • host - VNC服务器的主机名;
  • port - VNC服务器的TCP端口。如果没有指定端口号,则使用默认值5900;
  • VncUsername - 用于VNC认证的用户名。仅在服务器需要时使用;
  • VncPassword - 用于VNC认证的密码。仅在服务器需要时使用。

Squish还提供了一种“本地”连接协议,允许squishserver直接连接到它正在运行的会话,而不需要任何额外的远程桌面服务器/认证。为了使用它,必须将"os"方案指定为目标参数的一部分。该"os"方案接受以下字段

  • scheme - 连接方案 "os";
  • display - 要连接的X11显示字符串。如果未指定,将使用默认显示字符串。此参数仅在类Unix系统中相关,在Windows和OSX系统中被忽略。

远程桌面连接始终通过squishserver实例路由。如果指定了hostport参数,Squish将使用位于指定地址的侦听服务器。默认情况下,将使用squishide设置中或squishrunner命令行上指定的服务器参数。

例如

connectTo("vnc://example.com")
connectTo("vnc://example.com:5901")
connectTo("vnc://example.com?VncPassword=secret")
connectTo("vnc://example.com:5901?VncUsername=user&VncPassword=secret")
connectTo("os://")

connectTo({"scheme": "vnc",
           "host": "example.com"})
connectTo({"scheme": "vnc",
           "host": "example.com",
           "port": 5901})
connectTo({"scheme": "vnc",
           "host": "example.com",
           "VncPassword": "secret"})
connectTo({"scheme": "vnc",
           "host": "example.com",
           "port": 5901,
           "VncUsername": "user",
           "VncPassword": "secret"})
connectTo({"scheme": "os"})
connectTo("vnc://example.com");
connectTo("vnc://example.com:5901");
connectTo("vnc://example.com?VncPassword=secret");
connectTo("vnc://example.com:5901?VncUsername=user&VncPassword=secret");
connectTo("os://");

connectTo({scheme: "vnc",
           host: "example.com"});
connectTo({scheme: "vnc",
           host: "example.com",
           port: 5901});
connectTo({scheme: "vnc",
           host: "example.com",
           VncPassword: "secret"});
connectTo({scheme: "vnc",
           host: "example.com",
           port: 5901,
           VncUsername: "user",
           VncPassword: "secret"});
connectTo({scheme: "os"});
connectTo("vnc://example.com");
connectTo("vnc://example.com:5901");
connectTo("vnc://example.com?VncPassword=secret");
connectTo("vnc://example.com:5901?VncUsername=user&VncPassword=secret");
connectTo("os://");

connectTo({"scheme" => "vnc",
           "host" => "example.com"});
connectTo({"scheme" => "vnc",
           "host" => "example.com",
           "port" => 5901});
connectTo({"scheme" => "vnc",
           "host" => "example.com",
           "VncPassword" => "secret"});
connectTo({"scheme" => "vnc",
           "host" => "example.com",
           "port" => 5901,
           "VncUsername" => "user",
           "VncPassword" => "secret"});
connectTo({"scheme" => "os"});
connectTo("vnc://example.com");
connectTo("vnc://example.com:5901");
connectTo("vnc://example.com?VncPassword=secret");
connectTo("vnc://example.com:5901?VncUsername=user&VncPassword=secret");
connectTo("os://");

connectTo({"scheme" => "vnc",
           "host" => "example.com"});
connectTo({"scheme" => "vnc",
           "host" => "example.com",
           "port" => 5901});
connectTo({"scheme" => "vnc",
           "host" => "example.com",
           "VncPassword" => "secret"});
connectTo({"scheme" => "vnc",
           "host" => "example.com",
           "port" => 5901,
           "VncUsername" => "user",
           "VncPassword" => "secret"});
connectTo({"scheme" => "os"});
connectTo "vnc://example.com"
connectTo "vnc://example.com:5901"
connectTo "vnc://example.com?VncPassword=secret"
connectTo "vnc://example.com:5901?VncUsername=user&VncPassword=secret"
connectTo "os://"

connectTo [ dict create "scheme" "vnc"
                        "host" "example.com" ]
connectTo [ dict create "scheme" "vnc"
                        "host" "example.com"
                        "port" 5901 ]
connectTo [ dict create "scheme" "vnc"
                        "host" "example.com"
                        "VncPassword" "secret" ]
connectTo [ dict create "scheme" "vnc"
                        "host" "example.com"
                        "port" 5901
                        "VncUsername" "user"
                        "VncPassword" "secret" ]
connectTo [ dict create "scheme" "os" ]

图像对象

全局Image对象提供了读取、保存和操作图像文件的功能。可以通过使用Image Image.load(fileName)从文件加载图像或使用任何Image object.grabScreenshot(object, [parameterMap])grabDesktopScreenshot()测试API获取截图来获取Image类的实例。它可以作为图像搜索和OCR API的搜索区域参数,例如ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion])ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion])String getOcrText([parameterMap], [searchRegion])ScreenRectangle findOcrText(text, [parameterMap], [searchRegion])ScreenRectangle waitForOcrText(text, [parameterMap], [searchRegion])SequenceOfObjects findAllOcrText(text, [parameterMap], [searchRegion])Boolean test.imagePresent(imageFile, [parameterMap], [searchRegion])Boolean test.ocrTextPresent(text, [parameterMap], [searchRegion])

Image Image(QImage)

Image Image(QPixmap)

Image类型的构造函数。它使用AUT特定的QImage和QPixmap对象创建图像对象。

Image Image(width, height, [color])

《Image》类型的构造函数。它创建一个具有指定尺寸的图像。可以使用color参数指定图像像素的初始颜色。颜色可以指定为32位ARGB值,也可以指定为每个颜色通道的值集。

var img = new Image(100, 100, [255, 0, 0]);
img.save("C:\\red.png");
my $img = Image->new(100, 100, [255, 0, 0]);
$img->save("C:\\red.png");
img = Image(100, 100,[255, 0, 0])
img.save("C:\\red.png")
img = Image.new(100, 100, [255, 0, 0]);
img.save("C:\\red.png");
set img [image new 100 100 {255 0 0}]
invoke $img save "C:\\red.png"

Image Image.load(fileName)

这是一个静态的《Image》对象方法,默认情况下从测试用例目录下的指定文件中读取图像,并返回实例的引用。如果找不到文件或无法读取,则抛出异常。

参见findFile(where, filename)

img = Image.load("indicator.png")
test.compare(img.width, 32)
test.compare(img.height, 32)
var img = Image.load("indicator.png");
test.compare(img.width, 32);
test.compare(img.height, 32);
my $img = Image->load("indicator.png");
test->compare($img->width, 32);
test->compare($img->height, 32);
img = Image::load("indicator.png");
Test::compare(img.width, 32)
Test::compare(img.height, 32)
set img [image load "indicator.png"]
test compare [property get $img width] 32
test compare [property get $img height] 32

在图像实例的原型中可以找到以下属性和函数。

Number width

此属性表示图像实例的宽度(以像素为单位)。此值是只读的。当尝试设置新值时将抛出异常。

Number height

此属性表示图像实例的高度(以像素为单位)。此值是只读的。当尝试设置新值时将抛出异常。

Image.copy///

Image.copy(x, y, width, height)

此函数返回图像一部分的副本。如果指定的几何形状不位于图像边界内([(0, 0)...(width-1, height-1)]),则抛出异常。如果未指定坐标参数,则返回整个图像的副本。

Image.save(fileName)

此函数将图像实例保存到磁盘上的指定文件名。如果路径无效或不可写,则抛出异常。如果指定的路径是相对的,则文件相对于解释器的当前工作目录保存,默认情况下是当前正在执行的测试用例的位置。

保存文件的格式将基于文件扩展名。支持格式因平台/版本而异,但通常包括BMP、JPG、PNG、PPM、TIF、XBM和XPM。

var img = grabDesktopScreenshot();
img.save("C:\\screenshot1.png");
my $img = grabDesktopScreenshot();
$img->save("C:\\screenshot1.png");
img = grabDesktopScreenshot()
img.save("C:\\screenshot1.png")
img = grabDesktopScreenshot()
img.save("C:\\screenshot1.png")
set img [grabDesktopScreenshot]
invoke $img save "C:\\screenshot1.png"

Number Image.getPixelRGBA(x, y)

此函数返回一个数组,包含位于指定位置的像素的红色、绿色、蓝色和alpha颜色通道(按照该顺序)的颜色。如果像素不在图像边界内(从(0, 0)到(width-1, height-1)),则抛出异常。

pixel = img.getPixelRGBA(0, 0)
red = pixel[0];
green = pixel[1];
blue = pixel[2];
alpha = pixel[3];
var pixel = img.getPixelRGBA(0, 0);
var red = pixel[0];
var green = pixel[1];
var blue = pixel[2];
var alpha = pixel[3];
my @pixel = $img->getPixelRGBA(0, 0);
my red = $pixel[0];
my green = $pixel[1];
my blue = $pixel[2];
my alpha = $pixel[3];
pixel = img.getPixelRGBA(0, 0);
red = pixel[0];
green = pixel[1];
blue = pixel[2];
alpha = pixel[3];
set pix [invoke $img getPixelRGBA 0 0]
set red [lindex $pix 0]
set green [lindex $pix 1]
set blue [lindex $pix 2]
set alpha [lindex $pix 3]

完全不透明的像素的alpha值为255。完全透明的像素的alpha值为0。

Number Image.getPixel(x, y)

此函数返回指定位置的像素的32位ARGB颜色值。如果像素不在图像边界内(从(0, 0)到(width-1, height-1)),则抛出异常。此值可以直接与预期值(例如,纯绿色的0xff00ff00)进行比较。

pixel = img.getPixel(0, 0)
test.compare(pixel, 0xff102030)
var pixel = img.getPixel(0, 0);
test.compare(pixel, 0xff102030 );
my $pixel = $img->getPixel(0, 0);
test::compare($pixel, 0xff102030);
pixel = img.getPixel(0, 0);
Test::compare(pixel, 0xff102030);
set pixel [invoke $img getPixel 0 0]
test compare $pixel [expr 0xff102030]

Number Image.setPixel(x, y, rgbColor)

Number Image.setPixel(x, y, Array)

Number Image.setPixel(x, y, red, green, blue)

Number Image.setPixel(x, y, red, green, blue, alpha)

此函数更改指定位置的像素颜色。颜色可以指定为32位ARGB值,可以指定为每个颜色通道的值集合:红色、绿色、蓝色以及可选的alpha值,或这样的值数组;例如

img.setPixel(0, 0, 0xffff0000)
img.setPixel(0, 0, 255, 0, 0)
img.setPixel(0, 0, 255, 0, 0, 255)
img.setPixel(0, 0, [255, 0, 0])
img.setPixel(0, 0, [255, 0, 0, 255])
img.setPixel(0, 0, 0xffff0000);
img.setPixel(0, 0, 255, 0, 0);
img.setPixel(0, 0, 255, 0, 0, 255);
img.setPixel(0, 0, [255, 0, 0]);
img.setPixel(0, 0, [255, 0, 0, 255]);
$img->setPixel( 0, 0, 0xffff0000);
$img->setPixel( 0, 0, 255, 0, 0);
$img->setPixel( 0, 0, 255, 0, 0, 255 );
$img->setPixel( 0, 0, [255, 0, 0]);
$img->setPixel( 0, 0, [255, 0, 0, 255]);
img.setPixel(0, 0, 0xffff0000)
img.setPixel(0, 0, 255, 0, 0)
img.setPixel(0, 0, 255, 0, 0, 255)
img.setPixel(0, 0, [255, 0, 0])
img.setPixel(0, 0, [255, 0, 0, 255])
invoke $img setPixel 0 0 [expr 0xffff0000]
invoke $img setPixel 0 0 255 0 0
invoke $img setPixel 0 0 255 0 0 255
invoke $img setPixel 0 0 {255 0 0}
invoke $img setPixel 0 0 {255 0 0 255}

布尔图 Image.equals(otherImage)

此函数返回true,如果此图像等于其他图像。如果参数不引用图像实例,则抛出异常。

Screen 对象

有关屏幕的信息。要使用此 Screen 对象,必须在脚本文件中包含 Squish screen 库,并且 Squish 必须连接到/附加到 AUT。

source(findFile("scripts", "javascript/screen.js"));

function main()
{
    startApplication("myaut");

    // ...

    var scr = Screen.byIndex(0);
    var geom = scr.geometry;
    test.log("Screen is " + geom.width + " by " + geom.height);
}
use strict;
use utf8;
use warnings;

use Squish::Screen;

sub main {
    startApplication("myaut");

    # ...

    my $scr = Squish::Screen->byIndex(0);
    my $geom = $scr->geometry;
    test::log("Screen is " . $geom->width . " by " . $geom->height);
}
# -*- coding: utf-8 -*-
from screen import Screen

def main():
    startApplication("myaut")

    # ...

    scr = Screen.byIndex(0)
    geom = scr.geometry
    test.log("Screen is " + str(geom.width) + " by " + str(geom.height))
# encoding: UTF-8
require 'squish'
require 'squish/screen'

def main
    startApplication("myaut")

    # ...

    scr = Screen::byIndex(0)
    geom = scr.geometry
    Test.log("Screen is " + geom.width.to_s + " by " + geom.height.to_s)
package require squish::screen

    # ...

    set scr [Squish::Screen byIndex 0]
    set geom [$scr geometry]
    test log [concat "Screen is " [property get $geom width] " by " [property get $geom height]]

Screen.count()

此方法返回可用 Screen 对象的数量。

Screen.byIndex(index)

此方法返回一个 Screen 对象。指定的 index 必须在 0Screen.count() - 1 范围内。

index

Screen 对象的只读属性,表示此 Screen 对象在所有可用 Screen 对象列表中的索引。

geometry

Screen 对象的只读属性,返回一个包含此 Screen 对象尺寸的 ScreenRectangle

orientation

Screen 对象的可读/可写属性,通过以下四个属性之一指定此 Screen 的方向。除了以下属性外,还可用数字指定方向,1 表示 LandscapeOrientation,2 表示 PortraitOrientation,4 表示 ReverseLandscapeOrientation,8 表示 ReversePortraitOrientation。

Screen.LandscapeOrientation

Screen.PortraitOrientation

Screen.ReverseLandscapeOrientation

Screen.ReversePortraitOrientation

注意:由于语言限制,这些方向属性以小写字母开头。

ToplevelWindow 对象

有关顶级窗口的信息和处理。要使用此 ToplevelWindow 对象,必须在脚本文件中包含 Squish toplevelwindow 库。

source(findFile("scripts", "javascript/toplevelwindow.js"));

    // ...

    var win = ToplevelWindow.focused();
    var geom = win.geometry;
    test.log("Focused window is " + geom.width + " by " + geom.height);
use strict;
use utf8;
use warnings;

use Squish::ToplevelWindow;

    # ...

    my $win = Squish::ToplevelWindow->focused();
    my $geom = $win->geometry;
    test::log("Focused window is " . $geom->width . " by " . $geom->height);
# -*- coding: utf-8 -*-
from toplevelwindow import *

    # ...

    win = ToplevelWindow.focused()
    geom = win.geometry
    test.log("Focused window is " + str(geom.width) + " by " + str(geom.height))
# encoding: UTF-8
require 'squish'
require 'squish/toplevelwindow'

    # ...

    win = ToplevelWindow::focused()
    geom = win.geometry
    test.log("Focused window is " + geom.width + " by " + geom.height)
package require squish::toplevelwindow

    # ...

    set win [Squish::ToplevelWindow focused]
    set geom [$win geometry]
    test log "Focused window is [property get $geom width] by [property get $geom height]"

ToplevelWindow.byName(objectname, timeout)

ToplevelWindow.byObject(object)

这些方法返回一个 ToplevelWindow 对象,给出给定的 objectnameobject。第一个是一个方便方法,用于调用第二个,使用 Object waitForObject(objectOrName) 的结果。这些方法根据工具包接受不同的参数类型,并且应与大多数顶级窗口(如对话框、主窗口和浏览器标签页)一起工作。

tlw = ToplevelWindow.byName({'type': 'BrowserTab'})
#  ... is equivalent to ...
tlw = ToplevelWindow.byObject(activeBrowserTab())

ToplevelWindow.focused()

此方法返回一个具有键盘焦点的窗口的 ToplevelWindow 对象。如果没有找到具有键盘焦点的窗口,则引发异常。

注意:要从 Squish for Web 获取 TopLevelWindow 实例,请使用 ToplevelWindow.byObject(activeBrowserTab())。不支持 focused() 方法。

geometry

ToplevelWindow 对象的只读属性,返回一个包含引用的窗口尺寸的 ScreenRectangle

nativeObject

一个顶层数据窗口对象(ToplevelWindow)的只读属性,返回创建该顶层数据窗口对象的对象。

close()

此方法关闭由该顶层数据窗口对象引用的窗口。

maximize()

此方法将指定顶层数据窗口对象引用的窗口最大化。

minimize()

此方法最小化指定顶层数据窗口对象引用的窗口。

moveTo(x, y)

此方法将此顶层数据窗口对象引用的窗口客户端区域(不包括窗口边框)的左上角移动到指定的全局位置。

resizeTo(width, height)

此方法调整此顶层数据窗口对象引用的窗口客户端区域(不包括窗口边框)的大小,到指定的宽度和高度。

restore()

此方法将从全屏状态还原由指定的顶层数据窗口对象引用的窗口。

setFocus()

此方法将键盘输入焦点设置为指定的顶层数据窗口对象引用的窗口。

注意:在Windows上,防止单位失去焦点的功能阻止某些API改变活动窗口的焦点。因此,setFocus可能在Windows系统上没有效果。

注意:此功能不支持Squish for Web。使用时将生成错误。

setForeground()

此方法将指定顶层数据窗口对象引用的窗口置于前台。

注意:在Windows上,锁前台的特性防止某些API改变前台窗口。因此,setForeground可能在Windows系统上没有效果。

注意:此功能不支持Squish for Web。使用时将生成错误。

setFullscreen()

此方法将指定顶层数据窗口对象引用的窗口更改为全屏,即覆盖整个屏幕而不显示窗口边框。使用 restore() 取消此操作。

squishinfo 对象

全局的 squishinfo 对象提供了以下属性。

int squishinfo.major

此只读属性以单个整数形式存储Squish的主版本号(例如,4)。

int squishinfo.minor

此只读属性以单个整数形式存储Squish的次版本号(例如,0)。

int squishinfo.patch

此只读属性以单个整数形式存储Squish的修正版本号(例如,1)。

String squishinfo.resultDir

此只读属性存储结果目录的路径。

—squishinfo.settingsGroup

已废弃

—String

此只读属性持有当前测试活动设置组的名称。

String squishinfo.testCase

此只读属性包含了当前测试用例的路径。

字符串squishinfo.testCaseName

这个只读属性持有当前测试用例的名称。

字符串squishinfo.testSuiteName

这个只读属性持有当前测试套件的名称。

整数squishinfo.version

这个只读属性持有Squish的完整版本号(主要版本/次要版本/修补版本/发布版本)作为一个单一整数(进一步解释见下文)。

squishinfo.version的数字是一个唯一数字,代表Squish的完整版本号(主要版本/次要版本/修补版本/发布版本)。该数字由四个字节组成,通过将每一部分表示为一个单字节的十六进制数。所以Squish 4.0.1-final将表示为数字0x040001FF,其中0x04是主要版本(4),0x00是次要版本(0),0x01是修补版本(1),而0xFF是发布版本(final)。发布版本使用三个十六进制数之一进行编码:使用0xAA表示“alpha”,使用0xBB表示“beta”,使用0xFF表示“final”。

使用十六进制格式版本号可以轻松地在测试脚本中编写特定于版本的代码。以下是一个示例,其中我们只想在Squish 4.0.0-final或更高版本上执行某些代码(例如,利用某些Squish 4特定的功能)

if squishinfo.version >= 0x040000FF:
   # code meant for Squish version 4.0.0-final or higher
if (squishinfo.version >= 0x040000FF) {
   // code meant for Squish version 4.0.0-final or higher
}
if (squishinfo->version >= 0x040000FF) {
   # code meant for Squish version 4.0.0-final or higher
}
if Squishinfo.version >= 0x040000FF
   # code meant for Squish version 4.0.0-final or higher
end
if {[squishinfo version] >= 0x040000FF} {
   # code meant for Squish version 4.0.0-final or higher
}

字符串squishinfo.version_str

这个只读属性以人类可读的字符串形式(例如,“4.0.1-final”)持有Squish的版本号。

testInteraction函数

Squish为需要在回放期间与真实用户进行交互的测试提供了几个函数。这种交互包括手动验证中的简单问题以及提供用户输入,即手动驱动测试或在观察测试执行时做笔记。

testInteraction函数显示消息框,根据用户按下的按钮返回以下常量值之一

  • testInteraction.Ok
  • testInteraction.Yes
  • testInteraction.No

任何显示对话框的testInteraction函数都会在其标题栏中显示当前测试脚本文件名和行号。

调用这些函数仅在以--interactive选项启动squishrunner时才有效(另请参阅squishrunner –testsuite: 以批量模式运行测试)。来自squishide的测试始终以交互模式运行。在非交互模式下调用任何testInteraction函数(除了testInteraction.isAvailable())会导致脚本错误,从而终止脚本执行。

string testInteraction.choice(message, items)

显示一个对话框,其中message作为消息文本,以及一个可选择的items列表。返回的字符串包含所选项的文本或用户取消对话框时的空字符串。

var name = testInteraction.choice("Choose something", ["First", "Second", "Third"])
if (name == "") {
  test.warning("No item was chosen")
} else {
  test.log(item + " it is!")
}
my $item = testInteraction::choice("Choose something", ["First", "Second", "Third"]);
if ($item eq "") {
  test::warning("No item was chosen");
} else {
  test::log($item." it is!");
}
item = testInteraction.choice("Choose something", ["First", "Second", "Third"])
if not item:
  test.warning("No item was chosen")
else:
  test.log("{} it is!".format(item))
item = TestInteraction.choice("Choose something", ["First", "Second", "Third"])
if item == ""
  Test.warning("No item was chosen")
else
  Test.log("#{item} it is!")
end
set item [testInteraction choice "Choose something" [list "First" "Second" "Third"]]
if {$item == ""} {
  test warning "No item was chosen"
} {
  test log "$item it is!"
}

int testInteraction.information(message)

显示一个包含message作为消息文本、信息图标和OK按钮的消息框。

testInteraction.information("This is the 'information' function.\nPress 'OK' to continue.")
testInteraction::information("This is the 'information' function.\nPress 'OK' to continue.");
testInteraction.information("This is the 'information' function.\nPress 'OK' to continue.")
TestInteraction.information("This is the 'information' function.\nPress 'OK' to continue.")
testInteraction information "This is the 'information' function.\nPress 'OK' to continue."

string testInteraction.input(message, initialText)

显示一个对话框,其中用message作为消息文本,并为用户输入提供了一个行编辑器。可选的initialText将行编辑器的初始文本设置为。返回的字符串包含行编辑器的内容或用户取消对话框时的空字符串。

name = testInteraction.input("Type in your name and press one of buttons below.")
if (name == "") {
  testInteraction.warning("It's sad you don't want to share your name.")
} else {
  testInteraction.information("Hello " + name + "!")
}
$name = testInteraction::input("Type in your name and press one of buttons below.");
if ($name eq "") {
  testInteraction::warning("It's sad you don't want to share your name.");
} else {
  testInteraction::information("Hello $name!");
}
name = testInteraction.input("Type in your name and press one of buttons below.")
if name == "":
  testInteraction.warning("It's sad you don't want to share your name.")
else:
  testInteraction.information("Hello %s!" %name)
name = TestInteraction.input("Type in your name and press one of buttons below.")
if name == ""
  TestInteraction.warning("It's sad you don't want to share your name.")
else
  TestInteraction.information("Hello " + name + "!")
end
set name [testInteraction input "Type in your name and press one of buttons below."]
if {$name == ""} {
  testInteraction warning "It's sad you don't want to share your name."
} {
  testInteraction information "Hello $name!"
}

bool testInteraction.isAvailable()

此函数返回测试脚本是否由包含 --interactive 选项启动的 squishrunner 执行。这允许创建仅在请求时显示交互式对话框同时以非交互方式运行的测试。

void testInteraction.notification(message)

void testInteraction.notification(message, timeoutSecs)

显示一个带有 message 作为消息文本,持续 timeoutSecs 秒的定时非阻塞消息框。如果未提供 timeoutSecs,则消息框将显示 5 秒。

timeOut = 2
testInteraction.notification("This is the 'notification' function.\nWait " + timeOut +" seconds for message box to close.", timeOut)
//or
testInteraction.notification("This is the 'notification' function.\nWait 5 seconds for message box to close.")
$timeOut = 2;
testInteraction::notification("This is the 'notification' function.\nWait $timeOut seconds for message box to close.", $timeOut);
#or
testInteraction::notification("This is the 'notification' function.\nWait 5 seconds for message box to close.");
timeOut = 2
testInteraction.notification("This is the 'notification' function.\nWait %s seconds for message box to close." %timeOut, timeOut)
#or
testInteraction.notification("This is the 'notification' function.\nWait 5 seconds for message box to close.")
timeOut = "2"
TestInteraction.notification("This is the 'notification' function.\nWait "+ timeOut + " seconds for message box to close.", timeOut)
#or
TestInteraction.notification("This is the 'notification' function.\nWait 5 seconds for message box to close.")
set timeOut 2
testInteraction notification "This is the 'notification' function.\nWait $timeOut seconds for message box to close." $timeOut
#or
testInteraction notification "This is the 'notification' function.\nWait 5 seconds for message box to close."

string testInteraction.password(message)

显示一个对话框,其中 message 作为消息文本,并使用星号代替实际输入的字符进行行编辑。返回的字符串包含行编辑的内容或如果用户取消了对话框则为空字符串。

passwd = testInteraction.password("Type 'P@ssw0rd' without quotes to reveal secret information.")
if (passwd == "P@ssw0rd") {
  testInteraction.information("The secret information is: The Cake is a Lie!")
} else {
  testInteraction.warning("Wrong password. It seems the secret will remain hidden.")
}
$passwd = testInteraction::password("Type 'Passw0rd' without quotes to reveal secret information.");
if ($passwd eq "Passw0rd") {
  testInteraction::information("The secret information is: The Cake is a Lie!");
} else {
  testInteraction::warning("Wrong password. It seems the secret will remain hidden.");
}
passwd = testInteraction.password("Type 'P@ssw0rd' without quotes to reveal secret information.")
if passwd == "P@ssw0rd":
  testInteraction.information("The secret information is: The Cake is a Lie!")
else:
  testInteraction.warning("Wrong password. It seems the secret will remain hidden.")
passwd = TestInteraction.password("Type 'P@ssw0rd' without quotes to reveal secret information.")
if passwd == "P@ssw0rd"
  TestInteraction.information("The secret information is: The Cake is a Lie!")
else
  TestInteraction.warning("Wrong password. It seems the secret will remain hidden.")
end
set passwd [testInteraction password "Type 'P@ssw0rd' without quotes to reveal secret information."]
if {$passwd == "P@ssw0rd"} {
  testInteraction information "The secret information is: The Cake is a Lie!"
} {
  testInteraction warning "Wrong password. It seems the secret will remain hidden."
}

int testInteraction.question(message)

显示一个消息框,其中 message 作为消息文本,有一个问号图标,一个 按钮和一个 按钮。

questionResult = testInteraction.question("Do you wish to continue?")
if (questionResult == testInteraction.Yes) {
  testInteraction.information("Button 'Yes' was pressed.")
} else {
  testInteraction.information("Button 'No' was pressed.")
}
$questionResult = testInteraction::question("Do you wish to continue?");
if ($questionResult == testInteraction::Yes) {
  testInteraction::information("Button 'Yes' was pressed.");
} else {
  testInteraction::information("Button 'No' was pressed.");
}
questionResult = testInteraction.question("Do you wish to continue?")
if questionResult == testInteraction.Yes:
  testInteraction.information("Button 'Yes' was pressed.")
else:
  testInteraction.information("Button 'No' was pressed.")
questionResult = TestInteraction.question("Do you wish to continue?")
if questionResult == TestInteraction::YES
  TestInteraction.information("Button 'Yes' was pressed.")
else
  TestInteraction.information("Button 'No' was pressed.")
end
set questionResult [testInteraction question "Do you wish to continue?"]
if {$questionResult == [testInteraction Yes] } {
  testInteraction information "Button 'Yes' was pressed."
} {
  testInteraction information "Button 'No' was pressed."
}

void testInteraction.showImage(image, [message], [timeoutSecs])

显示一个包含 imagemessage 消息文本和 确定 按钮的定时非阻塞对话框。如果未提供 timeoutSecs,则对话框将显示 5 秒。

var img = grabDesktopScreenshot();
testInteraction.showImage(img, "Current desktop", 2);
my $img = grabDesktopScreenshot();
testInteraction::showImage($img, "Current desktop", 2);
img = grabDesktopScreenshot()
testInteraction.showImage(img, "Current desktop", 2)
img = grabDesktopScreenshot();
TestInteraction.showImage(img, "Current desktop", 2)
set img [grabDesktopScreenshot]
testInteraction showImage $img, "Current desktop", 2

int testInteraction.warning(message)

显示一个消息框,其中 message 作为消息文本,一个警告图标和一个 确定 按钮。

testInteraction.warning("This is the 'warning' function.\nPress 'OK' to continue.")
testInteraction::warning("This is the 'warning' function.\nPress 'OK' to continue.");
testInteraction.warning("This is the 'warning' function.\nPress 'OK' to continue.")
TestInteraction.warning("This is the 'warning' function.\nPress 'OK' to continue.")
testInteraction warning "This is the 'warning' function.\nPress 'OK' to continue."

testSettings 对象

Squish 提供了一个全局的 testSettings 对象,其属性和方法可以设置以控制测试执行的某些方面。

SequenceOfStrings testSettings.getWrappersForApplication(application)

此函数返回与指定 application 关联的包装器列表。(另见 testSettings.setWrappersForApplication(application, wrapperList)。)

bool testSettings.logScreenshotOnFail

如果此属性为 true,则每个测试失败都会导致 Squish 在失败发生时获取桌面的截图;默认情况下,此属性为 false 且不自动获取失败截图。

例如,假设我们在夜间测试中偶尔遇到验证特定小部件状态的测试失败。我们无法解释问题的原因,但怀疑由于尚未知的因素,我们应用程序的 GUI 整体状态已损坏。为了通过视觉检查为开发商提供有用的信息,我们启用自动捕获截图—but only for the test that is causing concern

testSettings.logScreenshotOnFail = True
# ... perform test ...
testSettings.logScreenshotOnFail = False
testSettings.logScreenshotOnFail = true;
// ... perform test ...
testSettings.logScreenshotOnFail = false;
testSettings->logScreenshotOnFail(1);
# ... perform test ...
testSettings->logScreenshotOnFail(0);
TestSettings.logScreenshotOnFail = true
# ... perform test ...
TestSettings.logScreenshotOnFail = false
testSettings set logScreenshotOnFail 1
# ... perform test ...
testSettings set logScreenshotOnFail 0

bool testSettings.logScreenshotOnError

如果此属性为 true,则每个测试错误都会导致 Squish 在错误发生时获取桌面的截图;默认情况下,此属性为 false 且不自动获取错误截图。

bool testSettings.logScreenshotOnWarning

如果此属性为true,每次测试警告都会导致Squish在警告发生时截取桌面截图;默认情况下,此属性为false,不会自动截取警告的截图。

bool testSettings.logScreenshotOnPass

如果此属性为true,每次测试通过都会导致Squish截取桌面截图。默认情况下,此属性为false,测试通过的截图不会自动截取。

bool testSettings.logStacktraceOnLog

如果此属性为true,每次测试日志将附加堆栈跟踪信息到支持堆栈跟踪信息的测试报告中。默认情况下,此属性为false。

bool testSettings.logStacktraceOnPass

如果此属性为true,每次测试通过都会在支持堆栈跟踪信息的测试报告中附加堆栈跟踪信息。默认情况下,此属性为false。

bool testSettings.objectNotFoundDebugging

如果此属性为false,则当对象无法定位或未准备好时,不会打开对象未找到的调试对话框。默认情况下,此属性为true,对象未找到对话框会在无法在指定时间内定位到对象或对象未准备好时打开。

某些算法需要在不触发对象未找到对话框的情况下确定对象是否已准备好。在通常触发不需要的对象未找到对话框的脚本部分,您可以使用objectNotFoundDebugging属性临时禁用此对话框。

testSettings.objectNotFoundDebugging = False
# ... wait for object that might not exist or get ready in time ...
testSettings.objectNotFoundDebugging = True
testSettings.objectNotFoundDebugging = false;
// ... wait for object that might not exist or get ready in time ...
testSettings.objectNotFoundDebugging = true;
testSettings->objectNotFoundDebugging(0);
# ... wait for object that might not exist or get ready in time ...
testSettings->objectNotFoundDebugging(1);
TestSettings.objectNotFoundDebugging = false
# ... wait for object that might not exist or get ready in time ...
TestSettings.objectNotFoundDebugging = true
testSettings set objectNotFoundDebugging 0
# ... wait for object that might not exist or get ready in time ...
testSettings set objectNotFoundDebugging 1

注意:如果“在squisheid首选项中禁用此播放的“ بازارعناوینناپسندی بازیابی ”部分启用时’对象未找到’问题,则将不会显示对象未找到对话框

bool testSettings.imageNotFoundDebugging

如果此属性为false,则当模版图像无法定位时,不会打开图像未找到的调试对话框。默认情况下,此属性为true,当模版图像无法在指定时间内定位时,会打开图像未找到对话框。

某些算法需要在不触发图像未找到对话框的情况下进行图像搜索。在通常触发不需要的图像未找到对话框的脚本部分,您可以使用imageNotFoundDebugging属性临时禁用此对话框。

testSettings.imageNotFoundDebugging = False
# ... wait for image that might not exist in time ...
testSettings.imageNotFoundDebugging = True
testSettings.imageNotFoundDebugging = false;
// ... wait for image that might not exist in time ...
testSettings.imageNotFoundDebugging = true;
testSettings->imageNotFoundDebugging(0);
# ... wait for image that might not exist in time ...
testSettings->imageNotFoundDebugging(1);
TestSettings.imageNotFoundDebugging = false
# ... wait for image that might not exist in time ...
TestSettings.imageNotFoundDebugging = true
testSettings set imageNotFoundDebugging 0
# ... wait for image that might not exist in time ...
testSettings set imageNotFoundDebugging 1

注意:如果“在squisheid首选项中禁用此播放的“ بازارعناوینناپسندی بازیابی ”部分启用时’图像未找到’问题,则将不会显示图像未找到对话框

bool testSettings.textNotFoundDebugging

如果此属性为false,则当无法定位搜索文本时,不会打开文本未找到的调试对话框。默认情况下,此属性为true,当搜索文本无法在指定时间内定位时,会打开文本未找到对话框。

某些算法需要在不触发文本未找到对话框的情况下进行文本搜索。在通常触发不需要的文本未找到对话框的脚本部分,您可以使用textNotFoundDebugging属性临时禁用此对话框。

testSettings.textNotFoundDebugging = False
# ... wait for text that might not exist in time ...
testSettings.textNotFoundDebugging = True
testSettings.textNotFoundDebugging = false;
// ... wait for text that might not exist in time ...
testSettings.textNotFoundDebugging = true;
testSettings->textNotFoundDebugging(0);
# ... wait for text that might not exist in time ...
testSettings->textNotFoundDebugging(1);
TestSettings.textNotFoundDebugging = false
# ... wait for text that might not exist in time ...
TestSettings.textNotFoundDebugging = true
testSettings set textNotFoundDebugging 0
# ... wait for text that might not exist in time ...
testSettings set textNotFoundDebugging 1

注意:如果“在squisheid首选项中禁用此播放的“ بازارعناوینناپسندی بازیابی ”部分启用时’文本未找到’问题,则将不会显示文本未找到对话框

testSettings.setWrappersForApplication(application, wrapperList)

此函数将与指定应用程序关联一个包装器列表。该列表中必须包含至少一个主工具包包装器。可选地,它可能包含特定于应用程序的包装器(对于支持它们的Squish版本)。主要工具包包装器包括

  • Qt
  • Tk
  • Web
  • Java
  • Mac
  • Windows
  • Android
  • iOS
  • Flex

这些主要工具包包装器名称直接对应于 Toolkit字段中的 Test Suite Configuration视图。

请注意,Squish 4的动态包装器支持大大降低了创建和维护特定于应用程序的包装器的需求。

以下是一个示例,它设置了Qt工具包包装器和自定义应用程序包装器,然后启动了AUT

testSettings.setWrappersForApplication("MyApp", ["Qt", "CanvasWrapper"])
startApplication("MyApp")
testSettings.setWrappersForApplication("MyApp", ["Qt", "CanvasWrapper"]);
startApplication("MyApp");
testSettings->setWrappersForApplication("MyApp", ("Qt", "CanvasWrapper"));
startApplication("MyApp");
TestSettings.setWrappersForApplication("MyApp", ["Qt", "CanvasWrapper"])
startApplication("MyApp")
testSettings setWrappersForApplication MyApp { Qt CanvasWrapper }
startApplication "MyApp"

(另请参阅 SequenceOfStrings testSettings.getWrappersForApplication(application)。)

bool testSettings.silentVerifications

如果此属性为真,Squish将不会为通过或失败的Boolean test.vp(name)Boolean test.xvp(name)Boolean test.vpWithObject(name, objectNameOrReference)Boolean test.vpWithImage(name, imageOrFilePath)调用产生测试结果条目。在结合使用test.vp()和test.vpWithObject()的(布尔)返回值的基础上,这可以用于自定义的一系列验证点。

以下是一个示例,检查三个截图验证点中的一个是否通过。

testSettings.silentVerifications = True
for current in ['VP-winxp', 'VP-win2k', 'VP-win7']:
    if test.vp(current):
        test.passes("%s matched" % (current, ))
        break
else:
    test.fail("none of the provided VPs matched")

bool testSettings.breakOnFailure

如果此属性为 true,则调试器会在每次由 Boolean test.compare(value1, value2) Boolean test.xcompare(value1, value2) Boolean test.verify(condition) Boolean test.xverify(condition) Boolean test.vp(name) Boolean test.xvp(name) Boolean test.vpWithObject(name, objectNameOrReference) Boolean test.vpWithImage(name, imageOrFilePath) Boolean test.exception(code)执行的每次失败验证以及每次对 test.fail(message) test.fatal(message)的调用中停止。默认情况下,此属性为 false

bool testSettings.throwOnFailure

如果此属性为真,则 Boolean test.compare(value1, value2) Boolean test.xcompare(value1, value2) Boolean test.verify(condition) Boolean test.xverify(condition) Boolean test.vp(name) Boolean test.xvp(name) Boolean test.vpWithObject(name, objectNameOrReference) Boolean test.vpWithImage(name, imageOrFilePath) Boolean test.exception(code)执行的每次失败验证以及每次对 test.fail(message) test.fatal(message)的调用都将引发脚本错误。默认情况下,此属性为false,上述函数不引发脚本错误。

整型 testSettings.retryDuration

此属性会影响布尔型函数 test.vp(name)test.xvp(name)test.vpWithObject(name, objectNameOrReference)test.vpWithImage(name, imageOrFilePath)。它可以用来指定验证失败后应重试多长时间。默认值为 0,表示验证只尝试一次。如果您将其设置为 5000,当验证持续失败时(即,它会重试直到通过或 5 秒过去),则至少会重试 5000ms。这对于 AUT 需要达到某个阶段才能通过属性或截图验证非常有用。这有助于减少计时问题。

注意:中间失败没有被记录。只有系列中的最后一个结果被记录。这可以是当重试时间到达而验证仍失败时的失败,或者是一个通过。

以下示例演示了如何为每个验证单独设置此属性,但您也可以为随后的每个验证设置一次。

testSettings.retryDuration = 5000
test.vp("VP1")
testSettings.retryDuration = 0
testSettings.retryDuration = 5000;
test.vp("VP1")
testSettings.retryDuration = 0;
testSettings->retryDuration(5000);
test::vp("VP1")
testSettings->retryDuration(0);
TestSettings.retryDuration = 5000
Test.vp("VP1")
TestSettings.retryDuration = 0
testSettings set retryDuration 5000
test vp "VP1"
testSettings set retryDuration 0

布尔型 testSettings.imageSearchTolerant

此属性会影响函数 ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion])ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion])Boolean test.imagePresent(imageFile, [parameterMap], [searchRegion])。如果有传递给上述函数的选项映射不包含 tolerant 键,则使用此属性的值代替。默认值为 false

数值类型 testSettings.imageSearchThreshold

此属性会影响函数 ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion])ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion])Boolean test.imagePresent(imageFile, [parameterMap], [searchRegion])。如果有传递给上述函数的选项映射不包含 threshold 键,则使用此属性的值代替。默认值为 99.5

布尔型 testSettings.imageSearchMultiscale

此属性会影响函数 ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion])ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion])Boolean test.imagePresent(imageFile, [parameterMap], [searchRegion])。如果有传递给上述函数的选项映射不包含 multiscale 键,则使用此属性的值代替。默认值为 false

数值类型 testSettings.imageSearchMinScale

此属性会影响函数 ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion])ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion])Boolean test.imagePresent(imageFile, [parameterMap], [searchRegion])。如果有传递给上述函数的选项映射不包含 minScale 键,则使用此属性的值代替。默认值为 50.0

数值类型 testSettings.imageSearchMaxScale

该属性影响以下功能:`ScreenRectangle findImage(imageFile, [parameterMap], [searchRegion])`、`ScreenRectangle waitForImage(imageFile, [parameterMap], [searchRegion])`和`Boolean test.imagePresent(imageFile, [parameterMap], [searchRegion])`。如果传递给上述函数的选项映射中不包含`maxScale`键,则使用该属性的值代替。默认值为`200.0`。

bool testSettings.defaultOcrLanguage

该属性影响以下OCR功能:`String getOcrText([parameterMap], [searchRegion])`、`ScreenRectangle findOcrText(text, [parameterMap], [searchRegion])`、`ScreenRectangle waitForOcrText(text, [parameterMap], [searchRegion])`和`Boolean test.ocrTextPresent(text, [parameterMap], [searchRegion])`。如果传递给上述函数的选项映射中不包含`language`键,则使用该属性的值代替。默认值为空,表示使用引擎的默认语言。

Integer testSettings.waitForObjectTimeout

该属性定义了在以下情况下默认的超时时间(以毫秒为单位):`Object waitForObject(objectOrName)`、`Object waitForObjectItem(objectOrName, itemOrIndex)`、`Object waitForObjectExists(name)`将等待对象查找成功。该超时值也适用于`Boolean test.vp(name)`、`Boolean test.xvp(name)`、`Boolean test.vpWithObject(name, objectNameOrReference)`、`Boolean test.vpWithImage(name, imageOrFilePath)`和`highlightObject(objectOrName, [msec])`。

超时值为0表示Squish将尝试找到对象一次。不支持负的超时值。

String testSettings.getPassword(key)

此方法检索与指定键关联的密码。密码存储在测试套件中,可以使用`密码信息`进行编辑。

注意:Squish测试套件中存储的密码必须以明文形式检索。因此,它们不是以安全方式存储的。只是单独存储,这样就不需要在测试脚本中硬编码密码。

config.xml中设置初始的testSettings对象值

通过编辑测试套件文件夹中的`config.xml`,可以设置`testSettings`对象属性的初始值。这样,您可以轻松地为多个测试用例设置相同的值。可以使用测试套件设置编辑器中的《测试设置》和《图像搜索》页面编辑config.xml中的测试设置,这些页面位于`squishide`中。

以下示例说明如何手动扩展config.xml。每个属性都可以以相同的方式设置。

<testconfig version="1.0">
...
<testsettings>
    <objectNotFoundDebugging>false</objectNotFoundDebugging>
    <testCaseName>some name</testCaseName>
</testsettings>
...
</testconfig>

测试套件的config.xml文件不一定总是自动创建。您可以使用文本编辑器手动创建它,或者在squishide中打开测试套件设置视图编辑器,编辑测试套件摘要和描述或默认测试设置。

RemoteSystem对象

注意: RemoteSystem对象可以用来与squishserver运行的系统进行交互。在某些情况下,AUT运行的系统与squishserver运行的系统并不相同。这意味着RemoteSystem在测试Android、iOS或一般可远程附加的AUT时,不能用来访问AUT的操作系统。

Squish提供了一个RemoteSystem对象,其方法可以对squishserver运行系统上的文件系统操作和进程执行进行操作。为了使用该对象,必须包含RemoteSystem库,并创建一个对象实例。

RemoteSystem RemoteSystem()

如果通过默认构造函数创建对象实例,则会自动建立与默认squishserver的连接。如果发生错误,无法建立连接,将会抛出异常,并且不会创建对象实例。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remotesys = new RemoteSystem();
    } catch (e) {
        test.fail("Connect to squishserver", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

eval {
    my $con = Squish::RemoteSystem->new();
    1;
} or do {
    my $e = $@;
    test::fail("Connect to squishserver", $e);
};
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remotesys = RemoteSystem()
    except Exception as e:
        test.fail("Connect to squishserver", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remotecon = RemoteSystem.new()
  rescue Exception => e
    Test.fail("Connect to squishserver", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remotesys [::Squish::RemoteSystem new]} result]} {
        test fail "Connect to squishserver" $result
    }
}

RemoteSystem RemoteSystem(host, port)

RemoteSystem对象的构造函数接受两个可选参数,可用于连接到任何squishserver。第一个参数是主机名或IP地址,第二个参数是端口号。以下示例创建了一个RemoteSystem对象,该对象连接到本地系统上手动启动的squishserver。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remotesys = new RemoteSystem("localhost", 4322);
    } catch (e) {
        test.fail("Connect to squishserver", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

eval {
    my $con = Squish::RemoteSystem->new("localhost", 4322);
    1;
} or do {
    my $e = $@;
    test::fail("Connect to squishserver", $e);
};
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remotesys = RemoteSystem("localhost", 4322)
    except Exception as e:
        test.fail("Connect to squishserver", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remotecon = RemoteSystem.new("localhost", 4322)
  rescue Exception => e
    Test.fail("Connect to squishserver", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remotesys [::Squish::RemoteSystem new localhost 4322]} result]} {
        test fail "Connect to squishserver" $result
    }
}

在调用对象构造函数时可能发生以下异常。

异常描述
运行时错误无法建立连接时。
类型/值/参数错误(JavaScript/Python/Ruby)当参数缺失时。

注意: Perl和Tcl的异常没有特定的异常类型。仅给出描述错误的消息。

RemoteSystem对象创建后,以下方法可用。

list RemoteSystem.execute(cmd)

list RemoteSystem.execute(cmd, cwd)

list RemoteSystem.execute(cmd, cwd, env)

list RemoteSystem.execute(cmd, cwd, env, options)

execute方法可以用来运行应用程序或shell命令。必须以命令及其所有参数的列表/数组作为第一个参数给出。下述三个参数为可选参数。

cwd参数指定执行提供的命令的工作目录。

env 参数允许设置或删除环境变量。使用空字符串作为值来删除环境变量。

options 参数提供了一些附加的选项,有时使用频率较低。以下是该参数支持的所有选项。

注意:RemoteSystem.execute 是一个同步操作,仅在执行命令完成后或进程作为后台任务启动时返回。当进程作为后台任务启动时,不再与 RemoteSystem 对象相关联。

RemoteSystem.execute 选项

以下表格列出了所有可能的选项。

参数类型默认值描述
cmd列表/数组强制要执行的命令及其参数的数组。
cwd字符串启动进程的工作目录。
env字典环境变量的键/值对。
options字典所有选项的字典。
options.keepLineEnding布尔值如果提供并设置为 false,将将启动进程的 stdout/stderr 输出的换行符转换为 '\n'(Unix)换行符。
options.clearenv布尔值如果提供并设置为 true,进程将以最小环境启动。然而,在大多数操作系统上,不可能删除所有环境变量,因为这样会阻止操作系统提供的某些功能或工具正常工作。
options.timeout整数30值是秒数超时。它用于限制启动的进程的执行时间。
options.encoding字符串UTF-8启动进程的 stdout/stderr 输出的编码名称。有关支持的标准编码,请参阅下文。

RemoteSystem.execute 返回值

以下表格列出了返回值。返回值是包含三个元素的简单列表/数组。顺序始终相同。

名称类型描述
exitcode字符串/Unicode进程的退出代码。
stdout字符串/Unicode进程的 stdout 输出。
stderr字符串/Unicode进程的 stderr 输出。

注意:JavaScript 中的返回值是一个具有属性的对象。

RemoteSystem.execute 示例

为每种语言提供示例。示例添加一个环境变量,删除一个,然后从 Windows 获取环境变量列表。命令的最大运行时间为 10 秒,使用 Windows IBM850 代码页进行编码。同时将换行符转换为 "\n" 换行符。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remotesys = new RemoteSystem();
        cmd = ["cmd", "/c", "set"];
        cwd = "";
        env = {};
        env["MYTESTENV"] = "test string";
        env["COMPUTERNAME"] = "";
        options = {};
        options.keepLineEnding = false;
        options.clearenv = false;
        options.timeout = 10;
        options.encoding = "IBM850"
        execresult = remotesys.execute(cmd, cwd, env, options);
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;
    my $cmd = ["cmd", "/c", "set"];
    my $cwd = "";
    my $env = {
      "MYTESTENV" => "test string",
      "COMPUTERNAME" => ""
    };
    my $options = {
      "keepLineEnding" => 0,
      "clearenv" => 0,
      "timeout" => 10,
      "encoding" => "IBM850"
    };
    eval {
        my $remotecon = Squish::RemoteSystem->new();
        my ($exitcode,$stdout,$stderr) = $remotecon->execute($cmd, $cwd, $env, $options);
        1;
    } or do {
        test::fail("RemoteSystem error", $@);
    };
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remotesys = RemoteSystem()
        cmd = [ "cmd", "/c", "set" ]
        cwd = ""
        env = {
            "MYTESTENV": "test string",
            "COMPUTERNAME": ""
        }
        options = {
            "keepLineEnding": False,
            "clearenv": False,
            "timeout": 10,
            "encoding": "IBM850"
        }
        (exitcode, stdout, stderr) = remotesys.execute(cmd, cwd, env, options)
        test.verify(exitcode == "0", "Command not executed")
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remotesys = RemoteSystem.new()
    cmd = ["cmd", "/c", "set"]
    cwd = ""
    env = {
      "MYTESTENV" => "test string",
      "COMPUTERNAME" => ""
    }
    options = {
      "keepLineEnding" => false,
      "clearenv" => false,
      "timeout" => 10,
      "encoding" => "IBM850"
    }
    exitcode, stdout, stderr = remotesys.execute(cmd, cwd, env, options)
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    set cmd [list cmd /c set]
    set cwd ""
    set env [dict create]
    set options [dict create keepNewLine 0 clearenv 0 timeout 10 encoding IBM850]

    if {[catch {set remotesys [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }
    if { [catch {foreach {exitcode stdout stderr} [$remotesys execute $cmd $cwd $env $options] {break}} result] } {
        test fail "RemoteSystem error" $result
    }
}

注意:当命令在 Windows 上执行并在控制窗口中运行时,编码必须与使用的控制台代码页相匹配。有关 Windows 代码页编号及其名称,请参阅 https://msdn.microsoft.com/de-de/library/windows/desktop/dd317756(v=vs.85).aspx

注意:Linux 编码主要是 UTF-8。

RemoteSystem.execute 编码

以下列表是可能编码的子集。

UTF-8UTF-16ISO 8859-1 至 10
ISO 8859-13 至 16ISO 2022-JPShift-JIS
IBM 874IBM 866IBM 850
Windows-1250 至 1258Big5KOI8-R

注意:有关支持的所有编码的完整列表,请参阅 https://doc.qt.ac.cn/qt-6/qtextcodec.html#details

远程系统执行异常

在执行命令时可能发生以下异常。

异常描述
运行时错误不支持的编码。当所需的编码不受支持时将引发异常。
运行时错误找不到工作目录。当找不到工作目录时将引发异常。
运行时错误超时后程序未启动。当要执行的程序在10秒内未启动时将引发异常。

String RemoteSystem.getEnvironmentVariable(variableName)

getEnvironmentVariable方法可用于从远程系统检索环境变量的内容。使用variableName参数指定远程系统上环境变量的名称。

注意:如果检索的环境变量在远程系统上未设置,函数将返回空字符串。无法区分变量设置为空字符串或根本未设置。

以下示例检索环境变量HOMEDRIVE并记录结果。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.log(remoteOS.getEnvironmentVariable("HOMEDRIVE"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::log($remoteOS->getEnvironmentVariable("HOMEDRIVE"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.log(remoteOS.getEnvironmentVariable("HOMEDRIVE"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.log(remoteOS.getEnvironmentVariable("HOMEDRIVE"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test log [$remoteOS getEnvironmentVariable "HOMEDRIVE"] } result] } {
        test fail "RemoteSystem error" $result
    }
}

String RemoteSystem.getOSName()

getOSName方法可用于检索远程系统操作系统的名称。如果无法确定操作系统,函数将返回"Unknown"。

可能名称包括

  • "Android" — Android
  • "Darwin" — macOS 和 iOS
  • "Linux" — Linux
  • "QNX" — QNX
  • "SunOS" — Solaris
  • "Windows" — Windows

以下示例检索操作系统名称并记录结果。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.log(remoteOS.getOSName());
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::log($remoteOS->getOSName());
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.log(remoteOS.getOSName())
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.log(remoteOS.getOSName())
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    } else {
        test log [$remoteOS getOSName]
    }
}

StringList RemoteSystem.listFiles(path)

listFiles方法可用于检索远程系统特定路径的目录列表。使用path参数指定要检索的远程系统路径。该方法返回文件和文件夹名称的列表(不返回完整路径)。它不会递归工作,因此不会显示子文件夹的内容。如果路径不存在或不是目录,将引发异常。

以下示例检索"/"目录(在Windows中应为home驱动器)的所有目录和文件名。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();

        dirList = remoteOS.listFiles("/");

        for (var i = 0; i < dirList.length; i++) {
            test.log(dirList[i]);
        }
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        my @dirList = $remoteOS->listFiles("/");
        my $dirListLength = @dirList;

        for (my $i = 0; $i < $dirListLength; $i++) {
            test::log($dirList[$i]);
        }
        1;
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        dirList = remoteOS.listFiles("/")

        for remoteFile in dirList:
            test.log(remoteFile)
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    dirList = remoteOS.listFiles("/")
    dirList.each do |remoteFile|
      Test.log remoteFile
    end
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { set dirList [$remoteOS listFiles "/"]] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch {
        foreach remoteFile $dirList {
            test log $remoteFile
        } } result ] } {
        test fail "RemoteSystem error" $result
    }
}

Variant RemoteSystem.stat(path, propertyName)

stat方法可用于从远程系统检索特定路径的不同属性。使用path参数指定远程系统上的路径,使用propertyName指定要检索的属性。属性名称必须从预定义的属性名称清单中选择(属性名称区分大小写)。根据属性,此方法返回不同类型的结果。如果路径不存在或属性未知,将引发异常。

以下列表显示支持的属性和返回类型。

属性名称返回类型
exists布尔值
isDir布尔值
isFile布尔值
isSymLink布尔值
isReadable布尔值
isWritable布尔值
isExecutable布尔值
isHidden布尔值
lastModified时间戳
lastRead时间戳
大小整数

以下示例打印所给路径是目录还是文件。并打印目录最后一次被读取的时间戳。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.log(remoteOS.stat("/", "isDir"));
        test.log(remoteOS.stat("/", "isFile"));
        test.log(remoteOS.stat("/", "lastRead"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::log($remoteOS->stat("/", "isDir"));
        test::log($remoteOS->stat("/", "isFile"));
        test::log($remoteOS->stat("/", "lastRead"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.log(str(remoteOS.stat("/", "isDir")))
        test.log(str(remoteOS.stat("/", "isFile")))
        test.log(remoteOS.stat("/", "lastRead"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.log(remoteOS.stat("/", "isDir")? "true" : "false")
    Test.log(remoteOS.stat("/", "isFile")? "true" : "false" )
    Test.log(remoteOS.stat("/", "lastRead"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test log [$remoteOS stat "/" "isDir" ] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test log [$remoteOS stat "/" "isFile" ] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test log [$remoteOS stat "/" "lastRead" ] } result] } {
        test fail "RemoteSystem error" $result
    }
}

Boolean RemoteSystem.exists(path)

exists方法可用于检查远程系统上的特定路径是否存在。使用path参数指定要检查的远程系统路径。

以下示例打印两个给定路径是否存在。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.log(remoteOS.exists("/"));
        test.log(remoteOS.exists("/some/nonexisting/path"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::log($remoteOS->exists("/"));
        test::log($remoteOS->exists("/some/nonexisting/path"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.log(str(remoteOS.exists("/")))
        test.log(str(remoteOS.exists("/some/nonexisting/path")))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.log(remoteOS.exists("/")? "true" : "false")
    Test.log(remoteOS.exists("/some/nonexisting/path")? "true" : "false")
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test log [$remoteOS exists "/"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test log [expr ![$remoteOS exists "/some/nonexisting/path"]] } result] } {
        test fail "RemoteSystem error" $result
    }
}

布尔 RemoteSystem.deleteFile(path)

deleteFile 方法可以用来删除远程系统上的文件。使用 path 参数指定远程系统上文件的路径。如果提供的文件无法删除或路径不指向文件,将抛出异常。

以下示例显示了如何使用 deleteFile 方法。如果您想要尝试示例,需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.deleteFile("/some/nonexisting/filepath"));
        test.verify(!remoteOS.exists("/some/nonexisting/filepath"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->deleteFile("/some/nonexisting/filepath"));
        test::verify(!$remoteOS->exists("/some/nonexisting/filepath"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.deleteFile("/some/nonexisting/filepath"))
        test.verify(!remoteOS.exists("/some/nonexisting/filepath"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.deleteFile("/some/nonexisting/filepath"))
    Test.verify(!remoteOS.exists("/some/nonexisting/filepath"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS deleteFile "/some/nonexisting/filepath"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [expr ![$remoteOS exists "/some/nonexisting/filepath"]] } result] } {
        test fail "RemoteSystem error" $result
    }
}

布尔 RemoteSystem.deleteDirectory(path)

布尔 RemoteSystem.deleteDirectory(path, recursive)

deleteDirectory 方法可以用来删除远程系统上的目录。使用 path 参数指定远程系统上文件夹的路径。可选的布尔参数 recursive 可以用来指定是否应该删除目录内的子目录和文件。如果未设置 recursive 标志,且指定的目录包含文件或文件夹,则删除操作将失败并抛出异常。此外,如果无法删除指定的某些文件和文件夹,也将抛出异常。

以下示例显示了如何使用 deleteDirectory 方法。如果您想要尝试示例,需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.deleteDirectory("/some/nonexisting/path"));
        test.verify(!remoteOS.exists("/some/nonexisting/path"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->deleteDirectory("/some/nonexisting/path"));
        test::verify(!$remoteOS->exists("/some/nonexisting/path"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.deleteDirectory("/some/nonexisting/path"))
        test.verify(!remoteOS.exists("/some/nonexisting/path"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.deleteDirectory("/some/nonexisting/path"))
    Test.verify(!remoteOS.exists("/some/nonexisting/path"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS deleteDirectory "/some/nonexisting/path"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [expr ![$remoteOS exists "/some/nonexisting/path"]] } result] } {
        test fail "RemoteSystem error" $result
    }
}

布尔 RemoteSystem.createDirectory(path)

createDirectory 方法可以用来在远程系统上创建目录。使用 path 参数指定远程系统上文件夹的路径。此方法仅在父目录已存在的情况下才会创建新的文件夹。如果您想要一次性创建多个目录,可以使用 createPath 方法 Boolean RemoteSystem.createPath(path)。如果文件夹无法创建,将抛出异常。

以下示例显示了如何使用 createDirectory 方法。如果您想要尝试示例,需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.createDirectory("/some/nonexisting/path"));
        test.verify(remoteOS.exists("/some/nonexisting/path"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->createDirectory("/some/nonexisting/path"));
        test::verify($remoteOS->exists("/some/nonexisting/path"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.createDirectory("/some/nonexisting/path"))
        test.verify(remoteOS.exists("/some/nonexisting/path"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.createDirectory("/some/nonexisting/path"))
    Test.verify(remoteOS.exists("/some/nonexisting/path"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS createDirectory "/some/nonexisting/path"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS exists "/some/nonexisting/path"] } result] } {
        test fail "RemoteSystem error" $result
    }
}

布尔 RemoteSystem.createPath(path)

createPath 方法可以用来在远程系统上创建目录。使用 path 参数指定远程系统上目录的路径。此方法将创建从指定路径缺少的所有文件夹。如果路径无法创建,将抛出异常。

以下示例显示了如何使用 createPath 方法。如果您想要尝试示例,需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.createPath("/some/nonexisting/path"));
        test.verify(remoteOS.exists("/some/nonexisting/path"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->createPath("/some/nonexisting/path"));
        test::verify($remoteOS->exists("/some/nonexisting/path"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.createPath("/some/nonexisting/path"))
        test.verify(remoteOS.exists("/some/nonexisting/path"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.createPath("/some/nonexisting/path"))
    Test.verify(remoteOS.exists("/some/nonexisting/path"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS createPath "/some/nonexisting/path"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS exists "/some/nonexisting/path"] } result] } {
        test fail "RemoteSystem error" $result
    }
}

布尔 RemoteSystem.rename(oldPath, newPath)

rename 方法可以用来在远程系统上重命名和移动文件和目录。使用 oldPath 参数指定远程系统上目录或文件的旧或当前路径。使用 newPath 参数指定远程系统上目录或文件的新或期望的路径。如果新路径已存在,则操作将失败。如果旧路径不存在或无法重命名文件或文件夹,将抛出异常。

以下示例展示了如何使用rename方法。如果您想尝试此示例,则需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.rename("/some/old/path", "/some/new/path"));
        test.verify(remoteOS.exists("/some/new/path"));
        test.verify(!remoteOS.exists("/some/old/path"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->rename("/some/old/path", "/some/new/path"));
        test::verify($remoteOS->exists("/some/new/path"));
        test::verify(!$remoteOS->exists("/some/old/path"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.rename("/some/old/path", "/some/new/path"))
        test.verify(remoteOS.exists("/some/new/path"))
        test.verify(!remoteOS.exists("/some/old/path"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.rename("/some/old/path", "/some/new/path"))
    Test.verify(remoteOS.exists("/some/new/path"))
    Test.verify(!remoteOS.exists("/some/old/path"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS rename "/some/old/path" "/some/new/path"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS exists "/some/new/path"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [expr ![$remoteOS exists "/some/old/path"]] } result] } {
        test fail "RemoteSystem error" $result
    }
}

Boolean RemoteSystem.createTextFile(path, content)

Boolean RemoteSystem.createTextFile(path, content, encoding)

createTextFile方法可以用于在远程系统上创建文本文件。参数path用于指定远程系统上要创建的文件的路径和文件名。参数content用于指定创建的文件内容,该内容为字符串。可选参数encoding可以用于指定文本文件的编码。默认编码为UTF-8,请参见上面可能的编码列表。如果提供的路径已存在,则此操作将失败(因此此函数不会覆盖现有文件)。如果文件已存在、编码不受支持或文件无法创建,将抛出异常。

以下示例展示了如何使用createTextFile方法。如果您想尝试此示例,则需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.createTextFile("/some/path/to/a/textfile", "Content..."));
        test.verify(remoteOS.exists("/some/path/to/a/textfile"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->createTextFile("/some/path/to/a/textfile", "Content..."));
        test::verify($remoteOS->exists("/some/path/to/a/textfile"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.createTextFile("/some/path/to/a/textfile", "Content..."))
        test.verify(remoteOS.exists("/some/path/to/a/textfile"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.createTextFile("/some/path/to/a/textfile", "Content..."))
    Test.verify(remoteOS.exists("/some/path/to/a/textfile"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS createTextFile "/some/path/to/a/textfile" "Content..."] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS exists "/some/path/to/a/textfile"] } result] } {
        test fail "RemoteSystem error" $result
    }
}

Boolean RemoteSystem.upload(localPath, remotePath)

upload方法可以用于将文件从本地系统(即运行者的系统)上传到远程系统(即运行的系统)。参数localPath用于指定本地系统上源文件的路径,而参数remotePath用于指定远程系统上文件的目标位置。如果提供的远程路径已存在,则此操作将失败(因此此函数不会覆盖现有文件)。此外,如果本地路径不存在或文件未正确传输,将抛出异常。

以下示例展示了如何使用upload方法。如果您想尝试此示例,则需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.upload("/some/local/path", "/some/remote/path"));
        test.verify(remoteOS.exists("/some/remote/path"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->upload("/some/local/path", "/some/remote/path"));
        test::verify($remoteOS->exists("/some/remote/path"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.upload("/some/local/path", "/some/remote/path"))
        test.verify(remoteOS.exists("/some/remote/path"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.upload("/some/local/path", "/some/remote/path"))
    Test.verify(remoteOS.exists("/some/remote/path"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS upload "/some/local/path" "/some/remote/path"] } result] } {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS exists "/some/remote/path"] } result] } {
        test fail "RemoteSystem error" $result
    }
}

Boolean RemoteSystem.download(remotePath, localPath)

download方法可以用于从远程系统(即服务器运行的系统)下载文件到本地系统(即运行者的系统)。参数remotePath用于指定远程系统上源文件的路径,而参数localPath用于指定本地系统上文件的目标位置。如果提供的本地路径已存在,则此操作将失败(因此此函数不会覆盖现有文件)。此外,如果远程路径不存在、无法创建本地文件或文件未正确传输,将抛出异常。

以下示例展示了如何使用download方法。如果您想尝试此示例,则需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.download("/some/remote/path", "/some/local/path"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->download("/some/remote/path", "/some/local/path"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.download("/some/remote/path", "/some/local/path"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.download("/some/remote/path", "/some/local/path"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS download "/some/remote/path" "/some/local/path"] } result] } {
        test fail "RemoteSystem error" $result
    }
}

Boolean RemoteSystem.copy(sourcePath, destinationPath)

可以使用 copy 方法来复制远程系统内的文件或文件夹。 sourcePath 参数用于指定远程系统上源文件或文件夹的路径,而 destinationPath 参数用于指定远程系统上文件或文件夹的目标位置。如果您要复制单个文件,目标路径可以是文件或文件夹。如果您要复制文件夹,目标路径必须是文件夹,否则会引发异常。如果在复制操作中涉及的一个文件已在目标位置存在(它不会覆盖现有文件),则此操作将失败。另外,如果任何文件无法正确复制,则会引发异常。

以下示例显示了如何使用 copy 方法。如果您想尝试该示例,您需要替换路径。

注意:根据您的设置,此测试可能会更改您的本地或远程系统上的文件或文件夹。

source(findFile('scripts', 'javascript/remotesystem.js'));

function main() {
    try {
        remoteOS = new RemoteSystem();
        test.verify(remoteOS.copy("/some/remote/path/a", "/some/remote/path/b"));
    } catch (e) {
        test.fail("RemoteSystem error", e.toString());
    };
}
use warnings;
use strict;
use Squish::RemoteSystem;

sub main {
    eval {
        my $remoteOS = Squish::RemoteSystem->new();
        test::verify($remoteOS->copy("/some/remote/path/a", "/some/remote/path/b"));
    } or do {
        test::fail("RemoteSystem error", $@);
    };
}
# -*- coding: utf-8 -*-
from remotesystem import RemoteSystem

def main():
    try:
        remoteOS = RemoteSystem()
        test.verify(remoteOS.copy("/some/remote/path/a", "/some/remote/path/b"))
    except Exception as e:
        test.fail("RemoteSystem error", str(e))
# encoding: UTF-8
require 'squish'
require "squish/remotesystem"
include Squish

def main
  begin
    remoteOS = RemoteSystem.new()
    Test.verify(remoteOS.copy("/some/remote/path/a", "/some/remote/path/b"))
  rescue Exception => e
    Test.fail("RemoteSystem error", e.to_s)
  end
end
package require squish::remotesystem

proc main {} {
    if {[catch {set remoteOS [::Squish::RemoteSystem new]} result]} {
        test fail "RemoteSystem error" $result
    }

    if { [catch { test verify [$remoteOS copy "/some/remote/path/a" "/some/remote/path/b"] } result] } {
        test fail "RemoteSystem error" $result
    }
}

布尔值 RemoteSystem.close()

close 方法可用于关闭从 RemoteSystem 实例到 squishserver 的连接。如果您想停止使用实例并显式清理其资源,请使用此方法。

用户界面类型

Squish 通过 UiTypes 命名空间(在命名空间有意义的语言中)提供了一种机制,通过它可以创建泛型类型的项。

DateTime 类型

UiTypes.DateTime 类型(在 Tcl 中是普通的 DateTime)能够存储日期和时间值。

DateTime UiTypes.DateTime()

DateTime UiTypes.DateTime(year, month, dayOfMonth)

DateTime UiTypes.DateTime(year, month, dayOfMonth, hour, minute, second)

此构造函数创建一个 DateTime 对象。如果没有给出参数,所有值都设置为 -1(即,DateTime 无效)。下面是如何创建一个有效的 DateTime 的方法

moonLanding = UiTypes.DateTime(1969, 7, 20)
var moonLanding = new UiTypes.DateTime(1969, 7, 20);
my $moonLanding = UiTypes::DateTime->new(1969, 7, 20);
moonLanding = UiTypes::DateTime.new(1969, 7, 20)
set moonLanding [construct DateTime 1969 7 20]

Squish 的 UiTypes 命名空间位于自动导入到测试脚本中的 Squish 命名空间内部——除了 Ruby 之外,Ruby 的脚本文件应该以 require 'squish' 语句开头。

DateTime 对象具有以下属性

int UiTypes.DateTime.year

此读写属性包含日期/时间的年份。

int UiTypes.DateTime.month

此读写属性包含日期/时间的月份(1-12)。

int UiTypes.DateTime.day

此读写属性包含日期/时间在该月的天数(1-31)。

int UiTypes.DateTime.hour

此读写属性包含日期/时间的小时(0-23)。

int UiTypes.DateTime.minute

此读写属性包含日期/时间的分钟(0-59)。

int UiTypes.DateTime.second

此读写属性包含日期/时间的秒数(0-59)。

UiTypes.ScreenPoint

表示屏幕上位置的点元素。此类型对象具有以下属性

整型 x

读/写属性,指定此点的水平坐标。

整型 y

读/写属性,指定此点的垂直坐标。

UiTypes.ScreenRectangle

表示屏幕位置和尺寸的矩形类型。

ScreenRectangle UiTypes.ScreenRectangle()

构造一个无效的 ScreenRectangle,其所有属性均设置为值 -1

ScreenRectangle UiTypes.ScreenRectangle(otherScreenRectangle)

构造 otherScreenRectangle 的副本。

ScreenRectangle UiTypes.ScreenRectangle(x, y, width, height)

使用给定的位置和大小构造一个 ScreenRectangle

someRect = UiTypes.ScreenRectangle(13, 27, 800, 600)
var someRect = new UiTypes.ScreenRectangle(13, 27, 800, 600);
my $someRect = UiTypes::ScreenRectangle->new(13, 27, 800, 600);
someRect = UiTypes::ScreenRectangle.new(13, 27, 800, 600)
set someRect [construct ScreenRectangle 13 27 800 600]

整型 x

矩形左边的 x 坐标或如对象无效则 -1。

整型 y

矩形顶边的 y 坐标或如对象无效则 -1。

整型 width

矩形的宽度或如对象无效则 -1。

整型 height

矩形的高度或如对象无效则 -1。

ScreenPoint center()

ScreenPoint 对象的形式返回矩形对象的中心。

杂项函数

String findFile(where, filename)

此函数返回给定 filename 的路径,或者在找不到文件时引发 LookupError 异常。

如果 where 参数是 "scripts"findFile 将在测试用例的 scripts 目录中查找 filename。如果该目录不包含该文件,则函数将尝试测试套件的 shared/scripts 目录。如果该目录也不包含文件,则函数将尝试 paths.ini 初始化文件 中的路径。如果仍然找不到,函数将尝试在定义了 SQUISH_SCRIPT_DIR 环境变量 的所有目录中查找。找到文件后,将返回文件名路径;否则将引发可捕获的 LookupError 异常。

如果 where 参数是 "testdata",则 findFile 将在测试用例的 testdata 目录中查找 filename。如果该目录不包含文件,则函数将尝试测试套件的 shared/testdata 目录,如果仍然找不到文件,则函数将尝试测试用例目录。找到文件后,将返回文件名路径;否则将引发可捕获的 LookupError 异常。

(另请参阅 source(filename) 函数和 测试数据函数。)

snooze(seconds)

此函数指示 Squish 暂停指定的小时数。参数 seconds 可以是整数或浮点数。实际睡眠时间将取决于当前的 snoozeFactor。除非您确实需要强制 Squish 睡眠,否则通常比使用 snooze 更稳健的是使用 Object waitForObject(objectOrName) 函数。

可以通过 squishide 来设置 snoozeFactor。点击 窗口 > 偏好设置 来调用 偏好设置对话框,然后点击 Squish 项目,接着点击 回放 项目,然后设置 Snooze Factor 的值。《snoozeFactor》也可以通过使用 squishrunner 的命令行选项来设置。请参见 squishrunner: 记录测试用例执行测试用例(高级)

source(filename)

按行读取和评估 filename 中的内容。与脚本语言的正常 "导入" 机制不同(例如 Python 的 import 或 Perl 的 use),这更像 C++ 中的 #include 指令,即语句将插入你的脚本在该位置。这是解析您自己的共享脚本文件的一种方法,而不是使用脚本语言的导入机制,这可能需要根据您的环境进行定制才能找到您的模块。

一个常见的用法是编写类似于 source(findFile("scripts", "common.js")) 的代码。这使用 String findFile(where, filename) 函数生成一个包含路径的文件名,然后评估该文件的脚本内容。这通常会导致额外的函数(甚至新的类和变量)成为执行此调用的测试脚本可用的。

Ruby 中,可以在函数或方法内部使用内置的 require 方法——例如 require findFile("scripts", "common.rb"))

有关信息,请参阅 创建和使用共享数据和共享脚本导入 Squish 资源对话框新建 Squish 测试脚本对话框

低级函数

nativeMouseClick(x, y, button)

此函数在当前活动的窗口上模拟原生鼠标点击。xy 参数是需要执行鼠标点击的屏幕坐标。button 参数是应使用的鼠标按钮,可以是 MouseButton.LeftButtonMouseButton.MiddleButtonMouseButton.RightButton 之一。

注意:理论上,对 nativeMouseClick 函数的调用可能会出错。例如,如果意外弹出覆盖目标窗口的窗口或控件,则鼠标点击将移到新活动的窗口或控件,而不是目标窗口。在实际情况中,这种情况非常罕见。

nativeType(keys)

此函数通过操作系统的功能模拟用户键盘输入,将按键发送到当前活动的窗口,即键盘焦点的窗口。在 Windows 中,这可用于与原生 Windows 消息框等交互。键盘输入将发送到具有键盘焦点的任何小部件。输入区分大小写,因此 nativeType("R")nativeType("r") 不同。

此函数还可以通过使用其名称并用尖括号(《<>》)括起来来模拟特殊键的输入,并且可以通过在每个键名之间使用一个 + 来模拟按键组合。以下是一些示例

nativeType("Hello");
nativeType("<Return>");
nativeType("<Alt+F4>");
nativeType("<Alt+Tab>");
nativeType("<Ctrl+c>");

这在 JavaScript、Perl、Python 和 Ruby 中都是有效的。

invoke nativeType "Hello"
invoke nativeType "<Return>"
invoke nativeType "<Alt+F4>"
invoke nativeType "<Alt+Tab>"
invoke nativeType "<Ctrl+c>"

nativeType 函数可以接受所有常见的字母数字字符(按文本直接编写),以及以下特殊键(必须在尖括号内括起):<Alt><Ctrl><Shift><Escape><Return><Space><Backspace><Tab><Pause><PageUp><PageDown><Home><End><Left><Right><Up><Down><Insert><Delete><Print><NumPad0><NumPad1><NumPad2><NumPad3><NumPad4><NumPad5><NumPad6><NumPad7><NumPad8><NumPad9><NumPadMultiply><NumPadAdd><NumPadSubtract><NumPadDivide><NumPadDecimal><MenuLeft><MenuRight><Win><WinLeft><WinRight><F1><F2><F3><F4><F5><F6><F7><F8><F9><F10><F11><F12><F13><F14><F15><F16><F17><F18><F19><F20><F21><F22><F23><F24><NumLock><ScrollLock><CapsLock> 以及 <Command>(仅限 macOS) .

通常,最好使用工具包特定的 type(objectOrName, text) 函数之一。

注意:理论上,使用 nativeType 函数输入的按键可能会出错。例如,如果 AUT 上意外弹出一个窗口,按键将不会输入到目标窗口,而是到了新激活的窗口。在实践中,这种情况非常罕见。

sendNativeEvent(windowName, sequence)

此函数将一系列低级别本地事件发送到名为 windowName 的窗口。当与另一个应用程序的窗口或使用外来工具包实现的控件交互时,此函数可能很有用。对于与标准应用程序控件交互,最好使用 Squish API 中的函数,例如 type(objectOrName, text) 函数。

以下是 JavaScript、Python、Perl 和 Ruby 中有效使用示例:

sendNativeEvent("Login", "username");

目前,唯一支持的事件类型是简单的按键。未来版本可能会添加对复杂按键和鼠标事件的支持。如果您对此有重要要求,请联系技术支持。

©2024 Qt 公司版权所有。此处包含的文档贡献是各自所有者的版权。
提供的文档根据 GNU 自由文档许可协议第 1.3版 许可,由自由软件基金会发布。
Qt 和相应的徽标是芬兰 Qt 公司及其全球其他国家的商标。所有其他商标均为其各自所有者的财产。