无法 运行 在同一测试程序中对 Gtk 应用程序进行多次单元测试

Unable to run unit tests on Gtk Application more than once in same test program

我正在 Vala 中的 Gtk 应用程序上编写一系列单元测试,我在测试程序中多次实例化和 运行ning Gtk 应用程序时遇到了问题。

第一次实例化应用程序时 运行 一切都按预期工作,但随后失败并显示消息:

Failed to register: An object is already exported for the interface org.gtk.Application at /org/valarade/testtools

根据我对 Gtk 应用程序生命周期的理解,该应用程序已在本地 DBus 会话总线上将自己注册为单个实例应用程序,从而防止其他实例成为 运行。

使用 d-feet 应用程序,我能够看到该应用程序在 运行s 第一次在本地总线上注册自己,并且当 运行ning 测试功能时它似乎自行注销终止。当后续测试函数实例化并运行s一个新实例时,没有任何痕迹,但仍然返回上述错误。

我已经尝试了几件事,包括确保销毁应用程序引用的所有对象以及测试函数之间的应用程序对象本身。我试过在 class 析构函数中调用 connection.close_sync 并将 register_session 设置为 false 但都没有任何效果。

测试程序的示例代码

static void main (string[] args) {

    Gtk.test_init (ref args);

    TestSuite.get_root ().add_suite (new FileLoaderPluginTests ().get_suite ());

    Idle.add (() => {
        Test.run ();
        Gtk.main_quit ();
        return true;
    });

    Gtk.main ();
}

和测试套件的代码

public FileLoaderPluginTests () {
    add_test ("method on_open_activate ()", file_loader_on_open_activate);
    add_test ("method on_open_response_ok ()", file_loader_on_open_response_ok);
}


public void file_loader_on_open_activate () {
    var app = new MockApplication ();

    app.activate.connect ((a) => {
        var action = app.shell.lookup_action ("file_open");
        action.activate (null);
        app.quit();
    });

    app.run ();
    app = null;

}

public void file_loader_on_open_response_ok () {
    var app = new MockApplication ();

    app.activate.connect ((a) => {
        var action = app.shell.lookup_action ("file_open");
        action.activate (null);
        app.quit();
    });

    app.run ();
}

在我看来,DBus 会话注册是针对 运行ning 测试程序而不是应用程序 class 本身的。我已经浏览了现有的宝贵的小文档,但我似乎无法找到任何可以让我在每次测试后注销应用程序的内容。

虽然我可以通过为每个单元测试设置不同的测试程序来解决这个问题,但这似乎是很多不必要的重复。理想情况下,我希望为整个应用程序中的每个逻辑单元编写一个测试程序,而这样一来,当有任何重要的代码覆盖时,它可能会产生相当多的结果。

我的问题是 - 有什么方法可以在测试程序中多次创建、运行 和销毁 Gtk 应用程序?或者,是否有更好的方法来测试可以避免此问题的 Gtk 应用程序?

由于 DBus 通信是异步的,我猜想在下一次测试启动下一个应用程序时,您的应用程序名称还没有从总线上注销。

测试应用程序的一些技巧classes:

  • 您可以在创建每个应用时为应用ID附加一个唯一标识(例如PID加上系统时钟时间);这样,应用程序将永远不会相互冲突。如果您可能 运行 并行测试程序(这些天 Automake 默认情况下会这样做。)
  • ,那么这是特别可取的。
  • 如果可能,请将您的逻辑放在应用程序之外 class 并放在较小的单元中,这样您就不必为每个测试都创建一个应用程序实例。在每个测试中启动和关闭应用程序实例会使它们非常慢。

PS。我相信 Test.run() 已经为你运行了一个主循环,所以你不需要在空闲函数中启动测试套件。