第 4 章:重演 GUI 事件

如何重演 GUI 事件。

In this chapter, we will show how to simulate a GUI event, and how to store a series of GUI events as well as replay them on a widget.

The approach to storing a series of events and replaying them is quite similar to the approach explained in 第 2 章 . All you need to do is to add a data function to your test class:

class TestGui: public QObject
{
    Q_OBJECT
private slots:
    void testGui_data();
    void testGui();
};
					

编写数据函数

As before, a test function's associated data function carries the same name, appended by _data .

void TestGui::testGui_data()
{
    QTest::addColumn<QTestEventList>("events");
    QTest::addColumn<QString>("expected");
    QTestEventList list1;
    list1.addKeyClick('a');
    QTest::newRow("char") << list1 << "a";
    QTestEventList list2;
    list2.addKeyClick('a');
    list2.addKeyClick(Qt::Key_Backspace);
    QTest::newRow("there+back-again") << list2 << "";
}
					

First, we define the elements of the table using the QTest::addColumn () function: A list of GUI events, and the expected result of applying the list of events on a QWidget . Note that the type of the first element is QTestEventList .

A QTestEventList can be populated with GUI events that can be stored as test data for later usage, or be replayed on any QWidget .

In our current data function, we create two QTestEventList elements. The first list consists of a single click to the 'a' key. We add the event to the list using the QTestEventList::addKeyClick () function. Then we use the QTest::newRow () function to give the data set a name, and stream the event list and the expected result into the table.

The second list consists of two key clicks: an 'a' with a following 'backspace'. Again we use the QTestEventList::addKeyClick () to add the events to the list, and QTest::newRow () to put the event list and the expected result into the table with an associated name.

重写测试函数

Our test can now be rewritten:

void TestGui::testGui()
{
    QFETCH(QTestEventList, events);
    QFETCH(QString, expected);
    QLineEdit lineEdit;
    events.simulate(&lineEdit);
    QCOMPARE(lineEdit.text(), expected);
}
					

The TestGui::testGui() function will be executed two times, once for each entry in the test data that we created in the associated TestGui::testGui_data() function.

First, we fetch the two elements of the data set using the QFETCH () 宏。 QFETCH () takes two arguments: the data type of the element and the element name. Then we create a QLineEdit , and apply the list of events on that widget using the QTestEventList::simulate () 函数。

Finally, we use the QCOMPARE () macro to check if the line edit's text is as expected.

Preparing the Stand-Alone Executable

As before, to make our test case a stand-alone executable, the following two lines are needed:

QTEST_MAIN(TestGui)
#include "testgui.moc"
					

The QTEST_MAIN () macro expands to a simple main() method that runs all the test functions, and since both the declaration and the implementation of our test class are in a .cpp file, we also need to include the generated moc file to make Qt's introspection work.

Building the Executable

You can build the test case executable using CMake or qmake.

构建采用 CMake

Configure your build settings in your CMakeLists.txt file:

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(tutorial4 LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
    set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/qtestlib/tutorial4")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Test Widgets)
qt_standard_project_setup()
qt_add_executable(tutorial4
    testgui.cpp
)
set_target_properties(tutorial4 PROPERTIES
    WIN32_EXECUTABLE TRUE
    MACOSX_BUNDLE TRUE
)
target_link_libraries(tutorial4 PRIVATE
    Qt6::Core
    Qt6::Gui
    Qt6::Test
    Qt6::Widgets
)
install(TARGETS tutorial4
    RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
    BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
    LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)
					

Next, from the command line, run either cmake 或使用 qt-cmake convenience script located in Qt-prefix/<version>/<platform>/bin/qt-cmake :

<Qt-prefix>/<version>/<platform>/bin/qt-cmake <source-dir> <build-dir> -G Ninja
					

Then, run your preferred generator tool to build the executable. Here, we're using Ninja:

ninja
					
采用 qmake 构建

Configure your build settings in your .pro 文件:

QT += widgets testlib
SOURCES = testgui.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/qtestlib/tutorial4
INSTALLS += target
					

Next, run qmake , and, finally, run make to build your executable:

qmake
make
					

Running the Executable

Running the resulting executable should give you the following output:

********* Start testing of TestGui *********
Config: Using QtTest library %VERSION%, Qt %VERSION%
PASS   : TestGui::initTestCase()
PASS   : TestGui::testGui(char)
PASS   : TestGui::testGui(there+back-again)
PASS   : TestGui::cleanupTestCase()
Totals: 4 passed, 0 failed, 0 skipped, 0 blacklisted, 18ms
********* Finished testing of TestGui *********
					

范例工程 @ code.qt.io

第 3 章 第 5 章