forked from qt-creator/qt-creator
Plugins: Add documentation about testing
Add information about how to write plugin tests and how to integrate unit tests. Change-Id: I13721f03c4c55a265a93f71a7c4d892f3e53a6bb Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
@@ -20,6 +20,24 @@ find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
|
||||
set(QtX Qt${QT_VERSION_MAJOR})
|
||||
#! [3]
|
||||
|
||||
#! [5]
|
||||
# Add a CMake option that enables building your plugin with tests.
|
||||
# You don't want your released plugin binaries to contain tests,
|
||||
# so make that default to 'NO'.
|
||||
# Enable tests by passing -DWITH_TESTS=ON to CMake.
|
||||
option(WITH_TESTS "Builds with tests" NO)
|
||||
|
||||
if(WITH_TESTS)
|
||||
# Look for QtTest
|
||||
find_package(${QtX} REQUIRED COMPONENTS Test)
|
||||
# Tell CMake functions like add_qtc_plugin about the QtTest component.
|
||||
set(IMPLICIT_DEPENDS Qt::Test)
|
||||
|
||||
# Enable ctest for auto tests.
|
||||
enable_testing()
|
||||
endif()
|
||||
#! [5]
|
||||
|
||||
#! [4]
|
||||
add_qtc_plugin(Example
|
||||
PLUGIN_DEPENDS
|
||||
@@ -36,5 +54,16 @@ add_qtc_plugin(Example
|
||||
example.h
|
||||
example_global.h
|
||||
exampleconstants.h
|
||||
examplefunctions.h
|
||||
)
|
||||
#! [4]
|
||||
|
||||
#! [6]
|
||||
# conditionally add auto tests
|
||||
if(WITH_TESTS)
|
||||
add_qtc_test(tst_mytest
|
||||
SOURCES tst_mytest.cpp
|
||||
DEPENDS Example
|
||||
)
|
||||
endif()
|
||||
#! [6]
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "example.h"
|
||||
|
||||
#include "exampleconstants.h"
|
||||
#include "examplefunctions.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
@@ -13,9 +15,31 @@
|
||||
#include <QMainWindow>
|
||||
#include <QMenu>
|
||||
|
||||
//! [test include]
|
||||
#ifdef WITH_TESTS
|
||||
#include <QtTest>
|
||||
#endif
|
||||
//! [test include]
|
||||
|
||||
namespace Example {
|
||||
namespace Internal {
|
||||
|
||||
//! [plugin tests]
|
||||
#ifdef WITH_TESTS
|
||||
class MyPluginTests : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void testMyTest()
|
||||
{
|
||||
// a failing test
|
||||
QVERIFY(false);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
//! [plugin tests]
|
||||
|
||||
ExamplePlugin::ExamplePlugin()
|
||||
{
|
||||
// Create your members
|
||||
@@ -53,6 +77,11 @@ bool ExamplePlugin::initialize(const QStringList &arguments, QString *errorStrin
|
||||
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
|
||||
//! [add menu]
|
||||
|
||||
//! [register tests]
|
||||
#ifdef WITH_TESTS
|
||||
addTest<MyPluginTests>();
|
||||
#endif
|
||||
//! [register tests]
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -81,4 +110,18 @@ void ExamplePlugin::triggerAction()
|
||||
//! [slot implementation]
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
//! [exported function]
|
||||
int addOne(int i)
|
||||
{
|
||||
return i; // that is wrong!
|
||||
}
|
||||
//! [exported function]
|
||||
|
||||
} // namespace Example
|
||||
|
||||
//! [include moc]
|
||||
#ifdef WITH_TESTS
|
||||
#include "example.moc"
|
||||
#endif
|
||||
//! [include moc]
|
||||
|
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "example_global.h"
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
//! [namespaces]
|
||||
|
@@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
#if defined(EXAMPLE_LIBRARY)
|
||||
# define EXAMPLE_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
|
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "example_global.h"
|
||||
|
||||
namespace Example {
|
||||
|
||||
int EXAMPLE_EXPORT addOne(int i);
|
||||
|
||||
} // namespace Example
|
21
doc/qtcreatordev/examples/exampleplugin/tst_mytest.cpp
Normal file
21
doc/qtcreatordev/examples/exampleplugin/tst_mytest.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "examplefunctions.h"
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
class tst_MyTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void mytest();
|
||||
};
|
||||
|
||||
void tst_MyTest::mytest()
|
||||
{
|
||||
// a failing test
|
||||
QCOMPARE(Example::addOne(1), 2);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(tst_MyTest)
|
||||
|
||||
#include "tst_mytest.moc"
|
@@ -38,6 +38,12 @@
|
||||
\li \l{Distributing Plugins}
|
||||
\endlist
|
||||
|
||||
\section1 Topics
|
||||
|
||||
\list
|
||||
\li \l{Adding Tests}
|
||||
\endlist
|
||||
|
||||
\section1 Design Principles
|
||||
|
||||
\list
|
||||
|
103
doc/qtcreatordev/src/plugin-tests.qdoc
Normal file
103
doc/qtcreatordev/src/plugin-tests.qdoc
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\page plugin-tests.html
|
||||
\title Adding Tests
|
||||
|
||||
There are two main ways of testing your plugin code:
|
||||
|
||||
\list
|
||||
\li \l{Plugin Tests}
|
||||
\li \l{Auto Tests}
|
||||
\endlist
|
||||
|
||||
Both have their specific use cases and setup, which is described in the
|
||||
following sections.
|
||||
|
||||
\section1 Setting up CMake
|
||||
|
||||
Before adding tests, prepare your build files. They need to look for the
|
||||
QtTest dependency and have a CMake option for building your plugin with
|
||||
tests:
|
||||
|
||||
\snippet exampleplugin/CMakeLists.txt 5
|
||||
|
||||
\section1 Plugin Tests
|
||||
|
||||
Plugin tests are deeply integrated into your plugin and its
|
||||
interaction with \QC. To add a test for something that requires
|
||||
the infrastructure of \QC or your plugin to be set up, write a plugin
|
||||
test.
|
||||
|
||||
Plugin tests are executed by starting \QC with the \c{-test <pluginname>}
|
||||
command line argument. \QC then fully loads your plugin and all the plugins
|
||||
that it depends on, going through the normal \l{Plugin Life Cycle}. After
|
||||
your plugin and all dependencies are fully initialized, your tests are
|
||||
executed. Afterwards, \QC automatically closes. Therefore, your plugin
|
||||
tests have access to all exported functionality of all \QC plugins that
|
||||
your plugin depends on, like \c{Core::ICore}. Use QtTest's normal test
|
||||
macros, like \c{QVERIFY} or \c{QCOMPARE} to report your test's success or
|
||||
failure.
|
||||
|
||||
To add plugin tests, add a QObject based class with private slots for your
|
||||
tests, and register it with \l{ExtensionSystem::IPlugin::addTest()} in your
|
||||
plugin's \l{ExtensionSystem::IPlugin::initialized()} method. Guard all test
|
||||
related code with a check for \c{WITH_TESTS}, to avoid shipping a binary
|
||||
release of your plugin with test functions.
|
||||
|
||||
Include QtTest:
|
||||
|
||||
\snippet exampleplugin/example.cpp test include
|
||||
|
||||
Then implement the test functions:
|
||||
|
||||
\snippet exampleplugin/example.cpp plugin tests
|
||||
|
||||
Register your test in ExtensionSystem::IPlugin::initialize():
|
||||
|
||||
\snippet exampleplugin/example.cpp register tests
|
||||
|
||||
If you declared the test object in the source file, like in this example,
|
||||
also include the \c{.moc} file that is required for Qt's meta object
|
||||
compiler:
|
||||
|
||||
\snippet exampleplugin/example.cpp include moc
|
||||
|
||||
\section1 Auto Tests
|
||||
|
||||
To add a test that does not depend on a running \QC infrastructure, use an
|
||||
auto test that lives independent of your plugin interface. Parsers are a
|
||||
common example, but you can test many things in this way if they have been
|
||||
written in a modular way.
|
||||
|
||||
Even though your test does not live in your plugin interface,
|
||||
like with plugin tests, you can still link the test to libraries and also
|
||||
your plugin library itself, to avoid code duplication or duplicate
|
||||
compilation of code.
|
||||
|
||||
In principle you can use any auto test framework,
|
||||
but QtTest is a simple one that integrates well with Qt, and is also used
|
||||
for the \l{plugin tests}{Plugin Tests}.
|
||||
|
||||
To add your test, add the test's C++ file, and use \c{add_qtc_test} in your
|
||||
CMake file to add the test target. If your test uses your plugin library,
|
||||
add it as a dependency with \c{DEPENDS}.
|
||||
|
||||
In the following example, the plugin exports a function \c{addOne}:
|
||||
|
||||
\quotefile exampleplugin/examplefunctions.h
|
||||
|
||||
And implements it in a source file:
|
||||
|
||||
\snippet exampleplugin/example.cpp exported function
|
||||
|
||||
The test is linked against the plugin library target with \c{DEPENDS}:
|
||||
|
||||
\snippet exampleplugin/CMakeLists.txt 6
|
||||
|
||||
The QtTest based test then includes the header from the plugin and
|
||||
tests the function:
|
||||
|
||||
\quotefile exampleplugin/tst_mytest.cpp
|
||||
*/
|
Reference in New Issue
Block a user