2

The QtQuickTest docs don't make it clear how to refer to other components, run tests on them, etc.

It is relatively simple to write a tst_foo.qml, define a GUI object and a TestCase inside it that runs functions called test_* that checks aspects of your GUI object, but that is not a real-world situation. You would have your components to test in files that are not called tst_*. So my questions are:

  • The tester automatically runs all QML files called tst_*.qml. This implies that there are separate qml file with unit tests. But so far, I have only been able to do what this person does: rename the QML object you want to test to tst_foo.qml and define a TestCase in it. So the subsequent questions are:
  • Are you supposed to define a TestCase inside the GUI element and call it from a tst_foo.qml file? If so, how?
  • Or are you supposed to define a TestCase inside tst_foo.qml that refers to your GUI component? If so, how?

Another issue is that the QML loader for the unit test seems to use QQuickView, so it can only load items derived from QQuickItem. So how do you test an ApplicationWindow? In this case, renaming your QML file to tst_mainApp.qml doesn't even work: "QQuickView only supports loading of root objects that derive from QQuickItem."

Community
  • 1
  • 1
Halfgaar
  • 732
  • 2
  • 7
  • 32

1 Answers1

4

Are you supposed to define a TestCase inside the GUI element and call it from a tst_foo.qml file? If so, how?

No, definitely not.

Or are you supposed to define a TestCase inside tst_foo.qml that refers to your GUI component? If so, how?

It depends on where the GUI object is. If it has its own import, you can use the -imports argument to the test executable, as documented here. You can also use the IMPORTPATH qmake variable in your test's .pro file, as mentioned there. Your test might look like this:

import QtQuick 2.6
import QtTest 1.0

import MyImport 1.0

TestCase {
    id: testCase
    name: "Untitled"
    width: 200
    height: 200
    when: windowShown

    Component {
        id: myItemComponent

        MyItem {
            // ...
        }
    }

    function test_stuff() {
        var myItem = myItemComponent.createObject(testCase);
        verify(myItem);

        // test myItem

        myItem.destroy();
    }
}

This works fine if you want to test a custom item like a button that you wrote. This is how most of Qt Quick Controls' tests work, for example.

However, if you want to test an application in the same manner as a user would interact with it, you have two options (that I know of):

  1. Use a testing tool like Squish. I haven't used this, but in terms of getting as close as possible to user interaction with an application, it would be hard to beat. It works by recording input from the developer, which is then replayed "on" your application whenever the tests are run.

  2. In my latest project, I decided to try testing the exact same QML used in the application. For this, you need to write your test in C++, and the C++/QML for the application must be built twice: once if you're building the application, once if you're building the test. It works quite well, but my application is not that large, so it doesn't take long to build.

The second option is probably more powerful, as you have a lot of flexibility when writing tests in C++, but it requires a bit more knowledge of Qt.

Another issue is that the QML loader for the unit test seems to use QQuickView, so it can only load items derived from QQuickItem. So how do you test an ApplicationWindow?

You'd need to write a C++ test for this using Qt Test, and then use QQmlEngine or QQmlApplicationEngine to load the UI. See this test for an example. However, you shouldn't need to test ApplicationWindow, unless you're going for the approach I'm using that I mentioned above.

Mitch
  • 23,716
  • 9
  • 83
  • 122
  • Seems clear enough, except that I shouldn't need to test `ApplicationWindow`? I want to test more than just the components; I want to test if an application actually does what it needs to do (functional tests), not just if some custom GUI element works. I'm not averse to writing C++, so is that indeed a manageable way to go? – Halfgaar Jul 07 '16 at 08:09
  • That's what I meant by the "unless you're going for the approach I'm using that I mentioned above". That is a whole other answer in its own right though (to explain how to set up the projects, C++, etc.). It's definitely manageable to write tests in C++. – Mitch Jul 07 '16 at 08:41