C ++用テストデータジェネレーター

画像







コードを単体テストするとき、遅かれ早かれテストデータの問題が生じます。 そして、ある場合には少数のハードワイヤード変数で十分であれば、他の場合には、大規模でランダムなデータが必要になります。 制御された世界では、カスタムタイプを生成するのに問題はありません(同じAutofixtureを使用します)が、C ++の世界はしばしば痛みと苦痛を引き起こします(そうでない場合は修正してください)。 少し前に、私は素晴らしいboost :: diライブラリに精通し、その影響を受けて、C ++プログラマがランダムな値で詰まったカスタムデータ型を生成できるライブラリの概念が熟し始めました。これは予備的な説明を必要としません。 次のようになりました:







struct dummy_member{ float a; int b; }; struct dummy{ explicit dummy(dummy_member val, std::string c) : val_(val), c_(c) {} private: dummy_member val_; std::string c_; }; int main(int argc, char* argv){ auto d = datagen::random<dummy>(); return 0; }
      
      





コードにリンクします 。 ヘッダーのみのライブラリ、C ++ 14。 猫に興味がある人はみんな聞いてみてください。







主なライブラリ機能





インライン型生成



組み込み型(char、wchar_tなど)の生成は当然サポートされています。 この場合、整数型は単にビットのセットとして生成され、floatとdoubleはランダムな整数(それぞれ、int32_tとint64_t)と-1から1の範囲のランダムな値の合計として生成されます。ブール値を生成するには、2つのランダムな整数の比較が使用されます。







 std::cout << "The answer to the question of everything is:" << datagen::random<int>() << std::endl;
      
      





カスタムタイプの生成。



カスタムタイプを生成するために、boost :: di(その作成者に感謝)と同じアイデアが使用されました。つまり、普遍的な型any_typeを記述する可能性があります。 LITTLEテンプレートを追加すると、次のツールを使用してカスタムタイプを生成することが判明しました。







  1. ユーザー定義の生成アルゴリズム。
  2. 最大数のパラメーターを持つパブリックコンストラクターに基づく生成。 すべてが記事の冒頭の例のようになります( struct dymmy



    )。
  3. {}-初期化に基づいた生成。 すべてが最初の例( struct dummy_member



    )と同じです。


ユーザー定義の手順に基づいてオブジェクトを生成するには、テンプレートを部分的または完全に特化する必要があります







 template<> struct datagen::value_generation_algorithm<TType> { TType get_random(random_source_base&); };
      
      





これにより、このクラスの一部の型生成パラメーターメンバーを作成する機能が追加され、型生成に影響を与えることができます。 たとえば、std行生成アルゴリズムは次のようになります。







 namespace datagen{ template <class CharType, class Traits, class Allocator> struct value_generation_algorithm<std::basic_string<CharType, Traits, Allocator>>{ using string_t = std::basic_string<CharType, Traits, Allocator>; string_t get_random(random_source_base& r_source){...}; size_t min_size{0}; size_t max_size{30}; std::basic_string<CharType> alphabet{"abcd...6789"}; }; }
      
      





生成された値のセットのリミッター



ライブラリは、生成された値のリミッターをサポートします。例:







 std::cout << "The answer to the question of everything is:" << random<int>(between(42,42)) << std::endl;
      
      





リミッターには次の2種類があります。







  1. 生成アルゴリズムのリミッター。 彼らの助けを借りて、 value_generation_algorithm<T>



    クラスのパラメーター値を変更できます。
  2. すでに生成された値へのリミッター(むしろ修正子)。


この場合、 2つの方法で使用できます







  1. 上記の例のように、それらをパラメーターとしてランダム関数に渡します。 この場合、それらは現在のアルゴリズム/値にのみ適用されます。
  2. scoped_limit



    基づいてscoped_limit



    を作成scoped_limit



    、それを一連の型に適用します。 その後、scoped_limitの有効期間中、生成されたタイプツリーの深さ全体に対して、指定されたすべてのタイプにリミッターが適用されます。


カスタム区切り文字を作成するには、区切り文字構造/クラスを宣言し、一方または両方の機能を実装する必要があります。







 struct dummy_algorithm_limit{}; struct dummy_value_limit{}; namespace datagen{ namespace limits { void adjust_algorithm(random_source_base&, dummy_algorithm_limit const& l, value_generation_algorithm<dummy>& a){ //      dummy } void adjust_value(random_source_base&, dummy_value_limit const& l, dummy& a){ //     dummy } } }
      
      





制限は次の順序で適用されます。







  1. アルゴリズムのscoped_limit
  2. アルゴリズムごとのパラメトリックリミッター

    これがオブジェクトツリーの生成です
  3. 値のscoped_limit
  4. 値のパラメトリックリミッター


一般的な情報



ライブラリのエントロピーのソースは、 <random>



を使用するrandom_source_implクラスです。 ただし、コンパイル段階でrandom_source_instance<int>



構造の特殊化を提供することにより、これをオーバーライドできます。

今日、stlからの次のコンテナの生成が実装されています(実際に作業する必要があるもの)。









ブーストのタイプのペア:









それらのリミッター:









msvc-14.0コンパイラでテストされ、c ++ 14が必要です。 残念ながら、gccの動作は少し異なります。その結果、ライブラリのコードはmingw(gcc-6.3.0)でコンパイルされませんでしたが、それと絶えず接触している人はすぐに修正できると思います。

ライブラリはパブリックドメインにあります 。 新しいタイプのアイデアと実装は大歓迎です。








All Articles