aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-12-05 15:57:37 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2023-12-24 09:56:29 +0100
commit3750fe1095df1f9dc3bed1168294bc10061ac8d2 (patch)
tree1d8325177582d96e719e486467437f655d59315d
parent65a607356369fc930429c3e63206c3a05911bb53 (diff)
Add QtQuickTest
[ChangeLog][PySide6] QtQuickTest has been added. Fixes: PYSIDE-2543 Change-Id: I949a0e50a2e522589863ade1e2b2335be580a0d7 Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Adrian Herrmann <adrian.herrmann@qt.io>
-rw-r--r--sources/pyside6/PySide6/QtQuickTest/CMakeLists.txt44
-rw-r--r--sources/pyside6/PySide6/QtQuickTest/typesystem_quicktest.xml32
-rw-r--r--sources/pyside6/PySide6/doc/qtquicktest.rst62
-rw-r--r--sources/pyside6/PySide6/glue/qtquicktest.cpp50
-rw-r--r--sources/pyside6/cmake/PySideHelpers.cmake1
-rw-r--r--sources/pyside6/doc/extras/QtQuickTest.rst58
-rw-r--r--sources/pyside6/doc/modules.rst4
-rw-r--r--sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in3
-rw-r--r--sources/pyside6/tests/QtQuickTest/CMakeLists.txt3
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml20
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml3
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir2
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject4
-rw-r--r--sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py46
14 files changed, 332 insertions, 0 deletions
diff --git a/sources/pyside6/PySide6/QtQuickTest/CMakeLists.txt b/sources/pyside6/PySide6/QtQuickTest/CMakeLists.txt
new file mode 100644
index 000000000..cd224f2b0
--- /dev/null
+++ b/sources/pyside6/PySide6/QtQuickTest/CMakeLists.txt
@@ -0,0 +1,44 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+project(QtQuickTest)
+
+set(QtQuickTest_SRC
+# module is always needed
+${QtQuickTest_GEN_DIR}/qtquicktest_module_wrapper.cpp
+)
+
+set(QtQuickTest_include_dirs ${QtQuickTest_SOURCE_DIR}
+ ${QtQml_SOURCE_DIR}
+ ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS}
+ ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS}
+ ${Qt${QT_MAJOR_VERSION}OpenGL_INCLUDE_DIRS}
+ ${Qt${QT_MAJOR_VERSION}Network_INCLUDE_DIRS}
+ ${Qt${QT_MAJOR_VERSION}Qml_INCLUDE_DIRS}
+ ${Qt${QT_MAJOR_VERSION}Quick_INCLUDE_DIRS}
+ ${libpyside_SOURCE_DIR}
+ ${QtGui_GEN_DIR}
+ ${QtOpenGL_GEN_DIR}
+ ${QtCore_GEN_DIR}
+ ${QtNetwork_GEN_DIR}
+ ${QtQml_GEN_DIR}
+ ${QtQuick_GEN_DIR}
+ ${QtQuickTest_GEN_DIR})
+
+set(QtQuickTest_libraries pyside6
+ ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES}
+ ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}
+ ${Qt${QT_MAJOR_VERSION}OpenGL_LIBRARIES}
+ ${Qt${QT_MAJOR_VERSION}Network_LIBRARIES}
+ ${Qt${QT_MAJOR_VERSION}Qml_LIBRARIES}
+ ${Qt${QT_MAJOR_VERSION}Quick_LIBRARIES}
+ ${Qt${QT_MAJOR_VERSION}QuickTest_LIBRARIES})
+
+set(QtQuickTest_deps QtGui QtOpenGL QtNetwork QtQml QtQuick)
+
+create_pyside_module(NAME QtQuickTest
+ INCLUDE_DIRS QtQuickTest_include_dirs
+ LIBRARIES QtQuickTest_libraries
+ DEPS QtQuickTest_deps
+ TYPESYSTEM_PATH QtQuickTest_SOURCE_DIR
+ SOURCES QtQuickTest_SRC)
diff --git a/sources/pyside6/PySide6/QtQuickTest/typesystem_quicktest.xml b/sources/pyside6/PySide6/QtQuickTest/typesystem_quicktest.xml
new file mode 100644
index 000000000..4f30d1916
--- /dev/null
+++ b/sources/pyside6/PySide6/QtQuickTest/typesystem_quicktest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+-->
+<typesystem package="PySide6.QtQuickTest">
+ <load-typesystem name="QtCore/typesystem_core.xml" generate="no"/>
+
+ <extra-includes>
+ <include file-name="QtQuickTest/quicktest.h" location="global"/>
+ <include file-name="QtCore/QDir" location="global"/>
+ <include file-name="pysideqobject.h" location="global"/>
+ <include file-name="vector" location="global"/>
+ </extra-includes>
+ <inject-code class="native" position="beginning"
+ file="../glue/qtquicktest.cpp" snippet="call-quick-test-main"/>
+
+ <add-function signature="QUICK_TEST_MAIN(QString@name@,QStringList@argv@={},QString@dir@={})"
+ return-type="int">
+ <inject-code file="../glue/qtquicktest.cpp" snippet="quick-test-main"/>
+ <inject-documentation format="target" mode="append"
+ file="../doc/qtquicktest.rst"
+ snippet="quick_test_main_documentation"/>
+ </add-function>
+ <add-function signature="QUICK_TEST_MAIN_WITH_SETUP(QString@name@,PyTypeObject*@setup@,QStringList@argv@={},QString@dir@={})"
+ return-type="int">
+ <inject-code file="../glue/qtquicktest.cpp" snippet="quick-test-main_with_setup"/>
+ <inject-documentation format="target" mode="append"
+ file="../doc/qtquicktest.rst"
+ snippet="quick_test_main_with_setup_documentation"/>
+ </add-function>
+</typesystem>
diff --git a/sources/pyside6/PySide6/doc/qtquicktest.rst b/sources/pyside6/PySide6/doc/qtquicktest.rst
new file mode 100644
index 000000000..9df2af071
--- /dev/null
+++ b/sources/pyside6/PySide6/doc/qtquicktest.rst
@@ -0,0 +1,62 @@
+// @snippet quick_test_main_documentation
+
+Sets up the entry point for a Qt Quick Test application.
+The ``name`` argument uniquely identifies this set of tests.
+
+``sys.argv`` should be passed to the ``argv`` argument to ensure
+propagation of the command line arguments.
+
+.. note:: The function assumes that your test sources are in the current
+ directory, unless the ``QUICK_TEST_SOURCE_DIR`` environment
+ variable is set or a directory is passed in ``dir``.
+
+The following snippet demonstrates the use of this function:
+
+.. code-block:: Python
+
+ import sys
+ from PySide6.QtQuickTest import QUICK_TEST_MAIN
+
+ ex = QUICK_TEST_MAIN("example", sys.argv)
+ sys.exit(ex)
+
+
+// @snippet quick_test_main_documentation
+
+// @snippet quick_test_main_with_setup_documentation
+
+Sets up the entry point for a Qt Quick Test application.
+The ``name`` argument uniquely identifies this set of tests.
+
+``sys.argv`` should be passed to the ``argv`` argument to ensure
+propagation of the command line arguments.
+
+This function is identical to ``QUICK_TEST_MAIN()``, except that it takes an
+additional argument ``setup``, the type of a ``QObject``-derived
+class which will be instantiated. With this class, it is possible to define
+additional setup code to execute before running the QML test.
+
+The following snippet demonstrates the use of this function:
+
+.. code-block:: Python
+
+ import sys
+ from PySide6.QtQuickTest import QUICK_TEST_MAIN_WITH_SETUP
+
+ class CustomTestSetup(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ @Slot(QQmlEngine)
+ def qmlEngineAvailable(self, qmlEngine):
+ pass
+
+ ex = QUICK_TEST_MAIN_WITH_SETUP("qquicktestsetup", CustomTestSetup, sys.argv)
+ sys.exit(ex)
+
+
+.. note:: The function assumes that your test sources are in the current
+ directory, unless the ``QUICK_TEST_SOURCE_DIR`` environment
+ variable is set or a directory is passed in ``dir``.
+
+// @snippet quick_test_main_with_setup_documentation
diff --git a/sources/pyside6/PySide6/glue/qtquicktest.cpp b/sources/pyside6/PySide6/glue/qtquicktest.cpp
new file mode 100644
index 000000000..f41735ddf
--- /dev/null
+++ b/sources/pyside6/PySide6/glue/qtquicktest.cpp
@@ -0,0 +1,50 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+/*********************************************************************
+ * INJECT CODE
+ ********************************************************************/
+
+// @snippet call-quick-test-main
+static int callQuickTestMain(const QString &name, QObject *setup,
+ QStringList argv, QString dir)
+{
+ if (dir.isEmpty())
+ dir = QDir::currentPath();
+ if (argv.isEmpty())
+ argv.append(name);
+
+ std::vector<QByteArray> argvB;
+ std::vector<char *> argvC;
+ const auto argc = argv.size();
+ argvB.reserve(argc);
+ argvC.reserve(argc);
+ for (const auto &arg : argv) {
+ argvB.emplace_back(arg.toUtf8());
+ argvC.push_back(argvB.back().data());
+ }
+
+ return quick_test_main_with_setup(int(argc), argvC.data(),
+ name.toUtf8().constData(),
+ dir.toUtf8().constData(), setup);
+}
+// @snippet call-quick-test-main
+
+// @snippet quick-test-main
+const int exitCode = callQuickTestMain(%1, nullptr, %2, %3);
+%PYARG_0 = %CONVERTTOPYTHON[int](exitCode);
+// @snippet quick-test-main
+
+// @snippet quick-test-main_with_setup
+Shiboken::AutoDecRef pySetupObject(PyObject_CallObject(reinterpret_cast<PyObject *>(%2), nullptr));
+if (pySetupObject.isNull() || PyErr_Occurred() != nullptr)
+ return nullptr;
+
+/// Convenience to convert a PyObject to QObject
+QObject *setupObject = PySide::convertToQObject(pySetupObject.object(), true /* raiseError */);
+if (setupObject == nullptr)
+ return nullptr;
+
+const int exitCode = callQuickTestMain(%1, setupObject, %3, %4);
+%PYARG_0 = %CONVERTTOPYTHON[int](exitCode);
+// @snippet quick-test-main_with_setup
diff --git a/sources/pyside6/cmake/PySideHelpers.cmake b/sources/pyside6/cmake/PySideHelpers.cmake
index c728e7c43..23ceda6bd 100644
--- a/sources/pyside6/cmake/PySideHelpers.cmake
+++ b/sources/pyside6/cmake/PySideHelpers.cmake
@@ -103,6 +103,7 @@ macro(collect_optional_modules)
Quick
Quick3D
QuickControls2
+ QuickTest
QuickWidgets
RemoteObjects
Scxml
diff --git a/sources/pyside6/doc/extras/QtQuickTest.rst b/sources/pyside6/doc/extras/QtQuickTest.rst
new file mode 100644
index 000000000..52f13590b
--- /dev/null
+++ b/sources/pyside6/doc/extras/QtQuickTest.rst
@@ -0,0 +1,58 @@
+ Qt Quick Test is a unit test framework for QML applications. Test cases are
+ written as JavaScript functions within a QML TestCase type:
+
+.. code-block:: JavaScript
+
+ import QtQuick
+ import QtTest
+
+ 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.
+
+QML API
+^^^^^^^
+
+The `QML types <https://doc.qt.io/qt-6/qttest-qmlmodule.html>`_
+in Qt Quick Test are available through the ``QtTest`` import.
+To use the types, add the following import statement to your ``.qml`` file:
+
+.. code-block:: JavaScript
+
+ import QtTest
+
+Running Tests
+^^^^^^^^^^^^^
+
+Test cases are launched by a harness that consists of the following code:
+
+.. code-block:: Python
+
+ import sys
+ from PySide6.QtQuickTest import QUICK_TEST_MAIN
+
+ QUICK_TEST_MAIN("example", sys.argv)
+
+Where "example" is the identifier to use to uniquely identify this set of
+tests.
+
+Test execution can be controlled by a number of command line options (pass
+``-h`` for help).
+
+Executing Code Before QML Tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To execute code before any of the QML tests are run, the
+:py:func:`QUICK_TEST_MAIN_WITH_SETUP` function can be used. This can be useful
+for setting context properties on the QML engine, amongst other things.
diff --git a/sources/pyside6/doc/modules.rst b/sources/pyside6/doc/modules.rst
index 625d60a75..357adcf8f 100644
--- a/sources/pyside6/doc/modules.rst
+++ b/sources/pyside6/doc/modules.rst
@@ -114,6 +114,10 @@ Qt Modules Supported by Qt for Python
Provides classes for setting up the controls from C++.
+ .. grid-item-card:: :mod:`QtQuickTest <PySide6.QtQuickTest>`
+
+ A unit test framework for QML applications where test cases are written as JavaScript functions.
+
.. grid-item-card:: :mod:`QtQuickWidgets <PySide6.QtQuickWidgets>`
Provides the QQuickWidget class for embedding Qt Quick in widget-based applications.
diff --git a/sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in b/sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in
new file mode 100644
index 000000000..1d8397537
--- /dev/null
+++ b/sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in
@@ -0,0 +1,3 @@
+include(@QT_SRC_DIR@/../qtdeclarative/src/qmltest/doc/qtqmltest.qdocconf)
+includepaths += -I @QT_SRC_DIR@/../qtdeclarative/src/qmltest
+include(../pyside-config.qdocconf)
diff --git a/sources/pyside6/tests/QtQuickTest/CMakeLists.txt b/sources/pyside6/tests/QtQuickTest/CMakeLists.txt
new file mode 100644
index 000000000..49f15e447
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/CMakeLists.txt
@@ -0,0 +1,3 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+PYSIDE_TEST(quicktestmainwithsetup/tst_quicktestmainwithsetup.py)
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml
new file mode 100644
index 000000000..2cfe936a6
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/data/tst_setup.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick 2.0
+import QtTest 1.2
+
+import QmlRegisterTypeCppModule 1.0
+import ImportPathQmlModule 1.0
+
+TestCase {
+ name: "setup"
+
+ QmlRegisterTypeCppType {}
+ ImportPathQmlType {}
+
+ function initTestCase()
+ {
+ verify(qmlEngineAvailableCalled)
+ }
+}
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml
new file mode 100644
index 000000000..617bdaaf6
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/ImportPathQmlType.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.0
+
+Item {}
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir
new file mode 100644
index 000000000..dea7c9a8a
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/imports/ImportPathQmlModule/qmldir
@@ -0,0 +1,2 @@
+module ImportPathQmlModule
+ImportPathQmlType 1.0 ImportPathQmlType.qml
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject
new file mode 100644
index 000000000..61e89f4af
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/quicktestmainwithsetup.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["tst_quicktestmainwithsetup.py", "data/tst_setup.qml",
+ "imports/ImportPathQmlModule/ImportPathQmlType.qml"]
+}
diff --git a/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py
new file mode 100644
index 000000000..33b2db08f
--- /dev/null
+++ b/sources/pyside6/tests/QtQuickTest/quicktestmainwithsetup/tst_quicktestmainwithsetup.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import os
+import sys
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[2]))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+from pathlib import Path
+from PySide6.QtCore import QObject, Slot
+from PySide6.QtQml import QQmlEngine, qmlRegisterType
+from PySide6.QtQuickTest import QUICK_TEST_MAIN_WITH_SETUP
+
+
+"""Copy of the equivalent test in qtdeclarative."""
+
+
+class QmlRegisterTypeCppType(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+
+class CustomTestSetup(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ @Slot(QQmlEngine)
+ def qmlEngineAvailable(self, qmlEngine):
+ # Test that modules are successfully imported by the TestCaseCollector
+ # that parses the QML files (but doesn't run them). For that to happen,
+ # qmlEngineAvailable() must be called before TestCaseCollector does its
+ # thing.
+ qmlRegisterType(QmlRegisterTypeCppType, "QmlRegisterTypeCppModule", 1, 0,
+ "QmlRegisterTypeCppType")
+ import_dir = Path(__file__).parent / "imports"
+ qmlEngine.addImportPath(os.fspath(import_dir))
+ qmlEngine.rootContext().setContextProperty("qmlEngineAvailableCalled", True)
+
+
+data_dir = Path(__file__).parent / "data"
+exitCode = QUICK_TEST_MAIN_WITH_SETUP("qquicktestsetup", CustomTestSetup, sys.argv,
+ os.fspath(data_dir))
+sys.exit(exitCode)