Qt插槽测试

时间:2014-08-21 16:19:42

标签: c++ qt testing signals-slots

我正在为Qt5 GUI应用程序编写一些测试用例。我使用QObject::findChild检查元素是否存在,QSignalSpy检查是否使用正确的参数调用其信号。现在我想检查信号是否连接到正确的插槽,但我不知道如何做到这一点。我本以为这是一个相当标准的事情,但我无法在网上找到任何相关信息。

我在附录中放了一个小的演示应用程序来解释我想要的东西。它仅包含主窗口中的滑块和找到并更改滑块的测试用例。我想继续测试w.doSomething(10)是否被调用,我想检查slider->valueChanged(10)是否是来电者。

我基本上看到了三种可能的方式:

  1. 使用我尚未找到的标准Qt测试工具/最佳实践。 (任何提示都表示赞赏。)

  2. 找到Qt将连接sender->*signal存储到receiver->*slot的表,并验证(略微滥用语法)

    sender == slider && signal == &QSlider::valueChanged;
    receiver == &w && slot == &MainWindow::doSomething;
    
  3. MainWindow::doSomething(int)编写一个包装内容:

    void doSomething(int value) {
        slotCallTable << this << "MainWindow::doSomething(int)" << value;
        doSomething_nowReally(value);
    }
    

    其中slotCallTable记录了我希望在Test::test()中以某种方式验证的呼叫。在那里,我想检查接收器是否是正确的对象。但我认为我无法以这种方式验证发件人(不会是一个大问题)。

  4. 任何人都可以告诉我,如果(1)存在,(2)是否可能/合理,或者是否有人已经做过与(3)类似的事情,我不必从零开始?

    请注意,我有测试应用程序的代码但我无法手动修改它,因为测试必须是自动重现的,并且测试代码不会进入主开发代码库。但是,只要它们(可靠地)可重复,代码的可编程更改就可以了。

    感谢您阅读所有长篇文章,非常感谢您,如果您能(也做)也回答我的一些问题。

    干杯
    IMIX

    附录(工作示例):

    // window.h:

    #include <QObject>
    #include <QMainWindow>
    #include <QSlider>
    
    class MainWindow : public QMainWindow {
        Q_OBJECT
    
    private:
        QSlider * slider;
    
    private slots:
        void doSomething(int value) {}
    
    public:
        MainWindow(QWidget * parent = nullptr) : QMainWindow(parent) {
            slider = new QSlider(Qt::Orientation::Horizontal, this);
            slider->setObjectName("slider");
            QObject::connect(slider, SIGNAL(valueChanged(int)),
                             this, SLOT(doSomething(int)));
            this->show();
        }
    
        ~MainWindow() { delete slider; }
    };
    

    // test.h:

    #include <QtTest>
    #include "window.h"
    
    class Test : public QObject {
        Q_OBJECT
    
    private:
        MainWindow w;
    
    private slots:
        void test() {
            QSlider * slider = w.findChild<QSlider *>("slider");
            QVERIFY(slider != nullptr); // slider exists
    
            QSignalSpy spy(slider, SIGNAL(valueChanged(int)));
            QCOMPARE(spy.isValid(), true); // signal exists
                // note: of course it exists here, but this
                //       would be a custom signal in real
    
            slider->setValue(10); // fire some signal
    
            QCOMPARE(spy.count(), 1);                    // fired exactly once
            QCOMPARE(spy.takeFirst().at(0).toInt(), 10); // with right arguments
    
            QVERIFY("how to test right slot was triggered ???" && false);
        }
    };
    

    // main.cc:

    #include "test.h"
    QTEST_MAIN(Test)
    

1 个答案:

答案 0 :(得分:0)

如果您想对连接进行单元测试,可以使用connect()Qt::UniqueConnection作为最后一个参数。

将测试行更改为:

QVERIFY( false == QObject::connect(slider, SIGNAL(valueChanged(int)), &w, SLOT(doSomething(int)), Qt::UniqueConnection)  );

如果连接不存在,则connect()会返回true

但是,请注意不可能检查多个连接(多次创建相同的连接)。