You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Qt Creator生成的QML模块可执行程序添加QML单元测试

解决Qt Quick应用QML单元测试中模块导入失败问题

问题场景

基于Qt 6.6 + CMake构建的Quick应用,添加QML单元测试时出现QuickApp模块导入失败,报错信息如下:

QWARN  : QuickAppTest::tst_main::compile() 
  /Users/qwqqqw/dev/QuickApp/tst_main.qml produced 2 error(s):
    /Users/qwqqqw/dev/QuickApp/tst_main.qml:5,1: Type Main unavailable
    qrc:/qt/qml/QuickApp/Main.qml: No such file or directory
  Working directory: /Users/qwqqqw/dev/build-QuickApp-Qt_6_6_1_for_macOS-Debug
  Import paths:
    '/Users/qwqqqw/dev/build-QuickApp-Qt_6_6_1_for_macOS-Debug'
    'qrc:/qt-project.org/imports'
    'qrc:/qt/qml'
    '/Users/qwqqqw/dev/Qt/6.6.1/macos/qml'
  Plugin paths:
    '.'

FAIL!  : QuickAppTest::tst_main::compile() Type Main unavailable

手动删除构建目录自动生成的qmldir文件中的prefer :/qt/qml/QuickApp/语句后,测试可正常运行。

原项目CMakeLists核心代码:

qt_add_executable(appQuickApp
    main.cpp
)

qt_add_qml_module(appQuickApp
    URI QuickApp
    VERSION 1.0
    QML_FILES Main.qml
)

测试相关代码:

add_executable(appQuickAppTest
  tst_main.cpp
  tst_main.qml
)
target_compile_definitions(appQuickAppTest PRIVATE
  -DQUICK_TEST_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
)
target_link_libraries(appQuickAppTest
  PRIVATE Qt6::QuickTest Qt6::Quick
)

原因分析

原项目中qt_add_qml_module将QML模块直接绑定到主可执行文件appQuickApp,QML文件被嵌入到主程序的资源包中。自动生成的qmldir会添加prefer :/qt/qml/QuickApp/语句,让QML引擎优先从资源路径加载模块,但测试程序appQuickAppTest无法访问主程序的资源,因此找不到Main.qml。

解决方法

方案1:将QML模块改为独立库模块

把QML模块从主可执行文件分离为单独的库目标,使主程序和测试程序都能链接该库共享模块:

# 替换原绑定到appQuickApp的qml模块,创建独立QML库
qt_add_qml_module(QuickApp
    URI QuickApp
    VERSION 1.0
    QML_FILES Main.qml
    TYPE STATIC # 也可选择SHARED,按需调整
)

# 主程序链接独立QML库
target_link_libraries(appQuickApp
    PRIVATE Qt6::Quick QuickApp
)

# 测试程序同样链接该库
target_link_libraries(appQuickAppTest
    PRIVATE Qt6::QuickTest Qt6::Quick QuickApp
)

此方案下生成的qmldir不会指向资源路径,测试程序可正常加载模块。

方案2:禁用QML模块的资源优先加载

在原qt_add_qml_module中添加NO_RESOURCE_PREFIX选项,避免生成资源优先的qmldir:

qt_add_qml_module(appQuickApp
    URI QuickApp
    VERSION 1.0
    QML_FILES Main.qml
    NO_RESOURCE_PREFIX
)

或者通过设置目标属性实现:

set_target_properties(appQuickApp PROPERTIES
    QT_QML_MODULE_PREFER_DISK_PATH ON
)

两种方式都会让qmldir不再包含prefer语句,测试程序可直接从磁盘路径加载QML文件。

方案3:为测试程序添加QML导入路径

无需修改原项目结构,通过设置测试程序的QML导入路径指向原项目QML模块的磁盘位置:

# 在CMake中添加编译定义指定导入路径
target_compile_definitions(appQuickAppTest PRIVATE
    -DQUICK_TEST_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
    -DQML_IMPORT_PATH="${CMAKE_BINARY_DIR}/qml/QuickApp"
)

# 或者添加运行时环境变量设置导入路径
add_custom_command(TARGET appQuickAppTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E env "QML2_IMPORT_PATH=${CMAKE_BINARY_DIR}/qml/QuickApp" $<TARGET_FILE:appQuickAppTest>
)

也可在测试的C++代码中手动设置导入路径:

#include <QtQuickTest/quicktest.h>
#include <QQmlEngine>

int main(int argc, char *argv[]) {
    QQmlEngine::setImportPathList({
        QStringLiteral("%1/qml/QuickApp").arg(CMAKE_BINARY_DIR),
        QQmlEngine::importPathList()
    });
    return quick_test_main(argc, argv, "QuickAppTest", QStringLiteral(QUICK_TEST_SOURCE_DIR));
}

内容的提问来源于stack exchange,提问作者psyched

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 04:15:42