Commit daf671b4 authored by Charles Yin's avatar Charles Yin

Integrate QtQuickTest into Qt

Change-Id: I558821c0dec9166ea1d0d2e1e2f889553c436316
Task-number:QTBUG-16082
parent 9bf28fbf
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of this
** file.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\page qmltest.html
\title QtQuickTest Reference Documentation
\keyword QtQuickTest Reference Documentation
\section1 Introduction
QtQuickTest is a unit test framework for Qt Quick (QML) applications.
Test cases are written as JavaScript functions within a TestCase
element:
\code
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")
}
}
\endcode
Functions whose names start with \c{test_} are treated as test cases
to be executed. See the documentation for the \l TestCase and
\l SignalSpy elements for more information on writing test cases.
\section1 Running tests
Test cases are launched by a C++ harness that consists of
the following code:
\code
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(example)
\endcode
Where "example" is an identifier to use to uniquely identify
this set of tests. You should add \c{CONFIG += qmltestcase}.
for example:
\code
TEMPLATE = app
TARGET = tst_example
CONFIG += warn_on qmltestcase
SOURCES += tst_example.cpp
\endcode
The test harness scans the specified source directory recursively
for "tst_*.qml" files. If \c{QUICK_TEST_SOURCE_DIR} is not defined,
then the current directory will be scanned when the harness is run.
Other *.qml files may appear for auxillary QML components that are
used by the test.
The \c{-input} command-line option can be set at runtime to run
test cases from a different directory. This may be needed to run
tests on a target device where the compiled-in directory name refers
to a host. For example:
\code
tst_example -input /mnt/SDCard/qmltests
\endcode
See \c{tests/qmlauto} in the source tree for an example of creating a
test harness that uses the \c{QUICK_TEST_SOURCE_DIR} macro.
If your test case needs QML imports, then you can add them as
\c{-import} options to the the test program command-line by adding
the following line to your .pro file:
\code
IMPORTPATH += $$PWD/../imports/my_module1 $$PWD/../imports/my_module2
\endcode
\section1 Running tests with QtQuick 1
The \c{-qtquick1} option can be passed to a test binary to run
the tests using QDeclarativeView (QtQuick 1) rather than QSGView (QtQuick 2):
\code
tst_example -qtquick1
\endcode
To run tests with either QtQuick 1 or QtQuick 2, use
"import QtQuick 1.0" in your unit tests and then specify
compatibility mode to the QtQuick2 engine:
\code
QMLSCENE_IMPORT_NAME=quick1 tst_example
\endcode
*/
TEMPLATE = subdirs
SUBDIRS += declarative
contains(QT_CONFIG, qmltest): SUBDIRS += qmltest
TEMPLATE=app
TARGET=tst_qmltestexample
CONFIG += qmltestcase
SOURCES += tst_qmltest.cpp
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import QtTest 1.0
TestCase {
name: "BasicTests"
function test_pass() {
compare(2 + 2, 4, "2 + 2")
}
function test_fail() {
compare(2 + 2, 5, "2 + 2")
}
function test_skip() {
skip("skipping")
}
function test_expecting() {
expectFail("", "this is the fail we wanted")
verify(false)
}
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 },
{tag: "2 + 2 = 5", a: 2, b: 2, answer: 5 }, // fail
]
}
function test_table(data) {
compare(data.a + data.b, data.answer)
}
}
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
import QtTest 1.0
Rectangle {
id: foo
width: 640; height: 480
color: "cyan"
TestCase {
name: "ItemTests"
id: test1
function test_color() {
compare(foo.color, "#00ffff")
}
}
}
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtQuickTest/quicktest.h>
QUICK_TEST_MAIN(qmltest)
QT.qmltest.VERSION = 5.0.0
QT.qmltest.MAJOR_VERSION = 5
QT.qmltest.MINOR_VERSION = 0
QT.qmltest.PATCH_VERSION = 0
QT.qmltest.name = QtQuickTest
QT.qmltest.bins = $$QT_MODULE_BIN_BASE
QT.qmltest.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/QtQuickTest
QT.qmltest.private_includes = $$QT_MODULE_INCLUDE_BASE/QtQuickTest/$$QT.qmltest.VERSION
QT.qmltest.sources = $$QT_MODULE_BASE/src/qmltest
QT.qmltest.libs = $$QT_MODULE_LIB_BASE
QT.qmltest.plugins = $$QT_MODULE_PLUGIN_BASE
QT.qmltest.imports = $$QT_MODULE_IMPORT_BASE
QT.qmltest.depends = declarative testlib
QT.qmltest.DEFINES = QT_DECLARATIVE_LIB
QT_CONFIG += qmltest
TEMPLATE = subdirs
SUBDIRS += folderlistmodel particles gestures inputcontext etcprovider
contains(QT_CONFIG, qmltest): SUBDIRS += testlib
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.0
Item {
id: spy
visible: false
// Public API.
property variant target: null
property string signalName: ""
property int count: 0
function clear() {
count = 0
qtest_expectedCount = 0
}
function wait(timeout) {
if (timeout === undefined)
timeout = 5000
var expected = ++qtest_expectedCount
var i = 0
while (i < timeout && count < expected) {
qtest_results.wait(50)
i += 50
}
var success = (count >= expected)
if (!qtest_results.verify(success, "wait for signal " + signalName, Qt.qtest_caller_file(), Qt.qtest_caller_line()))
throw new Error("QtQuickTest::fail")
}
// Internal implementation detail follows.
TestResult { id: qtest_results }
onTargetChanged: {
qtest_update()
}
onSignalNameChanged: {
qtest_update()
}
property variant qtest_prevTarget: null
property string qtest_prevSignalName: ""
property int qtest_expectedCount: 0
function qtest_update() {
if (qtest_prevTarget != null) {
qtest_prevTarget[qtest_prevSignalName].disconnect(spy, "qtest_activated")
qtest_prevTarget = null
qtest_prevSignalName = ""
}
if (target != null && signalName != "") {
var func = target[signalName]
if (func === undefined) {
console.log("Signal '" + signalName + "' not found")
} else {
qtest_prevTarget = target
qtest_prevSignalName = signalName
func.connect(spy.qtest_activated)
}
}
}
function qtest_activated() {
++count
}
}
This diff is collapsed.
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtDeclarative/qdeclarativeextensionplugin.h>
#include <QtDeclarative/qdeclarative.h>
#include <QtScript/qscriptvalue.h>
#include <QtScript/qscriptcontext.h>
#include <QtScript/qscriptcontextinfo.h>
#include <QtScript/qscriptengine.h>
#include "QtQuickTest/private/quicktestresult_p.h"
#include "QtQuickTest/private/quicktestevent_p.h"
QT_BEGIN_NAMESPACE
QML_DECLARE_TYPE(QuickTestResult)
QML_DECLARE_TYPE(QuickTestEvent)
// Copied from qdeclarativedebughelper_p.h in Qt, to avoid a dependency
// on a private header from Qt.
class Q_DECLARATIVE_EXPORT QDeclarativeDebugHelper
{
public:
static QScriptEngine *getScriptEngine(QDeclarativeEngine *engine);
static void setAnimationSlowDownFactor(qreal factor);
static void enableDebugging();
};
static QScriptContext *qtest_find_frame(QScriptContext *ctx)
{
qint32 frame = 1;
if (ctx->argumentCount() > 0)
frame = ctx->argument(0).toInt32();
++frame; // Exclude the native function; start at its caller.
while (ctx) {
if (frame-- <= 0)
break;
ctx = ctx->parentContext();
}
return ctx;
}
static QScriptValue qtest_caller_file
(QScriptContext *ctx, QScriptEngine *engine)
{
ctx = qtest_find_frame(ctx);
if (ctx) {
QScriptContextInfo info(ctx);
return engine->newVariant(info.fileName());
}
return engine->newVariant(QLatin1String(""));
}
static QScriptValue qtest_caller_line
(QScriptContext *ctx, QScriptEngine *engine)
{
ctx = qtest_find_frame(ctx);
if (ctx) {
QScriptContextInfo info(ctx);
return engine->newVariant(info.lineNumber());
}
return engine->newVariant(qint32(0));
}
class QTestQmlModule : public QDeclarativeExtensionPlugin
{
Q_OBJECT
public:
virtual void registerTypes(const char *uri)
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtTest"));
qmlRegisterType<QuickTestResult>(uri,1,0,"TestResult");
qmlRegisterType<QuickTestEvent>(uri,1,0,"TestEvent");
}
void initializeEngine(QDeclarativeEngine *engine, const char *)
{
// Install some helper functions in the global "Qt" object
// for walking the stack and finding a caller's location.
// Normally we would use an exception's backtrace, but JSC
// only provides the top-most frame in the backtrace.
QScriptEngine *eng = QDeclarativeDebugHelper::getScriptEngine(engine);
QScriptValue qtObject
= eng->globalObject().property(QLatin1String("Qt"));
qtObject.setProperty
(QLatin1String("qtest_caller_file"),
eng->newFunction(qtest_caller_file));
qtObject.setProperty
(QLatin1String("qtest_caller_line"),
eng->newFunction(qtest_caller_line));
}
};
QT_END_NAMESPACE
#include "main.moc"
Q_EXPORT_PLUGIN2(qmltestplugin, QT_PREPEND_NAMESPACE(QTestQmlModule));
plugin qmltestplugin
TestCase 1.0 TestCase.qml
SignalSpy 1.0 SignalSpy.qml
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef SIGNALSPY_H
#define SIGNALSPY_H
// This is a dummy header for defining the interface of "SignalSpy.qml" to qdoc.
#include <QtDeclarative/qdeclarativeitem.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class SignalSpy : public QDeclarativeItem
{
Q_OBJECT
Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
Q_PROPERTY(QString signalName READ signalName WRITE signalName NOTIFY signalNameChanged)
Q_PROPERTY(int count READ count countChanged)
public:
SignalSpy(QDeclarativeItem *parent) : QDeclarativeItem(parent) {}
~SignalSpy()
QObject *target() const;
void setTarget(QObject *target);
QString signalName() const;
void setSignalName(const QString &signalName);
int count() const;
Q_SIGNALS:
void targetChanged();
void signalNameChanged();
void countChanged();
};
QML_DECLARE_TYPE(SignalSpy)
QT_END_NAMESPACE
QT_END_HEADER
#endif
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\qmlclass SignalSpy SignalSpy
\brief The SignalSpy item enables introspection of signal emission.
\since 4.8
\ingroup qtest::qml
In the following example, a SignalSpy is installed to watch the
"clicked" signal on a user-defined Button element. When the signal
is emitted, the \l count property on the spy will be increased.
\code
Button {
id: button
SignalSpy {
id: spy
target: button
signalName: "clicked"
}
TestCase {
name: "ButtonClick"
function test_click() {
compare(spy.count, 0)