Help us understand the problem. What is going on with this article?

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

これは

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で作ったスクリーンショット作成アプリケーションについて紹介 です

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした