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”信号报告结果,传递三个字符串属性 infoidsummary

结果的模拟受 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。