TestCase

Represents a unit test case More...

Import Statement: import QtTest 1.0
Since: Qt 4.8

Detailed Description

Introduction to QML test cases

Test cases are written as JavaScript functions within a TestCase type:

import QtQuick 2.0
import QtTest 1.0

TestCase {
    name: "MathTests"

    function test_math() {
        compare(2 + 2, 4, "2 + 2 = 4")
    }

    function test_fail() {
        compare(2 + 2, 5, "2 + 2 = 5")
    }
}

Functions whose names start with "test_" are treated as test cases to be executed. The name property is used to prefix the functions in the output:

********* Start testing of MathTests *********
Config: Using QTest library 4.7.2, Qt 4.7.2
PASS   : MathTests::initTestCase()
FAIL!  : MathTests::test_fail() 2 + 2 = 5
   Actual (): 4
   Expected (): 5
   Loc: [/home/.../tst_math.qml(12)]
PASS   : MathTests::test_math()
PASS   : MathTests::cleanupTestCase()
Totals: 3 passed, 1 failed, 0 skipped
********* Finished testing of MathTests *********

Because of the way JavaScript properties work, the order in which the test functions are found is unpredictable. To assist with predictability, the test framework will sort the functions on ascending order of name. This can help when there are two tests that must be run in order.

Multiple TestCase types can be supplied. The test program will exit once they have all completed. If a test case doesn't need to run (because a precondition has failed), then optional can be set to true.

Data-driven tests

Table data can be provided to a test using a function name that ends with "_data". Alternatively, the init_data() function can be used to provide default test data for all test functions in a TestCase type:

import QtQuick 2.0
import QtTest 1.0

TestCase {
    name: "DataTests"

    function init_data() {
      return [
           {tag:"init_data_1", a:1, b:2, answer: 3},
           {tag:"init_data_2", a:2, b:4, answer: 6}
      ];
    }

    function test_table_data() {
        return [
            {tag: "2 + 2 = 4", a: 2, b: 2, answer: 4 },
            {tag: "2 + 6 = 8", a: 2, b: 6, answer: 8 },
        ]
    }

    function test_table(data) {
        //data comes from test_table_data
        compare(data.a + data.b, data.answer)
    }

    function test__default_table(data) {
        //data comes from init_data
        compare(data.a + data.b, data.answer)
    }
}

The test framework will iterate over all of the rows in the table and pass each row to the test function. As shown, the columns can be extracted for use in the test. The tag column is special - it is printed by the test framework when a row fails, to help the reader identify which case failed amongst a set of otherwise passing tests.

Benchmarks

Functions whose names start with "benchmark_" will be run multiple times with the Qt benchmark framework, with an average timing value reported for the runs. This is equivalent to using the QBENCHMARK macro in the C++ version of QTestLib.

TestCase {
    id: top
    name: "CreateBenchmark"

    function benchmark_create_component() {
        var component = Qt.createComponent("item.qml")
        var obj = component.createObject(top)
        obj.destroy()
        component.destroy()
    }
}

RESULT : CreateBenchmark::benchmark_create_component:
     0.23 msecs per iteration (total: 60, iterations: 256)
PASS   : CreateBenchmark::benchmark_create_component()

To get the effect of the QBENCHMARK_ONCE macro, prefix the test function name with "benchmark_once_".

Simulating keyboard and mouse events

The keyPress(), keyRelease(), and keyClick() methods can be used to simulate keyboard events within unit tests. The events are delivered to the currently focused QML item. You can pass either a Qt.Key enum value or a latin1 char (string of length one)

Rectangle {
    width: 50; height: 50
    focus: true

    TestCase {
        name: "KeyClick"
        when: windowShown

        function test_key_click() {
            keyClick(Qt.Key_Left)
            keyClick("a")
            ...
        }
    }
}

The mousePress(), mouseRelease(), mouseClick(), mouseDoubleClick(), and mouseMove() methods can be used to simulate mouse events in a similar fashion.

Note: keyboard and mouse events can only be delivered once the main window has been shown. Attempts to deliver events before then will fail. Use the when and windowShown properties to track when the main window has been shown.

See also SignalSpy.