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

Unit testing 无法在同一测试程序中对Gtk应用程序多次运行单元测试,unit-testing,gtk,dbus,vala,Unit Testing,Gtk,Dbus,Vala,我正在Vala中编写一系列关于Gtk应用程序的单元测试,我在测试程序中多次实例化和运行Gtk应用程序时遇到了一个问题 应用程序第一次实例化并运行时,一切正常,但随后出现故障时,会显示以下消息: Failed to register: An object is already exported for the interface org.gtk.Application at /org/valarade/testtools 根据我对Gtk应用程序生命周期的理解,该应用程序已在本地DBus会话总线上

我正在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应用程序以避免此问题?

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

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

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

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

我对DBus也有同样的怀疑,并且正在编写一些异步测试代码,但是-呃-您的解决方案没有那么复杂。我曾考虑在应用程序ID中添加一个唯一标识符,但我认为这可能会影响资源的自动加载,但显然不会。我已经将应用程序分解为最小的单元,但我仍然需要测试一些UI功能,为此我创建了应用程序和应用程序窗口的模拟版本,以便它们运行得非常快。非常感谢,感谢您简洁、周到、准确的回复!