如何测试 Tk 应用程序
Squish 的 Tk 特定 API 允许您查找和查询对象、访问属性,以及在该应用程序 (AUT) 的解释器中评估任意 Tcl 代码。
此外,Tk 便捷 API 提供以执行常见 GUI 操作的函数,如点击按钮或选择菜单项。
如何测试 Tk 小部件 部分展示了各种示例,说明如何使用脚本 Tk API 访问和测试复杂 Tk 小部件。
Tk 对象名称(限定名称)
Squish 为 Tk 应用程序与其他工具包使用完全不同的对象命名方案。Tk 使用 限定名称 来识别对象,例如 myapp.myframe.mylabel。 Squish 利用 Tk 的现有命名方案并使用它来识别 Tk 测试中的对象。
限定对象名称类似于 myapp.frame1.okbutton
。点符号用作分隔符(在文件路径中类似于 /
或 \
),用于根据其在对象层次结构中的位置来识别特定的对象。应用程序的主窗口是层次结构的根,包含所有应用程序的顶级小部件,其中一些包含子小部件,以此类推。在上面的示例中,okbutton
是 frame1
的子代,而 frame1
又是应用程序主窗口 myapp
的子代。
如何查找和查询 Tk 对象
Object waitForObject(objectOrName) 函数返回具有给定限定对象名称的对象的引用。
要查找对象的名称,您可以使用 间谍工具 来访问应用程序。或者,您可以记录一个快速丢弃的测试,在该测试中与所有感兴趣的应用程序对象进行交互,以便将对象名称填充到 对象映射 中。
要获取对象的引用——然后可以查询以检查对象的属性,或者可以用来与对象互动——请使用 Object waitForObject(objectOrName) 函数。例如,在 Tcl 中,您可以使用如下代码:
set button [waitForObject "myapp.frame1.okbutton"]
如果 Object waitForObject(objectOrName) 无法找到指定的对象,或者如果在超时之前对象不可用(例如,如果它处于隐藏状态),则抛出一个脚本错误,该错误会停止脚本的执行。为了检查对象是否存在,并且在找到的情况下才与对象互动,请使用 Boolean object.exists(objectName) 函数。
例如,假设您想要像之前那样找到 okbutton
并点击它,但只想在它存在的情况下这么做。在 Tcl 中,您可以使用以下代码实现这一点:
if {[object exists "myapp.frame1.okbutton"]} { set button [waitForObject "myapp.frame1.okbutton"] invoke clickButton $button }
使用限定对象名称与 Object waitForObject(objectOrName) 函数意味着测试工程师可以查询和互动AUT对象层次结构中的所有对象。
如何访问 Tk 对象属性
使用 Tk 脚本 API,可以访问 Tk 几乎所有的小部件属性。
例如,如果您想要更改一个 entry
小部件中的文本,您可以这样做,在适当的限定对象名称和新文本替换适当的地方使用以下 Tcl 代码:
set entry [waitForObject "myapp.frame1.e1"] property set $entry text "New text" set text [property get $entry text] test log [toString $text]
前两行设置新文本;第三行创建一个新变量 text
,最后一行将 text
打印到 测试结果 视图中。
如何使用 tcleval
尽管 Squish 测试脚本可以访问 Tk 小部件属性,但这对于测试目的来说仍然不够,因为并非所有您想要查询的信息都可通过这些属性获取。幸运的是,Squish 提供了一个解决方案:函数 String tcleval(code)。此函数可以执行AUT范围内的任意Tcl代码。
注意:此功能仅适用于Tcl/Tk应用程序,而不适用于Perl/Tk。
例如,如果您想检索Tk text
小部件的内容,您无法通过小部件属性来做,因为文本无法作为属性获得。您可以代替调用 text
小部件的 get
函数,因为该函数返回给定索引之间的 text
小部件文本。所以要获取全部文本,使用索引 1.0 和 end
。下面是如何使用 tcleval
函数来对一个 text
小部件调用 get
的示例:
set text [invoke tcleval ".textfield get 1.0 end"]
完整的 tceval
参数作为一个字符串传递。".textfield" 是 text
小部件的名称(记住在纯Tcl/Tk中,".
" 是小部件层次的根)。
如何使用 Tk 便利 API
本节简要介绍 Squish 在 Tk 之上提供的脚本API,以使其轻松执行常见用户操作,例如单击按钮。完整API的详细信息请参阅 Tk 便利 API 部分,该部分包含在 工具参考手册 中。在这里,我们将只展示一些示例,以让用户了解API提供了什么,以及如何使用它。
invoke clickButton [waitForObject \ ":addressbook\\.tcl.dialog.buttonarea.ok"] invoke type [waitForObject ":addressbook\\.tcl.dialog.email"] "com" waitForObjectItem ":addressbook\\.tcl.#menuBar" "File" invoke activateItem ":addressbook\\.tcl.#menuBar" "File" waitForObjectItem ":addressbook\\.tcl.#menuBar.#file" "Open..." invoke activateItem ":addressbook\\.tcl.#menuBar.#file" "Open..."
在这里,我们点击一个按钮,在输入框小部件中输入一些文本,并调用 文件 > 打开 菜单项。这些是最常用的Tk便利函数,虽然API中还有更多。有关在AUT中测试各种Tk小部件的更多示例,请参阅 如何测试 Tk 小部件。
如何测试 Tk 小部件
本节说明了如何使用Tcl测试Tk应用程序——特别是测试一些标准Tk小部件。虽然只展示了几个小部件,但相同的原理和实践适用于所有Tk小部件,所以在本节结束时,您应该能够测试AUT中的任何小部件。
实现测试脚本最具挑战性的方面通常是创建测试验证。正如在教程:开始测试 Tk 应用程序的插入附加验证点章节中所示,这可以通过使用间谍软件及其点 & 点击界面来完成。但在某些情况下,直接在代码中实现验证点可能更方便——并且更灵活。
要测试和验证代码中的小部件及其属性或内容,首先您需要在测试脚本中访问小部件。要获取小部件的引用,可以使用Object waitForObject(objectOrName)函数。该函数找到给定名称的小部件,并返回其引用。为此,您需要知道您想测试的小部件的名称,您可以使用Spy工具获取名称,并将其添加到对象映射中(以便Squish记住它),然后将对象名称(最好是它的符号名称)复制到剪贴板,以便将其粘贴到我们的测试中。如果您需要收集大量小部件的名称,记录一个模拟测试可能更快、更简单,在手动编写的测试脚本中确保您访问了想要验证的所有小部件。这会使Squish将所有相关名称添加到对象映射中,然后您可以将其复制并粘贴到我们的代码中。
如何测试小部件状态
一个常见的需求是测试小部件的状态,特别是它是否启用或禁用。小部件的state
属性包含您想要的信息——以下是一些使用示例
set entry1 [waitForObject ":myapp.entry1"] test compare [property get $entry1 state] "normal" set entry2 [waitForObject ":myapp.entry2"] test compare [property get $entry2 state] "disabled"
此代码验证entry1
小部件是启用的,以及entry2
小部件是禁用的。
复选框和单选按钮
尽管验证标准Tk单选按钮或复选框是否选中是一个常见需求,但这两个小部件都没有方便的属性可以使用,因此您必须编写比预期的更多代码。
我们将首先验证某个单选按钮是否选中。首先,我们必须检索单选按钮的variable
和value
属性,然后我们必须评估这个变量以查看它是否等于值——如果是这样,则单选按钮是选中的。
set radiobutton [waitForObject ":myapp.radiobutton"] set variable [property get $radiobutton "variable"] set value [property get $radiobutton "value"] set actual_value [invoke tcleval "return \$$variable"] test compare $actual_value $value
首先,我们必须检索单选按钮的引用,然后我们检索我们感兴趣的这两个属性。接下来,我们使用String tcleval(code)函数评估变量以获取其实际值,最后我们将实际值与属性值进行比较,看看它们是否相同。
对于复选框,我们必须使用类似的方法,除了它们的相关属性是onvalue
和offvalue
。
set checkbutton [waitForObject ":myapp.checkbutton"] set variable [property get $checkbutton "variable"] set onvalue [property get $checkbutton "onvalue"] set actual_value [invoke tcleval "return \$$variable"] test compare $actual_value $onvalue
在此,我们检索复选框的引用,然后是复选框的variable
和onvalue
属性。就像我们对单选按钮所做的那样,我们评估变量以获取其实际值,并将其与onvalue
进行比较,看看它们是否相同。
要验证复选框未被选中,您可以检索offvalue
属性并将其与实际值进行比较。如果它们相同,则复选框未选中。
文本字段
可以使用getvalue
属性查询标准Tk输入小部件的内容。
set entry [waitForObject ":myapp.entry"] test compare [property get $entry getvalue] "Houston"
在此,我们检查输入是否包含文本“休斯顿”。
要查询Tk的多行文本小部件的内容,我们调用小部件的get
方法,为其提供要检查的文本的开始和结束索引。
set text [invoke tcleval ".textfield get 1.0 end"] test compare $text "line 1\nline 2"
我们不是检索多行文本小部件的引用,而是使用 String tcleval(code) 函数来执行小部件的 get
方法,传入跨整个内容的索引。这样返回小部件的所有文本。然后我们检查文本是否正好包含两行(文本为“行 1”和“行 2”)。
Squish 不仅限于 Tk 的标准小部件——例如,我们可以测试 BWidget Entry 小部件。
set bentry [waitForObject ":myapp.bentry"] test compare [property get $entry text] "Apollo"
在这里,我们使用 BWidget 的 text
属性获取其文本,并将其与文本 "Apollo" 进行比较。
列表框
一个常见的要求是检查 Tk 列表框活动的文本项。这可以通过列表框的 get
方法轻松完成。
set active [invoke tcleval ".listbox get active"] test compare $active "Gemini"
与多行文本小部件类似,我们不是检索列表框的引用,而是使用 String tcleval(code) 函数来执行具有参数 active
的列表框 get
方法,以返回列表框活动项的文本。然后我们像通常一样比较文本,在本例中与文本 "Gemini" 进行比较。
iwidget Radiobox
iwidget Radiobox 与标准 Tk 单选按钮的不同之处在于,它有一个 getvalue
属性,该属性保存当前选中的单选按钮的文本。
set radiobox [waitForObject ":myapp.rbox"] test compare [property get $radiobox getvalue] "Mercury"
如果有 "Mercury"、"Venus" 和 "Mars" 这样的单选按钮,我们可以通过检索 Radiobox,并将其 getvalue
属性的值与其应该选中的单选按钮的文本进行比较,来验证 "Mercury" 单选按钮是否已选中。
©2024 The Qt Company Ltd. 文档贡献的版权属于各自的所有者。
提供的文档根据由自由软件基金会发布的 GNU 自由文档许可证 1.3 版本 的条款授权。
Qt 和相关标志是芬兰及其在世界其他地区的 The Qt Company Ltd. 的商标。所有其他商标均为各自所有者的财产。