Qt Creator Autotest Plugin について

  • 4
    いいね
  • 0
    コメント

はじめに

今回で3回目の投稿となります、ynuma です。
驚いたことに、去年のアドベントカレンダーも 12/21 に投稿しておりました。
ちょうど一年ぶりとなりますので、近況を簡単に書かせていただきます。
普段は、相変わらずHWの仕事を中心に行っております。
SWの方は、HWの評価用に簡単なクラスを作るくらいですが、常に新しい技術を勉強していきたい、と思っています。

本題になりますが、今回のテーマは昨年に引き続き Qt Test についてです。
昨年は、主に Qt Test Unit Test Framework の基本的な使い方についてまとめました。
詳細は、前回の記事を参照ください。
http://qiita.com/ynuma/items/b728c613e003b69e23a5

今回はそれをさらに拡張した Qt Creator AutoTest Plugin の使い方についてまとめます(以下、AutoTest Plugin と略します)。

Autotest Plugin について

簡単にいってしまうと Qt Creator 上で動作するテストの自動化を行うための管理ツールです。
自動テストというと Jenkins のようなサーバーとして動作する CI ツールを思い浮かべる方が多いのではないかと思いますが、今回ご紹介するのは、Qt Creator 上で動作する Plugin で、Qt Creator のビルド実行後に、テストを実行・管理するツールです。
初期インストール後は使用できない状態でないので、プラグインを追加する必要があります(後述)。

対象のバージョン

私が昨年の原稿を書いた時にインストールした Qt Creator v3.5.1 では、下図の通りプラグインの項目に Autotest が出てきません!
スクリーンショット 2016-12-20 5.26.17.png

この機能の存在を知ったのは、友人の @hermit4 氏から教えていただいたからで、自力ではなかなか気がつかなかったのではないかと思います。
いったい、どのバージョンから使えるのでしょうか?
ちょっと気になったので、Qt project の GitHub を調べてみました。

History for qt-creator/src/plugins/autotest の一番古い commit ログが、
2016/1/22 となっています。
この後リリースされた Qt Creator の バージョンが、v3.6.1(2016/3/16)
です。その次は、
v4.0.0-beta1(2016/3/23)
です。

3.6.1 リリース直後に Bugfix も行われているようなので、実質 4.0 以降で使えるものと思っていただければよいかと思います。

この記事の作成に使用した Qt Creator のバージョン

この記事は、v4.1.0 を使用して記述しています。
12/14(Wed) に、v4.2.0 がリリースされていたのを投稿直前になって知りました。
非常に残念ですが、今回は時間がないので、v4.2.0 については触れません。

注目すべき点

昨年記事を書いた時点で、既に Qt unit test というものが提供されていました。
これは、1 つのプロジェクトという扱いで、IDE として使用するには少し物足りない感じでした。
他のプロジェクトファイルと同様にテストのソースコードをビルドして、実行するという流れでした。
複数のテストケースを実行する場合に、ユーザーがコードやプロジェクトを選択・変更してテストを実施する必要がありました。

Autotest Plugin では、Qt Creator 上に、プロジェクトとは別の "テスト" というメニューが追加されています。
具体的には、複数のテストケースを GUI から選択して実行したり、前述のような一般的な CI ツール風に使用できるようになりました。

テストのフレームワークは、Qt Test, Quick Test, Google Test を選択できます。

使用するための準備

使用するためには、Qt Creator Plugin に Autotest を追加する必要があります。
メニューバーの
Qt Creator → プラグインについて
と操作すると、下図のようなインストール済みプラグインの一覧が表示されます。
このリストの中の下部にユーティリティという項目があり、その中の AutoTest を選択します。
もし、この AutoTest という項目が現れない場合は、Qt Creator を update してください。

スクリーンショット 2016-12-19 6.30.11.png

この後、Qt Creator の再起動が必要です。
*見逃す可能性がありますが、一応ダイアログの下部に再起動を促すメッセージが表示されています。

Testcase 作成方法

実際にテストケースの作り方について、説明します。
メニューバーから

ファイル → ファイル/プロジェクトの新規作成

と操作すると、下記ダイアログが表示されます。

スクリーンショット 2016-12-20 5.35.43.png

プロジェクト → 他のプロジェクト→ Auto Test Project

と選択し、選択ボタンを押します。
下図の通りプロジェクトパスの設定ダイアログが表示されます。

スクリーンショット 2016-12-20 5.41.31.png

プロジェクト名とパスを選択し、続きを押します。
下図の通り、Project and Test Information ダイアログが表示されます。

スクリーンショット 2016-12-20 5.43.38.png

お好みの設定を行います。
今回の説明では、Test Framework は Qt Test、GUI Application などのチェックボックスはすべて選択しました。
Test Case Name は何でも構いません。
Build auto tests の選択については、存在理由が理解できていないのですが、とりあえず always としておきます(アプリをビルドする度に毎回 Test が実行されると思ったのですが、そのような動作は行われませんでした)。
続きを押すと、下図の通り、キットの選択画面が表示されます。

スクリーンショット 2016-12-20 6.16.58.png

今回は、このまま続きを押します。
下図の通り、プロジェクト管理画面が表示されます。

スクリーンショット 2016-12-20 6.20.27.png

