如何模拟QML组件

How to mock a QML component

本文关键字:QML 组件 模拟 何模拟      更新时间:2023-10-16

实际上,我正试图在嵌入C++对象的QML组件上运行一些测试。不幸的是,我在执行测试时遇到了一些错误。QML文件无法识别C++对象。这也是有意义的,因为C++对象是在main.cpp文件中设置的。

我的问题是:如何模拟上下文属性来执行QML测试?或者其他人说,如何混合Qt/QML代码进行单元测试?

我在没有编译任何C++代码的情况下就完成了QML测试。

在我的例子中,我有一个C++对象控制器,它有一个名为left_motor的属性,这是另一个对象,它有speed属性。

请注意speed是可读的,但不是可写的。任何更新都将通过插槽进行。在QML中,它看起来像这样:controller.left_motor.onGuiSpeedChanged(速度)

我能够在QML中使用Item组件、属性和一些javascript来模拟这一点。

Item {                      // mock of controller
    id: controller
    property alias left_motor: left_motor
    Item {
        id: left_motor
        property int speed: 0
        function onGuiSpeedChanged(arg) {
            speed = arg
        }
    }
}
property alias controller: controller

现在调用controller.left_motor.onGuiSpeedChanged(速度)像以前一样解析,但连接到mock函数。我甚至可以读回speed属性来知道呼叫发生了。

这是我的测试函数(我正在测试的代码是第1页的一部分):

function test_set_speed() {
    console.log("controller.left_motor.speed: " + controller.left_motor.speed)
    var got = page1.set_left_speed(250)
    compare(got, 250, "set_left_speed() return incorrect")
    console.log("controller.left_motor.speed: " + controller.left_motor.speed)
}

请注意,使用插槽而不是可写属性非常重要。对槽的调用看起来就像一个函数调用,可以被嘲笑为这样。我想不出一个方法来模拟一个地产写作。

我开始尝试可写属性,因为这是绑定C++和QML的文档中的第一件事。它按预期连接QML和C++,但无法进行模拟测试。

据我所知,你们和我遇到了同样的问题。不久前,我写了这个mock:https://bitbucket.org/troyane/qml-cpp-template(您可以出于自己的目的免费使用该代码)。

看看main.cpp,你可以看到两种做事的方法:

// 1 case:
// Register type and create object at QML side
qmlRegisterType<CppClass>("CppClassModule", 1, 0, "CppClass");
QQmlApplicationEngine engine(QUrl("qrc:///qml/main.qml"));
qDebug() << "Qt version: " << qVersion();
// 2 case:
// Create object here and "move it up" to QML side
// engine.rootContext()->setContextProperty("cppClass", new CppClass);

祝你好运!

最好的解决方案是将C++类型移动到QML插件中,以便QML测试可以导入它们。这个插件需要在运行时可用于测试,这意味着确保可以在导入路径中找到它们。如果遇到找不到插件的任何问题,可以将QML_IMPORT_TRACE环境变量设置为1,以提供一些有用的调试输出。

然而,即使是仅QML的测试用例也需要一些C++来设置它们。

要在运行任何QML测试之前执行C++代码,可以使用QUICK_TEST_MAIN_WITH_SETUP宏:

// src_qmltest_qquicktest.cpp
#include <QtQuickTest>
#include <QQmlEngine>
#include <QQmlContext>
class Setup : public QObject
{
    Q_OBJECT
public:
    Setup() {}
public slots:
    void qmlEngineAvailable(QQmlEngine *engine)
    {
        engine->rootContext()->setContextProperty("myContextProperty", QVariant(true));
    }
};
QUICK_TEST_MAIN_WITH_SETUP(mytest, Setup)
#include "src_qmltest_qquicktest.moc"

最灵活、最强大的选择是用C++编写测试并从中加载QML。