summaryrefslogtreecommitdiffstats
path: root/doc/testcases.txt
blob: 4a5e53f53d5597fd8348356a8e4452fe8796c050 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

Organization of test cases
==========================

The test cases are launched by a C++ harness that consists of
the following code:

    #include <QtTestQuick/qdeclarativetest.h>
    QTEST_QUICK_MAIN(qmlexample)

Where "qmlexample" is an identifier to use to uniquely identify
this set of tests.

The test harness scans recursively for "tst_*.qml" files in the qrc
resources that are bound into the test harness binary.  The following
is an example .qrc file:

    <!DOCTYPE RCC><RCC version="1.0">
    <qresource>
        <file>tst_basic.qml</file>
        <file>tst_item.qml</file>
    </qresource>
    </RCC>

The QTEST_QUICK_SOURCE_DIR environment variable can also be set
at runtime to run test cases from a non-resource directory.

Other *.qml files may appear for auxillary QML components that are
used by the test.

See "tests/qmlexample" for an example of creating a test harness.

Basic test cases
================

Test cases are written as JavaScript functions within a "TestCase" element:

----------------------
import Qt 4.7
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 that start with "test_" are treated as test cases to be
executed.  The "name" is used to prefix the functions in the output:

********* Start testing of MathTests *********
FAIL!  : MathTests::test_fail() 2 + 2 = 5: actual: 4, expected: 5
PASS   : MathTests::test_math()
Totals: 1 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.

A number of helper functions are available to assist with writing tests:

    fail(msg)
        - Fail the current test and show "msg".
        - Similar to QFAIL in C++

    verify(cond, msg)
        - Verify that "cond" is true, fail with "msg" if not.
        - Similar to QVERIFY in C++

    compare(actual, expected, msg)
        - Compare "actual" with "expected", fail with "msg" if not.
        - Similar to QCOMPARE in C++

    skip(msg)                   ["Single" mode]
    skipAll(msg)
        - Skip the current test and show "msg".
        - Similar to QSKIP in C++

    expectFail(msg)             ["Abort" mode]
    expectFailContinue(msg)
        - Mark the current test as expected to fail, with "msg" on failure.

    warn(msg)
        - Similar to QWARN in C++

    ignoreWarning(msg)
        - Ignore warning message
        - Similar to QTest::ignoreMessage(QtWarningMsg, msg)

    wait(ms)
        - Wait for "ms" milliseconds, processing Qt events.

    sleep(ms)
        - Sleep for "ms" milliseconds, but do not process events.

The "msg" parameters can be omitted if there is no particular message
that should be displayed other than "FAIL" or "SKIP".

Special functions
=================

The following special function names have the same meaning as in C++:

    initTestCase()
    cleanupTestCase()
    init()
    cleanup()

Note: The initTestCase_data() function from C++ is not supported.

Data-driven tests
=================

Table data can be provided to a test using a function name that ends
with "_data":

----------------------
import Qt 4.7
import QtTest 1.0

TestCase {
    name: "DataTests"

    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) {
        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.

Asynchronous testing
====================

The "when" property can be used to cause a "TestCase" element to trigger
only when a certain condition is true.  For example, the following example
runs a test when the user presses the mouse button:

----------------------
import Qt 4.7
import QtTest 1.0

Rectangle {
    id: foo
    width: 640; height: 480
    color: "cyan"

    MouseArea {
        id: area
        anchors.fill: parent
    }

    property bool bar: true

    TestCase {
        name: "ItemTests"
        when: area.pressed
        id: test1

        function test_bar() {
            verify(bar)
        }
    }
}
----------------------

Multiple "TestCase" elements 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:

----------------------
TestCase {
    when: false
    optional: true

    function test_not_run() {
        verify(false)
    }
}
----------------------