10
8

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 5 years have passed since last update.

AltPlusAdvent Calendar 2017

Day 13

テーブル駆動テスト in C++

Posted at

この記事はAltplus Advent Calendar 2017の13日目のエントリです。

最近なぜかJava関連のアカウントにTwitterでフォローされることが多い、JavaマスコットのDukeを愛してやまない竹田です。

テーブル駆動テスト

今回は、Go wikiで紹介されて、Goコミュニティでよく使われている(?)テーブル駆動開発をC++でやってみたいと思います。

テーブル駆動テストとは、テストの入力と期待値をテーブルの行に記載し、テーブルを走査しながら実行していくテストのことです。

例えば、int型の入力を受け取って、2倍する関数int twice(int x)のテスト・テーブルは以下のようになります。

in(入力) out(出力)
0 0
1 2
2 4

このテーブルを使って、テーブル駆動テストを書くと以下のようになります。

#include <cassert>

int twice(int x){
    return x * 2;
}

int main()
{
   struct { int in; int out; } table[]{
       {0, 0},
       {1, 2},
       {2, 4}
   };
    
   for(auto [in, out]: table){
    assert(twice(in) == out);
   }
}

テスト・ケース毎にAssertを書く必要がなくなり、テーブルに入出力がまとめられているため、関数の入出力仕様に集中することができます。入出力で仕様が決定される純粋な関数のテストに役立ちます。

関数の引数が増えてもテーブルの列を追加するだけで対応できます。文字列とインデックスを取って、インデックス番目の文字を返すat関数のテーブルは、

文字列(in1) インデックス(in2) 文字(out)
"abc" 0 'a'
"Hello" 3 'l'
"Hello world!" 7 'r'
#include <cassert>
#include <string_view>

char at(std::string_view s, int index){
    return s[index];
}

int main()
{
   struct { char const* str; int index; char out; } table[]{
       {"abc", 0, 'a'},
       {"Hello", 3, 'l'},
       {"Hello world!", 7, 'o' }
   };
    
   for(auto [s, i, out]: table){
    assert(at(s, i) == out);
   }
}

最後に

テーブル駆動テストを利用すると、関数の入出力仕様にフォーカスしたテスト・ケースを見通しよく記載することができます。

C++の"unnamed struct"(テーブルの定義に利用している名前なしのstruct)、"range-based for"、"structured bindings"を利用して、快適なテーブル駆動テストにしましょう!

10
8
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
10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?