openSUSE:WebYaST 测试/PackageKit
编写涉及 PackageKit 的测试
遵循 不要访问系统 约定,以下是如何在编写 WebYaST 测试时模拟 PackageKit 调用。
关于 PackageKit
PackageKit 是一个 D-Bus 服务,提供软件包和仓库管理。借助 PolicyKit,它允许非特权用户安装软件和更新。
PackageKit 提供两个接口,即“org.freedesktop.PackageKit”用于同步操作,而“org.freedesktop.PackageKit.Transaction”用于异步操作。前者用于 PackageKit 内部函数,后者将请求传递给 PackageKit 后端并通过信号报告回结果。
模拟 PackageKit
模拟同步调用很简单,相同的规则 适用于标准的 D-Bus 服务。
棘手的部分是异步接口。它使用 D-Bus 信号机制 来获取结果。有 正常(取决于函数)、错误 和 完成 信号需要处理。
信号具有一个名称(标识信号)和一个签名。后者描述了信号属性及其类型。
一个典型的信号将是“Package”,具有 'info'、'id' 和 'summary' 属性。
在模拟 PackageKit 函数时,必须知道(并模拟)该函数本身,包括其签名和报告信号。
使用 PackageKit 进行测试
对于涉及 PackageKit 的测试,软件 webservice 插件在其 test/ 目录下提供了一个 packagekit_stub.rb 辅助文件。(您不应该在除此插件之外的任何地方需要 PackageKit!)
在包含 test_helper 后,添加
require File.join(File.dirname(__FILE__), "..", "packagekit_stub")
到您的测试文件中。
这允许您在测试的 'setup' 函数中创建一个 PackageKit stub 对象
@pk_stub = PackageKitStub.new
然后使用以下命令创建事务接口和代理 stub
@transaction, @packagekit = PackageKit.connect
模拟特定函数
如上所述,您需要知道该函数及其结果信号。由于其异步特性,事务的函数模拟稍微复杂一些,因为它需要将函数调用与结果信号处理程序分开。
因此,我们需要 模拟调用的函数 和 模拟结果信号。
该函数
例如,我们以 'SearchName' 为例。
搜索名称接受两个传入的字符串参数,即要搜索的仓库 (where) 和软件包名称 (what)。
m = DBus::Method.new("SearchName")
m.from_prototype("in repos:s, in name:s")
现在需要将该函数添加到事务接口
transaction.methods[m.name] = m
并且我们需要一个虚拟实现
class <<transaction
def SearchName repos, name
# dummy !
end
end
结果信号
'SearchName' 通过“Package”信号报告结果,传递三个字符串属性 info、id 和 summary。
结果的模拟受 PackageKitResultSet 类支持。通过传递信号名称及其签名来创建实例。
rset = PackageKitResultSet.new "Package", :info => :s, :id => :s, :summary => :s
(由于 Ruby 中可以在不使用 {} 括起来的情况下传递尾随 Hash,因此签名看起来像多个参数)
通过 '<<' 添加结果信号,将信号属性分组在数组中
rset << ["info1", "id1", "summary1"]
字符串类型属性也可以指定为符号
rset << [:info2, :id2, :summary2]
现在我们将此 PackageKitResultSet 实例传递给 stub 对象。
@pk_stub.result = rset
(!!! 此赋值会在 D-Bus 上创建和排队信号。下一次事务调用将收到这些信号。)
调用模拟函数
一旦模拟了函数和结果信号,实际的函数调用与真实调用没有区别(在使用 WebYaST 的 PackageKit 类时)
对于上面的 'SearchName' 示例,操作如下
PackageKit.transact( "SearchName", ["installed;~devel", "yast2"], "Package") do |info,id,summary|
... do something with the result ...
end
在这里,我们通过事务接口调用 'SearchName',传递 ["installed;~devel", "yast2"] 并侦听“Package”信号。每个“Package”信号预计都具有三个属性,这些属性在 Ruby 块中可用作 info、id 和 summary。