2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

QtAdvent Calendar 2019

Day 18

QtのDataDrivenTestでstd::size_tとかを(比較的?)ストレスなく使う

Posted at

これは

Qt Advent Calendar 201918日目の記事です

昨日は@task_jpさんのQML の一部を別の QML で差し替える方法でした

課題やってたらこんな時間になっちゃった 急いで書かなきゃ(18日23時40分)

さて

みなさんQtのソフトウェアでのTestって何でやってらっしゃるんですかね?
私はとりあえずQt標準のTestで行っています
多くのテストフレームワークと同様にQtのテストフレームワークにもDataDrivenTestの機能が備わっています

公式のサンプルにはこんな例が乗っています

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";
}

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

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

addColumnテストデータのカラムの型を指定して
newRowでテストデータの値を登録していますね

で、

さっきのサンプルを見ればわかるとおり(?)、
addColumnで登録した型の情報はnewRowの式で参照することができないので、プログラマが間違えるとこんなものも書けてしまいます

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

    QTest::newRow("hoge") << "hello" << 1; // "result"の型がおかしい
}

まあこれくらいならエラーを見てすぐ気づくことができますが、std::size_tを渡そうとしたときで

void TestQString::toUpper_data()
{
    QTest::addColumn<HogeHogeData>("data");
    QTest::addColumn<std::size_t>("size");

    QTest::newRow("hoge") << .... << 1; // 1の型はintになる
}

これは突然expected data of type 'ulong', got 'int' for element 0 of data with tag 'hoge'とか吐いて死ぬことになる

仕方なくすべてのリテラルにsuffixをつけて回るのは非常に面倒だしすぐ忘れる

C++erなら型は気にしないとね!

というわけでこうする

要はnewRowのときに型がわかればいいので

namespace test {

template <class>
struct Column
{
    Column(const char* name) : str(name) {}
    const char* str;
};

template <class... Args>
struct DDTest
{
    DDTest(Column<Args>... cols)
    {
        (QTest::addColumn<Args>(cols.str), ...);
    }
    void newRow(const char* name, Args... args)
    {
        (QTest::newRow(name) << ... << args);
    }
};
template <class... Args>
DDTest(Column<Args>...)->DDTest<Args...>;

} // namespace test
void TestClass::HogeHoge_test_data() {
    test::DDTest dataTest(
        test::Column<std::size_t>("limit"),
        test::Column<std::size_t>("count"));

    dataTest.newRow("10000", 10'000, 1'000'000);
    dataTest.newRow("10000", 20'000, 1'000'000);
    dataTest.newRow("10000", 40'000, 1'000'000);
    dataTest.newRow("10000", 80'000, 1'000'000);
}

rowのラベルとデータが同じカッコ内に並ぶのはちょっと不格好だが、これで型が違うことを防げる(不格好なのはまあどうにでもなる(やってないけど))

ついでに入力中にIDEが型名を表示してくれるので若干助かる?
Screenshot from 2019-12-19 00-15-59.png

書いてるうちに日付が変わってしまったZE

明日は

@cod-sushiさんのQtで作ったスクリーンショット作成アプリケーションについて紹介 です

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?