読者です 読者をやめる 読者になる 読者になる

C++と色々

主にC++やプログラムに関する記事を投稿します。

C++ Testing Framework Catchの紹介

C++

CatchとはC++のテスティングレームワークの1つです。ヘッダオンリーで使うことが出来ます!簡単!
https://github.com/philsquared/Catch

私はこちらのブログを拝見して知りました。
ブログズミ: C++ Testing Framework の Catch を使ってみた
Google Testなどと同じようにJUnit形式のxmlを出力することができるのでJenkinsでCIすることも可能です。

触ってみて私が感じたCatchの良い所は、

  • 構造化テストがとても書きやすい
  • JUnit4ライクなassertThatと(カスタム)Matcherがある
  • テストケース名が文字列なので日本語名が付けられる
  • タグを付けるのが簡単で、タグを限定したテストの実行が容易

まだよく分かっていないところと気になるところ

  • パラメータ化、型パラメータ化テストは書けるのか、書けるのなら書きやすいのか
  • 製作中のせいか、Matcherの数が少ない
  • ドキュメントが最低限しか無い

私は今Catchを趣味プログラミングで試用しています。
 最近JUnit4を勉強しまして、アノテーションやリフレクションを活かしたテスティングフレームワークでとても便利だと感じていました。JUnitではテストメソッド名に日本語を使う慣習もあるようです。私はJUnitで構造化テスト、パラメータ化テスト、ルール、assertThatとMatcherなどがとても便利に感じました。
 CatchはFixtureやxmlレポートもありますが、これらはGoogle Testなどにもあります。テストケースに日本語をつけることが出来たりassertThatがあることがJunit意識してるのかなと思いましたが、Boost TestやGoogle Testなどと比べて個人的にとても嬉しいです。

アンドキュメントでしたが、ソースコードを読みながら試しに自分でカスタムマッチャーを書いてみました。operator==で比較するisマッチャーを書いてみました。

サンプル

#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <catch_runner.hpp>

namespace Catch {
  namespace Matchers {
    template <typename T>
    class Is : public Impl::MatcherImpl<Is<T>, T> {
    private:
      T const& expected;

    public:
      Is(T const& expected)
        : expected(expected) {}
      Is(Is const& other)
        : expected(other.expected) {}

      bool match(T const& actual) const override {
        return expected == actual;
      }

      std::string toString() const override {
        std::ostringstream oss;
        oss << "is actual. but it was expected \"" << std::boolalpha << expected << "\"";
        return oss.str();
      }
    };

    template <typename T>
    Is<T> is(T const& expected) {
      return Is<T>(expected);
    }
  }
}

#include <vector>

TEST_CASE("vector", "[vector]")
{
  using namespace Catch::Matchers;
  std::vector<int> sut;

  SECTION("要素が空の時", "[empty]")
  {
    REQUIRE_THAT(sut.empty(), is(true));
    REQUIRE_THAT(sut.size(), is(0));
  }

  SECTION("要素が1件ある時")
  {
    sut.push_back(1);

    REQUIRE_THAT(sut.empty(), is(false));
    REQUIRE_THAT(sut.size(), is(1));
    REQUIRE_THAT(sut[0], is(1));
  }

  SECTION("要素が2件ある時")
  {
    sut.push_back(1);
    sut.push_back(2);

    REQUIRE_THAT(sut.empty(), is(false));
    REQUIRE_THAT(sut.size(), is(2));
    REQUIRE_THAT(sut[0], is(1));
    REQUIRE_THAT(sut[1], is(2));
  }
}

実行結果

All tests passed (9 assertions in 1 test case)

続行するには何かキーを押してください . . .