【问题标题】:Unable to run unit tests on Gtk Application more than once in same test program无法在同一测试程序中多次在 Gtk 应用程序上运行单元测试
【发布时间】:2015-09-04 00:10:35
【问题描述】:

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

第一次实例化应用程序并运行一切正常,但随后失败并显示消息:

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

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

使用 d-feet 应用程序,我可以看到应用程序在本地总线上首次运行时自行注册,并且在运行的测试功能终止时似乎自行取消注册。后面的测试函数实例化并运行一个新实例时没有任何痕迹,但仍然返回上述错误。

我已经尝试了几件事,包括确保应用程序引用的所有对象以及测试函数之间的应用程序对象本身都被销毁。我尝试在类析构函数中调用 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 会话注册是针对正在运行的测试程序的生命周期,而不是应用程序类本身。我已经浏览了那里宝贵的小文档,但我似乎无法在每次测试后取消注册应用程序的任何内容。

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

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

【问题讨论】:

    标签: unit-testing gtk dbus vala


    【解决方案1】:

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

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

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

    PS。我相信Test.run() 已经为您运行了一个主循环,因此您无需在空闲函数中启动测试套件。

    【讨论】:

    • 我对 DBus 有同样的怀疑,并且正在编写一些异步测试代码,但是 - 呃 - 你的解决方案不那么复杂。我曾考虑向应用程序 ID 添加一个唯一标识符,但认为它可能会干扰资源的自动加载,但显然不是。我已经将应用程序分解成最小的单元,但我仍然需要测试一些 UI 功能,为此我创建了 Application 和 ApplicationWindow 的 Mock 版本,因此它们运行得非常快。非常感谢,感谢您简洁、周到和准确的回复!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 2016-04-25
    • 1970-01-01
    • 2016-04-05
    • 2010-09-11
    • 1970-01-01
    相关资源
    最近更新 更多