これは
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が型名を表示してくれるので若干助かる?
書いてるうちに日付が変わってしまったZE