Как смоделировать компонент QML

На самом деле я пытаюсь запустить какой-то тест для компонента QML, который встраивает объекты C++. К сожалению, я получаю некоторые ошибки при выполнении моих тестов. Объекты C++ не распознаются файлом QML. Это также имеет смысл, поскольку объекты C++ устанавливаются в файле main.cpp.

Мой вопрос: как я могу макет свойства контекста для выполнения тестов QML? Или другой сказал, как я могу сделать юнит-тест со смешиванием кода Qt / QML?

3 ответа

Я получил тесты QML для меня без компиляции в любом коде C++.

В моем случае у меня есть объектный контроллер C++ со свойством left_motor, которое является другим объектом и имеет свойство speed.

Обратите внимание, что скорость читаема, но не доступна для записи. Любые обновления будут происходить через слоты. В QML это выглядит так: controller.left_motor.onGuiSpeedChanged(speed)

Я смог смоделировать это в 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 (speed) разрешаются, как и раньше, но подключаются к фиктивной функции. Я даже могу прочитать обратно свойство speed, чтобы узнать, что звонок произошел.

Вот моя тестовая функция (код, который я тестирую, является частью page1):

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++, как и ожидалось, но не может быть смоделирован для тестирования.

Как я понимаю, вы правы, у вас та же проблема, что и у меня. Некоторое время назад я написал этот макет: 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++ для их настройки .

Чтобы выполнить код C++ перед выполнением любого из тестов QML,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 .

Другие вопросы по тегам