I have gone through the documentation provided by Qt on TestCase, Qt Quick Test Reference Documentation, Ubuntu QML unit testing, Testing with qmltestrunner part 1 & 2, Writing and running qml testcases, How to create a Qt-Quick Test
All that I have found about it is:
Qmltestrunner is a tool used for unit testing. This tool allows to execute QML files as test cases. These files should contain test_functions. Qmltestrunner is an open-source project and its source code can be found from the github.
But there are few questions for which I'm looking out for answers:
qmltestrunner documentation? where can I find it? (Could not find wiki page for it)
Is qmltestrunner part of qt quick test framework?
What all dependencies are there for qmltestrunner?
Is there any proper example where I can find complete explanation about QML unit testing? qt quick test framework explains running-tests which I couldn't understand.
Thank you
Unfortunately there's no documentation for qmltestrunner (I cannot one). If you only want to know how to use it, qmltestrunner.exe -h may help you. Most options are described in Qt Test Overview.
Yes. Qt Quick Test Reference Documentation - Running Tests says you need a .cpp file that contains QUICK_TEST_MAIN(xxx) and a .pro file that contains CONFIG += qmltestcase, and build this project to run your QML unit tests. The output binary file of this project is (almost the same as) qmltestrunner.
To run qmltestrunner (in Windows with Qt 5.7, for example), you need at least the following modules: Qt5Core.dll, Qt5Gui.dll, Qt5Network.dll, Qt5Qml.dll, Qt5Quick.dll, Qt5QuickTest.dll, Qt5Test.dll, Qt5Widget.dll. And some extra modules for your QML files if needed (ex. QtQuick Controls 2)
TestCase describes how to write a unit tests in QML. To run the file, simply run qmltestrunner.exe -input C:\My\Testing\File\Path\tst_myComponentTest.qml in command line.
Here's simple step-by-step example about how to write a QML component with unit tests. For example, assume that we have a ExpandButton that expands when it is clicked:
//ExpandButton.qml
import QtQuick 2.7
import QtQuick.Controls 1.2
Button {
width: 50; height: 50
onClicked: { width = 100; }
}
To test this behavior, write a tst_ExpandButton.qml:
import QtQuick 2.7
import QtTest 1.0
Item {
width: 800; height: 600
ExpandButton {
id: expandButton
anchors.centerIn: parent
}
TestCase {
name: "ExpandButton"; when: windowShown
function test_clickToExpand() {
var widthBeforeClick = expandButton.width;
mouseClick(expandButton);
var widthAfterClick = expandButton.width;
verify(widthBeforeClick < widthAfterClick);
}
}
}
Now we have two QML files, ExpandButton.qml and tst_ExpandButton.qml. Run the unit test with qmltestrunner.exe -input D:\aaa\bbb\tst_ExpandButton.qml and you can see the result:
********* Start testing of qmltestrunner *********
Config: Using QtTest library 5.7.0, Qt 5.7.0 (i386-little_endian-ilp32 shared (dynamic) release build; by MSVC 2015)
PASS : qmltestrunner::ExpandButton::initTestCase()
PASS : qmltestrunner::ExpandButton::test_clickToExpand()
PASS : qmltestrunner::ExpandButton::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 13ms
********* Finished testing of qmltestrunner *********
http://doc.qt.io/qt-5/qtquick-qtquicktest.html This will help in understanding qmltest runner
http://doc.qt.io/qt-5/qml-qttest-signalspy.html This will help in understanding signal spy which is used to catch signals
http://doc.qt.io/qt-5/qml-qttest-testcase.html This will help in writing each test case
Related
I'm trying to create a very simple wayland compositor using the examples found here, like this:
import QtQuick 2.12
import QtQuick.Window 2.2
import QtWayland.Compositor 1.3
WaylandCompositor {
id: wlcompositor
WaylandOutput {
compositor: wlcompositor
window: Window {
width: 800
height: 480
visible: true
title: wlcompositor.socketName
Grid {
anchors.fill: parent
anchors.margins: 100
columns: 2
Repeater {
model: shellSurfaces
ShellSurfaceItem {
id: shellSurfaceItem
autoCreatePopupItems: true
shellSurface: modelData
onSurfaceDestroyed: shellSurfaces.remove(index)
}
}
}
}
}
ListModel { id: shellSurfaces }
XdgShell {
onToplevelCreated: shellSurfaces.append({shellSurface: xdgSurface})
}
}
And then I'm creating a separate client app that just creates a couple Rectangles as a test.
import QtQuick 2.12
import QtQuick.Window 2.12
Window
{
id: window
visible: true
width: 200
height: 200
Rectangle
{
anchors.fill: parent
color: "green"
Rectangle
{
x: 10
y: 10
width: 100
height: 100
color: "blue"
}
}
}
Everything seems simple and straightforward. But when I run it on my Pi4 (using the -platform wayland flags), the client gets crazy distortion, like this:
I'm testing it with Boot2Qt, which is a yocto linux image. I've tried Qt versions 5.14.2 and the newest 5.15.0 with the same results. There are no errors on the console. Nothing that indicates anything is wrong except that it looks awful.
I did notice that if I use weston as my compositor instead of QtWayland, then the app looks perfect. So that makes me think there's something wrong with WaylandCompositor. But my search of google found nobody else complaining of the same thing.
I don't even know what to try. Does anybody have any ideas?
I had similar effects using qt 5.15.1 and qt 5.15.2 with qt wayland on the pi 4. I managed to get QT Wayland working with no distortion by compiling the mesa driver 20.3.3 and 20.3.4, using the following options:
-Dplatforms=x11,wayland -Dvulkan-drivers=broadcom -Ddri-drivers= -Dgallium-drivers=kmsro,v3d,vc4 -Dbuildtype=release -Dprefix=/usr -Degl=true
After installing the drivers i updated the sysroot on my host and cross-compiled the QT Lib.
That made it finally working. Good luck.
I've encountered this very same issue from Qt 5.12 to 5.15, and Qt 6.2.0 RC.
The solution to avoid distortion is to enable dma-buf in QtWayland, and set hardware integration from the compositor side:
export QT_WAYLAND_CLIENT_BUFFER_INTEGRATION=linux-dmabuf-unstable-v1
export QT_WAYLAND_SERVER_BUFFER_INTEGRATION=dmabuf-server
Note that in order to enable dma-buf it required me to tweak .pro and configure.json files (I'm doing native build on the Pi4), as the libdrm-dev header couldn't be detected by qmake or cmake correctly.
Add INCLUDEPATH += /usr/include/libdrm/ to the following two:
./src/plugins/hardwareintegration/client/dmabuf-server/dmabuf-server.pro
./src/plugins/hardwareintegration/compositor/dmabuf-server/dmabuf-server.pro
And add libdrm/ before drm headers in following files:
./src/client/configure.json
./src/compositor/configure.json
A re-configure & rebuild should work. Tested on Pi4 + Qt 5.15.2 with both armhf and arm64 image, using dtoverlay=vc4-kms-v3d-pi4 overlay.
If memory serves me correctly, the closed-source graphics driver are a real pain when it comes to wayland support. You may have some luck by enabling the broadcom backend (which I think it's what appropriate for rpis) for qt wayland by setting QT_WAYLAND_CLIENT_BUFFER_INTEGRATION=brcm before starting the compositor.
There is some info about this env var in this readme: https://code.qt.io/cgit/qt/qtwayland.git/tree/README
But if practically possible, I would think the mesa open-source drivers will give you a lot less pain, as it's much more widely used and support is likely much better.
I have simply copied this example from the docs, adjusting the import version number to the newest ones (but I tried with both for same result).
import QtQuick.Window 2.12
import Qt.labs.settings 1.1
Window {
id: window
width: 800
height: 600
Settings {
property alias x: window.x
property alias y: window.y
property alias width: window.width
property alias height: window.height
}
}
As opposed to advertised, the window geometry was not saved after I closed and reopened the window. In fact, it now doesn't show the window at all? (I tried re-running qmake and cleaning all)
I also get this warning every time I run the project in Qt Creator, regardless of whether I use Settings or not:
17:01:02: Starting C:...debug\untitled.exe...
QML debugging is enabled. Only use this in a safe environment.
qrc:/main.qml:10:5: QML Settings: Failed to initialize QSettings instance. Status code is: 1
qrc:/main.qml:10:5: QML Settings: The following application identifiers have not been set: QVector("organizationName", "organizationDomain")
1) Is the warning related to the issue?
2) How do I remove the warning?
3) How do I get the settings to be applied as advertised?
...Turns out I had to keep reading the docs to the end.
1) Warning is related to the issue.
2) Per the docs, add this at the beginning of the main in main.cpp
app.setOrganizationName("Some Company");
app.setOrganizationDomain("somecompany.com");
app.setApplicationName("Amazing Application");
3) Now works as advertised.
Hi Everyone i am new to QT and i am having trouble loading one qml through another qml
Basically i have created a qml MyTabView(MyTabView.qml)
import QtQuick 2.3
import QtQuick.Controls 1.2
TabView {
width: 360
height: 360
Component.onCompleted: {
addTab("Tab 1", tab1)
addTab("Tab 2", tab2)
}
Component {
id: tab1
Rectangle {color: "red"}
}
Component {
id: tab2
Rectangle {color: "blue"}
}
}
and i am trying to show it through another qml(main.qml) which is in the same directory
import QtQuick 2.3
import QtQuick.Controls 1.2
import "."
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Main")
MyTabView {}
}
but when i try to run my project i get this error
QQmlApplicationEngine failed to load component
qrc:/qml/main.qml:11 TabView is not a type
Please note that i have M Caps in MyTabView.qml and that MyTabView.qml and main.qml are in the same directory.
Can someone point me what mistake i am doing ?
One thing i want to point is that when i replace all the code of MyTabView.qml instead of MyTabView {} inside main.qml,the program does not give any error and runs correctly.
Thanks in advance
Have you added the file to your Resources ?
Adding your MyTabView.qml to your project in the same directory of main.qml is not sufficient.
You have to put your QML file in the Resources (probably main.qrc/qml/) in order to have it deployed.
The editor of Qt Creator does not need this inclusion in order to find your type, therefore it displays no error.
I had a similar problem.
qrc:AGview.qml:8:15: AGraph is not a type
I solved it:
my original code (in my main.cpp):
view.setSource(QUrl("qrc:AGview.qml"));
the working one:
view.setSource(QUrl("qrc:/AGview.qml"));
I think without the slash it don't search in the actual folder.
You should rename your "TabView.qml" to something like "MyTabView.qml".
Because of that import
import "."
you have conflict of TabView from "QtQuick.Controls 1.2" and local folder "."
This error can also be caused by a component's having an error. For instance, I had this sequence of errors:
QQmlApplicationEngine failed to load component
qrc:/main.qml:6 Type MainView unavailable
qrc:/MainView.qml:27 Type ApplicationLocked unavailable
qrc:/ApplicationLocked.qml:4 MetaStateChart is not a type
It's not very clear, bu the error in MainView is caused by a problem in ApplicationLocked. When I fixed that error, everything else worked.
So contrary to the conventional wisdom of starting with the first compiler error, it may be necessary to start with the last one!
I have the same thing as you, there are 2 solutions, Frist is to lower the qt version below 6, the second is to use cmake to compile, it will be successful
Ok I have had this problem recently with QT 6.2 and QML. Using both CMake and QMake as the build systems.
The solution is to add the QML file e.g. MyTabView.qml to the resources file and make sure it is added to the CMakeLists.txt or the project file (should be done automatically for you).
Then in the top of your main.qml or wherever you are using this custom component import qrc:/. Assuming the custom qml file was added under the prefix / and therefore its resource path will be qrc:/MyTabView.qml.
I've been playing with QML application and extensions through qmlRegisterType, and I stumbled into a strange thing : I have 2 projects. The first one produces a dll with a custom QML type, and the second one is a really simple application which looks like this :
main.cpp :
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine(QUrl("qrc:/main.qml"));
return app.exec();
}
main.qml
import QtQuick 2.3
import QtQuick.Window 2.2
import TestLib 1.0
Window {
visible: true
width: 360
height: 360
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
HelloWorld {
id: hello
test: "Foo !!"
}
Text {
anchors.centerIn: parent
text: hello.test
font.pointSize: 40
}
}
When I run my project through Qt Creator, everything works fine, and when I click anywhere on the window, it closes properly.
But now, if I try to compile the exact same code through a Visual Studio project (I use and special version of Premake to generate the Visual Studio solution and project files which handle the Qt special files correctly) then everything compiles, runs fine, but as soon as I click on the window, I have a crash with the following callstack :
ntdll.dll!RtlFreeHeap() Unknown
kernel32.dll!HeapFree() Unknown
msvcr120.dll!free(void * pBlock) Line 51 C
TestLib.dll!000007fef7bb6d6c() Unknown
Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1936 C++
Qt5Cored.dll!QObject::~QObject() Line 1030 C++
Qt5Quickd.dll!QQuickItem::~QQuickItem() Line 2120 C++
Qt5Quickd.dll!QQuickRootItem::~QQuickRootItem() C++
Qt5Quickd.dll!QQuickRootItem::`scalar deleting destructor'(unsigned int) C++
Qt5Quickd.dll!QQuickWindow::~QQuickWindow() Line 1102 C++
Qt5Quickd.dll!QQuickWindowQmlImpl::~QQuickWindowQmlImpl() C++
Qt5Quickd.dll!QQmlPrivate::QQmlElement<QQuickWindowQmlImpl>::~QQmlElement<QQuickWindowQmlImpl>() Line 106 C++
Qt5Quickd.dll!QQmlPrivate::QQmlElement<QQuickWindowQmlImpl>::`scalar deleting destructor'(unsigned int) C++
Qt5Qmld.dll!qDeleteAll<QList<QObject * __ptr64>::const_iterator>(QList<QObject *>::const_iterator begin, QList<QObject *>::const_iterator end) Line 323 C++
Qt5Qmld.dll!qDeleteAll<QList<QObject * __ptr64> >(const QList<QObject *> & c) Line 332 C++
Qt5Qmld.dll!QQmlApplicationEnginePrivate::cleanUp() Line 64 C++
Qt5Qmld.dll!QQmlApplicationEngine::~QQmlApplicationEngine() Line 241 C++
TestApp.exe!000000013faf2630() Unknown
TestApp.exe!000000013faf4197() Unknown
I spent a lot of time browsing Google and such, but I couldn't find anything helpfull. I think that maybe I'm missing some compilation option in my projects, that Qt Creator automatically adds, but I don't know which one :/
I know that just looking at this question will probably not be sufficient to find a solution, so I prepared a small project that perfectly reproduces the problem. If you're willing to try it, feel free to drop me a message, and I'll send it to you (I don't have any dropbox account or equivalent, unfortunately)
Thanks in advance for any help !
You are using at least part of Release CRT msvcr120.dll with your Debug application and debug Qt dlls. It is not safe to mix Debug and Release in the same application because this creates more than 1 independent heap. If you allocate memory in the release heap you can not free it in the Debug heap and vise-versa because doing so corrupts the heap. Also the heap corruption does not necessarily cause an instant crash at the next allocation / deallocation so it becomes hard to debug. As you found out using the correct CRT will fix this problem.
I have multiple versions of Qt installed, and I need to compile my project with all of them.
Using a pro file, I could not find in the documentation how to do a conditional compilation.
Ideally, this is what I would like to do:
QT_VERSION = 5 # this can be 4, set manually
if(QT_VERSION == 5) {
QT += widgets
}
if(QT_VERSION == 4) {
QT += gui
}
Naturally, the if() command does not exist in pro files.
Is there a better way to do the same thing?
You can use conditional functions and scopes here:
QT_VERSION = 5 # this can be 4, set manually
equals(QT_VERSION, 5){
QT += widgets
}
equals(QT_VERSION, 4) {
QT += gui
}
However, there are a few things that you need to pay attention to in your original code:
Explicitly defining the Qt version is not necessary, and it can make you get a headache if you forgot to change that in the .pro file. Instead, qmake automatically defines a variable QT_MAJOR_VERSION for you.
Using equals will work in this case. However, as noted below, equals performs a string comparison. However, it is better to use greaterThan and lessThan because your code will automatically stop working when you try to compile it with Qt 6 (somewhere in the future).
Adding gui to the QT is not needed, as it is included by default.
So, your code should be:
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
Here are some undocumented qmake gems:
defined(func, type)
Returns true if func is defined; type must be either test or replace, to match defineTest or defineReplace.
equals(var1, var)
(also works as isEqual).
Returns true if var1 is equal to var2 (string comparison).
lessThan(var1, var2)`
Returns true if var1 is less than var2 (as an integer).
greaterThan(var1, var2)
Returns true if var1 is greater than var2 (as an integer).
inFile(file, var, val)
Returns true if a variable var is defined in the specified file. Additionally, it can test to see if it has the requested value.
load(string)
Something of a cross between include() and CONFIG += [feature]. load(foo) will look for a file called "foo.prf" in the standard feature path, and execute its contents immediately. Features that are contained within CONFIG are executed last, after the ".pro" file has finished processing. Like include(), it will return true if the file was found.
You can make checks in one line like this:
equals(QT_MAJOR_VERSION, 5):!lessThan(QT_MINOR_VERSION, 5) {
QT += bluetooth
} else {
message(Qt $$QT_VERSION Bluetooth not supported.)
}
!lessThan there stands for greater or equal.
Since Qt 5.10, there is versionAtLeast and versionAtMost test functions.
Usage example:
!versionAtLeast(QT_VERSION, 5.11.2):error("Use at least Qt version 5.11.2")
P.S.: Posting this answer, since simple googling "qmake check Qt version" doesn't brings these references (but this post does).
This is a simple test to do. This is what we have been doing in QtSerialPort and also some other modules inside the Qt framework:
lessThan(QT_MAJOR_VERSION, 5) {
...
} else {
...
}
Similar and common conditions are:
contains(QT_MAJOR_VERSION, 5): ...
or:
greaterThan(QT_MAJOR_VERSION, 4): ...
Here you can find another QtSerialPort example we have been doing in there.