第2章 データ駆動型テスト

この章では、異なるテストデータを使ってテストを複数回実行する方法を示します。

これまでのところ、テストしたいデータをテスト関数にハードコーディングしてきました。さらにテストデータを追加すると、関数はこのようになります:

QCOMPARE(QString("hello").toUpper(), QString("HELLO"));
QCOMPARE(QString("Hello").toUpper(), QString("HELLO"));
QCOMPARE(QString("HellO").toUpper(), QString("HELLO"));
QCOMPARE(QString("HELLO").toUpper(), QString("HELLO"));

繰り返しのコードで関数がごちゃごちゃになるのを防ぐために、Qt Test はテスト関数にテストデータを追加することをサポートしています。必要なのは、テストクラスにもうひとつプライベートスロットを追加することだけです:

class TestQString: public QObject
{
    Q_OBJECT

private slots:
    void toUpper_data();
    void toUpper();
};

データ関数を書く

テスト関数に関連するデータ関数は、その名前に_data 。私たちのデータ関数はこのようになります:

void TestQString::toUpper_data()
{
    QTest::addColumn<QString>("string");
    QTest::addColumn<QString>("result");

    QTest::newRow("all-lower") << "hello" << "HELLO";
    QTest::newRow("mixed")     << "Hello" << "HELLO";
    QTest::newRow("all-upper") << "HELLO" << "HELLO";
}

まず、QTest::addColumn ()関数を使って、テストテーブルの2つの要素を定義します。テスト文字列と、その文字列にQString::toUpper ()関数を適用した場合の期待される結果です。

次に、QTest::newRow ()関数を使用してテーブルにデータを追加します。また、多くのデータ行を繰り返し生成する場合など、行名に何らかのデータの書式を設定する必要がある場合にも、QTest::addRow ()を使用することができます。データの各行は、テスト・テーブルの個別の行になります。

QTest::newRow() は1つの引数を取ります:データセットに関連付けられ、データ行を識別するためにテストログで使用される名前です。QTest::addRow() は、(printf-style)書式文字列の後に、書式文字列の書式トークンの代わりに表現されるパラメータを取ります。次に、データセットを新しいテーブル行にストリームする。最初に任意の文字列、次にその文字列にQString::toUpper()関数を適用した結果の期待値。

テスト・データは2次元のテーブルと考えることができる。この場合、stringresult という2つの列と3つの行がある。また、各行には名前とインデックスが関連付けられている:

インデックス名前文字列結果
0全下位"こんにちは"ハロー
1ミックス「ハローこんにちは
2オール・アッパー「ハローHELLO

データが行にストリームされると、各データムは、その値が供給される列の型と一致するようにアサートされる。アサーションが失敗した場合、テストは中断される。

もし2つの行が同じ名前であったり、2つの列が同じ名前であったりすると、(Qt 6.5以降)警告が表示されます。警告をエラーとして扱う方法についてはqWarning() を、他の警告からテストをクリアする方法についてはTest for Warningsを参照してください。

テスト関数の書き換え

テスト関数を書き直すことができます:

void TestQString::toUpper()
{
    QFETCH(QString, string);
    QFETCH(QString, result);

    QCOMPARE(string.toUpper(), result);
}

TestQString::toUpper() 関数は、関連する TestQString::toUpper_data() 関数で作成したテストテーブルの各エントリに対して 1 回ずつ、計 3 回実行されます。

最初に、QFETCH() マクロを使用して、データセットの2つの要素を取得します。QFETCH() は2つの引数を取ります:要素のデータ型と要素名です。次に、QCOMPARE() マクロを使用してテストを実行します。

この方法により、テスト自体に変更を加えることなく、新しいデータをテストに追加することが非常に簡単になります。

スタンドアロン実行ファイルの準備

テストケースをスタンドアロン実行ファイルにするには、次の2行が必要です:

QTEST_MAIN(TestQString)
#include "testqstring.moc"

前回と同様に、QTEST_MAIN() マクロは、すべてのテスト関数を実行する単純な main() メソッドに展開されます。テストクラスの宣言と実装の両方が .cpp ファイルにあるので、Qt のイントロスペクションを動作させるために、生成された moc ファイルもインクルードする必要があります。

実行ファイルのビルド

テストケースの実行ファイルは、CMake または qmake を使ってビルドすることができます。

CMakeでビルドする

CMakeLists.txt ファイルでビルド設定を行います:

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

cmake_minimum_required(VERSION 3.16)
project(tutorial2 LANGUAGES CXX)

find_package(Qt6 REQUIRED COMPONENTS Core Gui Test Widgets)

qt_standard_project_setup()

qt_add_executable(tutorial2
    testqstring.cpp
)

set_target_properties(tutorial2 PROPERTIES
    WIN32_EXECUTABLE TRUE
    MACOSX_BUNDLE TRUE
)

target_link_libraries(tutorial2 PRIVATE
    Qt6::Core
    Qt6::Gui
    Qt6::Test
    Qt6::Widgets
)

install(TARGETS tutorial2
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

qt_generate_deploy_app_script(
    TARGET tutorial2
    OUTPUT_SCRIPT deploy_script
    NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

次に、コマンドラインからcmake を実行するか、Qt-prefix/<version>/<platform>/bin/qt-cmake にあるqt-cmake 便利スクリプトを使用します:

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

次に、お好みのジェネレーター・ツールを実行して実行ファイルをビルドします。ここではNinjaを使っています:

ninja

qmakeでビルドする

.pro ファイルでビルド設定を行います:

QT += widgets testlib

SOURCES = testqstring.cpp

# install
target.path = $$[QT_INSTALL_EXAMPLES]/qtestlib/tutorial2
INSTALLS += target

次にqmake を実行し、最後にmake を実行して実行ファイルをビルドします:

qmake
make

実行ファイルの実行

出来上がった実行ファイルを実行すると、以下のような出力が得られるはずだ:

********* Start testing of TestQString *********
Config: Using QtTest library %VERSION%, Qt %VERSION%
PASS   : TestQString::initTestCase()
PASS   : TestQString::toUpper(all-lower)
PASS   : TestQString::toUpper(mixed)
PASS   : TestQString::toUpper(all-upper)
PASS   : TestQString::cleanupTestCase()
Totals: 5 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms
********* Finished testing of TestQString *********

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.