I have a simple application that runs successfully; however, I am having difficulties trying to run a test case with qmltest. From the documentation it shows to setup the main.cpp file with the QUICK_TEST_MAIN_WITH_SETUP
call to initialize the QML engine context. There is a runtime message: QMetaObject::invokeMethod: No such method QObject::qmlEngineAvailable(QQmlEngine*)
as well as a qwarn message: QWARN : example::case_1::test_case1() file: MouseQml.qml:44: ReferenceError: mouse is not defined
. The QML test case can't find my Class member function mouse.clear()
. Am I setting this up correctly?
main.cpp
#include <QtQuickTest/quicktest.h>
#include <QQmlEngine>
#include <QQmlContext>
#include <QQmlComponent>
#include "mousememory.h"
class Setup : public QObject
{
public:
Setup() {}
public slots:
void qmlEngineAvailable(QQmlEngine *engine)
{
QScopedPointer<MouseMemory> mouse(new MouseMemory);
engine->rootContext()->setContextProperty("mouse", mouse.data());
}
};
QUICK_TEST_MAIN_WITH_SETUP(example, Setup)
simplified MouseQML.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
id: root
visible: true
width: 500
height: 500
Row {
id: tools
Button {
id: clear
objectName: "clear"
text: "Clear"
onClicked: {
canvas.clear()
}
}
}
Canvas {
id: canvas
anchors.top: tools.bottom
width: 500
height: 500
property int lastX: 0
property int lastY: 0
function clear() {
var ctx = getContext("2d")
ctx.reset()
canvas.requestPaint()
mouse.clear()
}
}
}
tst_case_1.qml
import QtQuick 2.0
import QtTest 1.0
import "../app"
TestCase {
name: "case_1"
MouseQml {
id: mainApp
}
function initTestCase() {
var qmlClear = findChild(mainApp, "clear")
tryCompare(qmlClear, "text", "Clear")
}
function cleanupTestCase() {
}
function test_case1() {
var qmlClear = findChild(mainApp, "clear")
mouseClick(qmlClear)
//tryCompare(qmlClear, "text", "Clear")
}
function test_case() {
}
}
console output
11:45:54: Starting MouseMonitor\build\ui_test\debug\ui_test...
QMetaObject::invokeMethod: No such method QObject::qmlEngineAvailable(QQmlEngine*)
********* Start testing of example *********
Config: Using QtTest library 5.11.2, Qt 5.11.2 (x86_64-little_endian-llp64 shared (dynamic) debug build; by MSVC 2015)
PASS : example::case_1::initTestCase()
PASS : example::case_1::test_case()
QWARN : example::case_1::test_case1() file:///MouseQml.qml:44: ReferenceError: mouse is not defined
PASS : example::case_1::test_case1()
PASS : example::case_1::cleanupTestCase()
Totals: 4 passed, 0 failed, 0 skipped, 0 blacklisted, 16ms
********* Finished testing of example *********
You have 2 errors:
The first one seems to be caused because the example of the docs is not completely correct since it omits the use of the macro Q_OBJECT
that should be used if you want to implement the slots and you should add #include "main.moc"
.
The other because apparently you do not understand what QScopedPointer is for, its main task is to eliminate the pointer when the object is also deleted, in this case the QScopedPointer will be deleted when qmlEngineAvailable finishes executing and thus eliminating the MouseMemory pointer. A possible solution is to make the QScopedPointer member of the class extending its life cycle and therefore that of the MouseMemory.
Considering the above, the solution is as follows:
main.cpp
#include "mousememory.h"
#include <QtQuickTest>
#include <QQmlEngine>
#include <QQmlContext>
class Setup : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
void applicationAvailable(){
}
#endif
void qmlEngineAvailable(QQmlEngine *engine)
{
mouse.reset(new MouseMemory);
engine->rootContext()->setContextProperty("mouse", mouse.data());
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
void cleanupTestCase(){
}
#endif
private:
QScopedPointer<MouseMemory> mouse;
};
QUICK_TEST_MAIN_WITH_SETUP(example, Setup)
#include "main.moc"
The complete example you find here.
Note: In Qt 5.12 two slots have been added:
void applicationAvailable()
void cleanupTestCase()