Как смоделировать компонент 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 .