適宜設定して、終了を押します。
下図の通り、case11 という名前の testcase が含まれた空の Project が作成されます。

スクリーンショット 2016-12-20 6.22.40.png

この後、Unit test を作るときと同様に、テストケースを記述していきます。

testcase 実行方法

testcase が作成できたら、テストを実行します。
まずは、サイドバーにテストというメニューが追加されているので、そちらを表示してみましょう。

pict1.png


スクリーンショット 2016-12-20 6.29.51.png

このような感じで、一般の IDE 風にテストケースの選択画面が出てきます。
下図のように、サイドバーの上段にプロジェクト、下段にテストというレイアウトが作業しやすいかと思います。サイドバーに複数の画面を表示させるには、サイドバーのアイコンの スクリーンショット 2016-12-20 6.46.14.png ボタンを押します。

スクリーンショット 2016-12-20 6.47.56.png

テストケースを選択して、Qt Test の箇所を右クリックし、選択したテストの実行をクリックすれば、必要なテストだけ選択実行できます。
もちろん、すべてのテストの実行も選択できます。

pict2.png

実行結果について

先ほどの画面の右下の部分にアプリケーション出力が表示されています。
ここには、Unit Test の結果が表示されます。
この他に、Window 下部の
8 テスト結果
を選択すると、IDE 風に欠ケース毎の Pass/Fail 結果のみが表示されます。

スクリーンショット 2016-12-20 6.41.31.png

その他の設定について

メニューバーの Qt Creator → 設定... と選択すると、以下のような各種設定 Diaglog が表示されます。

スクリーンショット 2016-12-20 20.38.18.png

左側のメニューリストから、”QAテスト設定” という項目を選択すると、Autotest に関する詳細設定を行うことが可能です。

例えば、結果の出力を制限するとか、テストのフレームワークを表示させないようにすることができるようです。
また、ここでベンチマーク測定機能の設定も行えるようです。
経過時間だけでなく、ティックカウンタ(組み込み向け?)やイベントカウンタなど、かなり凝った測定も行えるようになっているようです。

加えて、Google Test の設定も変えられるようです。

こういった細々した内容の設定をマニュアルでやる場合は、深い知識と時間が要求されますが、このように UI から簡単に選択できるようになったのは、大変便利になったのではないか、と思います。

UIアプリテスト例

実際に簡単なUIアプリケーションのテストを書いてみました。
アプリケーションは、下記コードの通り、MainWindow に3つの sinewave を表示する単純なものです。

スクリーンショット 2016-12-20 20.33.09.png

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    double calcRadian(const int x, const int points);
    int showSineWave(const int waves, const int xStart, const int xStop, const int yTop, const int yOffset);

protected:
    void paintEvent(QPaintEvent *);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <math.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

double
MainWindow::calcRadian(const int x, const int points)
{
    const double Pi = 3.14;
    return double(2 * Pi * (x % points) / (points - 1));
}

int
MainWindow::showSineWave(const int waves, const int xStart, const int xStop, const int yTop, const int yOffset)
{
    if (waves < 0 || xStart < 0 || xStop < 0 || yTop < 0 || yOffset < 0)
    {
        return -1;
    }

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(QPen(Qt::red, 8, Qt::SolidLine, Qt::RoundCap));

    const int pointsPerWave = (xStop - xStart) / waves;
    for (int x = xStart; x <= xStop; ++x)
    {
        int y = yTop * sin(calcRadian(x, pointsPerWave)) + yOffset;
        painter.drawPoint(x, y);
    }

    return 0;
}

void
MainWindow::paintEvent(QPaintEvent *)
{
    showSineWave(1, 100, 700, 75, 100);
    showSineWave(2, 100, 700, 70, 300);
    showSineWave(4, 100, 700, 65, 500);
}

MainWindow::~MainWindow()
{
    delete ui;
}

■ テストコード

このテストコードは、MainWindow Class の public method の unit test case です。
また、UI の目視確認ができるように Window をわざと表示させています。
最初の思惑としては、画面のスクリーンショットを期待値として、画像を比較チェックするつもりでしたが、あまり凝ってもわかりにくくなるので、今回はそこまでしません。

tst_case1.cpp

#include <QtTest>
#include <QCoreApplication>

// add necessary includes here
#include "/Users/ynumajir/WidgetApp/autotest/src/mainwindow.h"
#include <unistd.h>

class case1 : public QObject
{
    Q_OBJECT

public:
    case1();
    ~case1();

private slots:
    void initTestCase();
    void cleanupTestCase();
    void test_case1();

};

case1::case1()
{

}

case1::~case1()
{

}

void case1::initTestCase()
{

}

void case1::cleanupTestCase()
{

}

void case1::test_case1()
{
    MainWindow mainWin;
    mainWin.show();
    sleep(1);
    QVERIFY(-1 == mainWin.showSineWave(-1, -1, -1, -1, -1));
    QVERIFY(0 == mainWin.calcRadian(0, 201));
    QVERIFY(3.14 == mainWin.calcRadian(100, 201));
}

QTEST_MAIN(case1)

#include "tst_case1.moc"

テストを実行すると、すべて Pass します。
もし興味がありましたら、実行してみてください。

参考リンク

この投稿は Qt Advent Calendar 201621日目の記事です。