0

I am struggling with adding QML unit test to the Qt Quick Application generated in Qt Creator.

I have generated a Qt Quick Application in Qt Creator with following CMakeLists.txt (Qt 6.6)

cmake_minimum_required(VERSION 3.16)

project(QuickApp VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)

qt_standard_project_setup(REQUIRES 6.5)

qt_add_executable(appQuickApp
    main.cpp
)

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

# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
# If you are developing for iOS or macOS you should consider setting an
# explicit, fixed bundle identifier manually though.
set_target_properties(appQuickApp PROPERTIES
#    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appQuickApp
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

target_link_libraries(appQuickApp
    PRIVATE Qt6::Quick
)

include(GNUInstallDirs)
install(TARGETS appQuickApp
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

I added the following:

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
)
//tst_main.cpp
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(QuickAppTest)
//tst_main.qml
import QtQuick
import QtTest
import QuickApp

Main {
  width: 400
  height: 400

  TestCase {
    name: "MainTest"
    when: windowShown

    function test_show() {
      wait(1000000)
    }
  }
}

When trying to run appQuickAppTest target from Qt Creator, it fails to import QuickApp module

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

Here the test executable appQuickAppTest manages to find QuickApp module location and it's qmldir (autogenerated, found in the build folder), but in the qmldir the path is specified using QRC (3rd line with prefer statement). When I manually remove this line, I can run tests!

module QuickApp
typeinfo appQuickApp.qmltypes
prefer :/qt/qml/QuickApp/
Main 1.0 Main.qml

My guess is that appQuickAppTest tries to load Main.qml from resources, but fails, since resources are embedded in the different executable inside QuickApp.app.

I think the problem is that QML module and executable is a single target. See here: Executable as a QML module

https://doc.qt.io/qt-6/qt-add-qml-module.html

But maybe there is still a way to make it work somehow? Is there an easier way to add QML unit tests to the project generated by Qt Creator?

1
  • As I understand it, TestCase is supposed to be the top-level object in the test file. Don't embed it in something else. Commented Jun 27 at 23:07

1 Answer 1

0

I put the tests in a subdirectory under the application...so e.g. AppName/test/tst_tests.qml

Then the tests get their own CMakeLists.txt. Main parts are:

...
// include the application parts
include_directories(../../AppName)

// collect test files and create the test app
file(GLOB QML_SOURCES RELATIV ${CMAKE_CURRENT_SOURCE_DIR} tst_*.qml)
source_group("Test Files" FILES ${QML_SOURCES})
add_executable(AppNameTests main.cpp
           setup.cpp setup.h ${QML_SOURCES})

// link the app
target_link_libraries(AppNameTests
                  PRIVATE Qt${QT_VERSION_MAJOR}::QuickTest
                  PRIVATE Qt${QT_VERSION_MAJOR}::Qml
                  PRIVATE Qt6::Quick
                  PRIVATE Qt6::QuickControls2
                  PRIVATE AppName)

...

In the main app, you include this directory:

...

set(MY_UNITTESTS TRUE)
enable_testing()

...

if(${MY_UNITTESTS})
    add_subdirectory(tests/)    
endif()

...

In the end after building you have an executable for the tests.

Sign up to request clarification or add additional context in comments.

6 Comments

Can you please share parts of the main app CMakeLists.txt? I am interested to see if you have a single target for executable and qml module or you have different targets?
with add_subdirectory(tests/) in the main app you make the test CMakeLists.txt part of your main app. If you build the main app, the tests are build as well. There is no separate target in the main app for the tests
I once made a test app where I tried many QML stuff. It also includes an example for QML tests: gitlab.com/basic53/DemoApp
I saw your test app previously, it was useful! I wonder however if it is possible to make a simpler version, with project generated from Qt Creator and just adding some unit tests. Do you use any QML types from your AppName in AppNameTests?
Adding just some testcases will work as well. Maybe you just have to link your main app to your test app in your example in the question.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.