ラベル testing framework の投稿を表示しています。 すべての投稿を表示
ラベル testing framework の投稿を表示しています。 すべての投稿を表示

2020年12月1日火曜日

[C++] Concepts で外部ライブラリの template よりも優先されるオーバーロード関数を書く

※この記事は C++ Advent Calendar 2020 一日目の記事です。

はじめに

 C++20 で Concepts が導入されました。
コンセプト - cpprefjp C++日本語リファレンス

コンセプトはテンプレートパラメータを制約する機能で、「コンセプトによって関数オーバーロードやテンプレート特殊化」ができます。
今までテンプレート関数のオーバーロードを書く場合は SFINAE などのテクニックを使って書いていたと思いますが、コンセプトで書きやすくなりました。
これも大きな変化の1つですが、コンセプト関数が通常の関数よりも優先して lookup されるのも便利になった点の1つです。
コンセプトによるオーバーロードの場合、コンセプト関数が通常の関数よりも優先して lookup され、要件を満たすコンセプト関数がなかったら他の候補を探しに行きます。SFINAE では優先順位がつけられないケースでもコンセプトなら可能になりました。

どういうこと?
SFINAE では解決できなかった優先順位問題とコンセプトを使った実装の例

↑こちらは、std::cout << できない型の場合は "unknown" を出力するようにしようとしている様子です。

donot-change.h には std::cout するだけの template 関数 print があります。
こちらは変更ができない想定です。(外部ライブラリとか)

SFINAE.cpp では頑張って、 std::cout ができない場合で特殊化しオーバーロードしようとしてます。他の書き方を書いたりもしましたが、どうしても ambiguous になってしまって条件を満たすことができませんでした。

一方 Concepts.cpp は printable ではないコンセプト制約でオーバーロードするだけで実現できています。
すごく簡単ですね。

ちなみに
ちなみに donot-change.h を変更可能とした場合は、以下のように書くことができます。
namespace printer_internal
{
template<typename Elem, typename Traits, typename T>
::std::basic_ostream<Elem, Traits>& operator << (::std::basic_ostream<Elem, Traits>& os, const T&)
{
    return os << "unknown";
}
}

// 解決順序
// foo::operator <<
// ::operator <<
// ::printer_internal::operator <<
template<typename T>
void print(const T& val)
{
    using namespace ::printer_internal;
    ::std::cout << val << ::std::endl;
}
これは ADL の解決順序を利用して実現しています。
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ https://wandbox.org/permlink/rlQoH37cvYTI23qo 
使い所は?
例でも示したとおり、オーバーロードしたい対象の関数を変更できるのであれば、そちらで解決する方法を模索するのが良いと思います。
ただ、外部ライブラリなど変更することができない場合、非侵入的に解決する方法として覚えておくと役に立つ日が来るかもしれません。

実例
そもそも私がなんで外部ライブラリの挙動をオーバーロードで変更したいと思ったのかというと、以下の理由でした。

* Google Test はアサーションが失敗すると、そのときの値を出力します
* std::cout できない場合はバイト列を出力します
* できない場合の対応は「ちなみに」の ADL を利用した方法で実現されています
* 古い Google Test ではこの機能がない
* 自作テスティングフレームワーク iutest は Google Test と互換性がある
* iutest は Google Test の拡張機能としての一面もある
* 古い Google Test と iutest の組み合わせでも不明な型を printable にしたい
* Google Test 側のコードは書き換えられない
* どうしよう

実際にコンセプトで対応してる部分はこちらになります。
最後に
教えていただいた いなむのみたま(@mitama_rs) 先生ありがとうございました。
ちなみにそのツイートにもぶら下がってますが、C++20 未満のコンパイラでこの問題を解決する方法も募集しておりますmm


2020年7月28日火曜日

iutest v1.17.1 をリリースしました

C++ テスティングフレームワーク iutest v1.17.1 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.net/projects/iutest/releases/p12829

変更点は以下の通りです。

* New
* GTEST_SKIP 対応
* IUTEST_*_NE_RANGE アサーションを追加
* IUTEST_*_NE_COLLECTIONS アサーションを追加

* Improved
* ::std::wstring_view / ::std::u16string_view / ::std::u32string_view 対応
* Variadic Templates 非対応コンパイラーでの型パラメータの型表示を改善

* Changes
* アサーションに operator << したときの出力を PrintToString したものと同じになるように変更
* iuwandbox: Wandbox 向けにサイズ圧縮したヘッダーをデフォルトで使用するように変更
* iuwandbox: 上記に伴いフルバージョンのヘッダーを使うオプション(--no-iutest-use-wandbox-min)を追加
* deprecated: iuwandbox: --iutest-use-wandbox-min
* Python2 のサポート終了

* Bug fixes
* C++20 で削除された basic_ostream::operator << に対応
* IUTEST_AP が同じ名前空間に複数定義できない問題を修正
* Google Test 旧バージョンとの互換性を修正
* その他いくつかの不具合を修正



では。

2019年11月13日水曜日

iutest v1.17.0 をリリースしました

C++ テスティングフレームワーク iutest v1.17.0 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.net/projects/iutest/releases/71920

変更点は以下の通りです。

* New
* ::std::string_view 対応
* ::std::filesystem 対応
* FreeBSD 対応
* ALMOST_EQ アサーション を追加
* --iutest_locale_ctype オプションを追加

* Improved
* setlocale(LC_CTYPE, IUTEST_FLAG(locale_ctype)) をテスト実行開始時に行うように修正
* Visual Studio 2019 対応

* Changes
* 大きな配列/コンテナ/オブジェクトの pinter を修正
* iutest_main で setlocale していたものを廃止
* junit xml 出力で出力するテストが 0 だった場合にファイル書き出ししないように修正
* CSV パラメータ生成でファイルオープン失敗した場合の警告レベルを FATAL から WARNING に変更
* CSV パラメータ生成で要素がなかった場合に WARNING 出力
* deprecated: IUTEST_USE_OWN_LIST

* Bug fixes
* いくつかの不具合を修正


一応、v1.17 になって C++17 に対応した。という体でリリースしてます。
ホントはいろいろ足らない気がしてますが、ひとまず filesystem と string_view の対応はできると思います。
実際に使用してみたら、全然使い物にならない・・ってこともあるかもしれないので、issue 報告お待ちしております。

では。

2018年10月25日木曜日

iutest v1.16.7 をリリースしました

C++ テスティングフレームワーク iutest v1.16.7 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.net/projects/iutest/releases/70218

1.16 系は終わったと言ったな。。。あれはウソだ!

変更点は以下の通りです。
* Improved
  *  iuwandbox: コードサイズをさらに削減したヘッダーファイルに対応(--iutest-use-wandbox-min)

* Bug fixes
  * 古い google mock の互換性エラー修正
  * いくつかの不具合を修正

今回は主に、iuwandbox で利用する iutest.min.hpp のさらなる圧縮をした iutest.wandbox.min.hpp を使用するオプションを追加しました。
こちらの機能は試験的機能となっております。
問題なさそうであれば 1.17 系でデフォルトになる予定です。







もともと 600KB 近くあったのを、500KB 以下まで削減しました。
(↑は develop ブランチの計測なので、v1.16.7 だと少し違うかも。)

できあがった iutest.wandbox.min.hpp を見えもらえるとわかると思うのですが(Gist においておきました)、
iutest.min.hpp には、主に「構文の許す限りのインデントや改行削除」を行っていたのですが、iutest.wandbox.min.hpp では「内部マクロの名前省略」「Wandbox にない OS/Compiler 向け Config 削除」をしました。

iutest.min.hpp を作ったときの記事は以前書いているのでそちらも見ていただくとなにをしているかが、よりわかると思います。


今回の Wandbox 向けの圧縮はまた別途まとめて記事にしたいと思います。
(ローカル変数名とか、公開している部分でなければもっと名前の省略はできると思う)
(同一で連続したアクセス修飾子は消しても大丈夫なはずなので、そこも削れるはず)
(独自のリストクラスを使ってる部分をやめたらかなり減らせると思う。v1.17 でやる予定)

2018年9月19日水曜日

iutest v1.16.6 をリリースしました

C++ テスティングフレームワーク iutest v1.16.6 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.net/projects/iutest/releases/70056

変更点は以下の通りです。
* Improved
  * Matcher に (NanSensitive)FloatNear/DoubleNear を追加
  * Matcher に template 版の浮動小数点数比較を追加・(NanSensitive)FloatingPointEq/FloatingPointNear
  * long double に対応
  
* Changes
  * iuwandbox: -D__WANDBOX__ コンパイラーオプションを必ずつけるように変更

* Bug fixes
  * iuwandbox: dryrun オプションが失敗を返す問題を修正
  * いくつかのコンパイラー警告を修正

さて、1.16 系は今回で最後のリリースとなります。(なんもなければ…)
先行で対応開始していた C++17 対応を develop に取り込み、version 1.17 を目指して開発して参りますmm

2018年8月6日月曜日

iutest v1.16.5 をリリースしました

C++ テスティングフレームワーク iutest v1.16.5 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.net/projects/iutest/releases/69879

変更点は以下の通りです。
* Improved
  * IUTEST_*_NULL, IUTEST_*_NOTNULL を可変長引数対応
  * IUTEST_*_HRESULT_SUCCEEDED, IUTEST_*_HRESULT_FAILED を可変長引数対応
  * compatibility: iuutil に ad_hoc_testresult の取得関数を追加

* Changes
  * ad_hoc_testresult の取得関数名を ad_hoc_test_result に変更

* Bug fixes
  * iuwandbox: iuwandbox で std-cxx の指定をするとオプションチェックで失敗する不具合を修正

iuwandbox でコンパイラーの std オプションを指定すると、不明なオプションとなってしまう不具合を修正してます。
致命的な不具合だったので、早めのリリースとなりました。
(C++17 対応に着手しだしたので二桁になる前に 1.17 にしたい)

2018年7月5日木曜日

iutest v1.16.4 をリリースしました

C++ テスティングフレームワーク iutest v1.16.4 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.net/projects/iutest/releases/69788

変更点は以下の通りです。
  • 変更
    • deprecated: IUTEST_IGNORE 関係を非推奨にしました
  • 修正
    • バグ修正

今回も大きな機能リリースはなしです。
ただ大きな変更として、ファイルの改行コードが半端に混在している状態だったのを正常化しました。
また、一部のコンパイラーでの警告対応が入ってます。

今回は yumetodo san にとってもお世話になりました。
ありがとうございましたmm

2018年5月2日水曜日

iutest v1.16.3 をリリースしました

C++ テスティングフレームワーク iutest v1.16.3 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.net/projects/iutest/releases/69492

変更点は以下の通りです。
  • 追加
    • IUTEST_ASSERT,IUTEST_EXPECT の Variadic 対応
    • iuwandbox: --iutest-use-main を追加
  • 変更
    • iuwandbox: Wandbox の std オプション変更への追従とヒント出力
  • 修正
    • バグ修正

今回も大きな機能リリースはなしです。
(単一マクロ引数だったアサーションを Variadic 対応している途中なのでその紹介は次回リリース時にでも…)
C++17 的な機能を実装して 1.17 リリースしたいなーと思ってるので、しばらく 1.16 系が続くかも…

2017年12月29日金曜日

iutest v1.16.2 をリリースしました

C++ テスティングフレームワーク iutest v1.16.2 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.jp/projects/iutest/releases/68841

とても久しぶりのリリースですが、特に変わってません・・・
最近は CI 周りばかりいじっていて進捗が・・・
あんまりキリがいい状態ではなかったのですが、さすがに年内にはもう一本リリースしないとなーということで出しました。はい。

変更点は以下の通りです。
  • 追加
    • 警告をエラーとするオプション(--iutest_warning_into_error)を追加
  • 削除
    • NaCl サポートを終了
  • 修正
    • バグ修正

来年は機能開発したいですね。では。

2016年12月9日金曜日

iutest v1.16.0 をリリースしました

C++ テスティングフレームワーク iutest v1.16.0 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.jp/projects/iutest/releases/66838

変更点は以下の通りです。
  • 追加
    • iuwandbox で複数ソースファイルのビルドに対応
    • 例外アサーションで構造化例外(SEH)もキャッチできるように対応
  • 変更
    • --iutest_filter のルールを Google Test 互換に修正
  • 修正
    • バグ修正

今回、--iutest_filter の仕様を変更しています。
今までは Google Test と少し異なるルールでした(というか勘違いしてた)が、Google Test と同様の仕様になりましたので、ご注意ください。

では。

2016年11月30日水曜日

[iutest] iutest.min.hpp の圧縮

※下書きしたまま公開するのを忘れてました。
iutest v1.15.2 が既にリリースされていますが、以下は v1.15.1 のときの結果になります。ご了承ください。



iutest v1.15.0 のときには、824,858 byte ありましたが、これをさらにコンパクトにして 573,897 byte にまで小さくしました。
こんな感じだったのが、
namespace iutest
{
class TestInfo
: public detail::iu_list_node<TestInfo>
{
public:
TestInfo(detail::iuITestCaseMediator* testcase,const char* name,detail::iuFactoryBase* factory)
: m_testname(name)
,m_factory(factory)
,m_testcase(testcase)
,m_should_run(true)
,m_ran(false)
,m_disable(false)
,m_skip(false)
,m_matches_filter(true)
{
m_mediator.SetPointer(this);
if( detail::IsStringForwardMatching(name, "DISABLED_")
|| (strstr(name, "/DISABLED_") != NULL) )
{
m_disable = true;
}
}
public:
const char* test_case_name(void) const { return m_testcase->test_case_name(); }
こんな感じになりました。
namespace iutest{class TestInfo: public detail::iu_list_node<TestInfo>{public: TestInfo(detail::iuITestCaseMediator* testcase,const char* name,detail::iuFactoryBase* factory): m_testname(name),m_factory(factory),m_testcase(testcase),m_should_run(true),m_ran(false),m_disable(false),m_skip(false),m_matches_filter(true){m_mediator.SetPointer(this);if(detail::IsStringForwardMatching(name,"DISABLED_")||(strstr(name,"/DISABLED_")!=NULL)){m_disable=true;}}public: const char* test_case_name()const{return m_testcase->test_case_name();}const char* name()const{return m_testname.c_str();}bool should_run()const IUTEST_CXX_NOEXCEPT_SPEC{return m_should_run;}bool is_ran()const IUTEST_CXX_NOEXCEPT_SPEC{return m_ran;}bool is_disabled_test()const IUTEST_CXX_NOEXCEPT_SPEC{return m_disable;}bool is_skipped()const IUTEST_CXX_NOEXCEPT_SPEC{return m_skip||m_test_result.Skipped();}bool is_reportable()const IUTEST_CXX_NOEXCEPT_SPEC{return m_matches_filter;}TimeInMillisec elapsed_time()const{return m_test_result.elapsed_time();}const TestResult* result()const IUTEST_CXX_NOEXCEPT_SPEC{return &m_test_result;}const char* value_param()const{return m_value_param.empty()?NULL:m_value_param.c_str();}const char* type_param()const{return m_testcase->type_param();}::std::string testcase_name_with_default_package_name()const{return TestEnv::AddDefaultPackageName(test_case_name());}public: bool HasFatalFailure()const{return m_test_result.HasFatalFailure();}bool HasNonfatalFailure()const{return m_test_result.HasNonfatalFailure();}bool HasFailure()const{return m_test_result.Failed();}bool Passed()const{if(is_skipped()){return false;}return m_test_result.Passed();}public: ::std::string test_full_name()const{::std::string fullname=test_case_name();fullname+=".";fullname+=name();return fullname;}::std::string test_name_with_where()const{::std::string str=m_testname;if(value_param()!=NULL){str+=", where GetParam() = ";str+=m_value_param;}return str;}public: static bool ValidateTestPropertyName(const ::std::string& name){const char* ban[] ={"name","status","time","classname","type_param","value_param"};
大きな変更は、同じヘッダーが2つ分含まれていたバグの修正と改行コード、空白の削減をしています。
iutest.min.hpp は Wandbox や paiza.IO のようなオンラインコンパイラーを使うときに使用をしていますので、サイズが小さくなることにメリットはあるわけです。

paiza.IO
さて、paiza.IO での実行は以前も記事に書いたように Too long 、ソースコードサイズが大きすぎて実行できませんでした。
ブログズミ: paiza.IO の API を使ってみた

iutest.min.hpp のサイズが小さくなりましたが、paiza.IO の制限 10,000 byte からはまだまだ大きすぎます。
そこで、paiza.IO 向けに更に削減するようにしてみました。
paiza.IO はコンパイラーが決まっているので、ある程度プリプロセスをかけるようにした感じです。

具体的には __clang__ や __has_include, __has_feature などをプリプロセスして、#if を削減しています。
また、Google Test 互換用のヘッダーファイルを除外するようにしています。

これで、テストコードを含めて 388,831 byte まで減らすことができました。
けど、まだまだ足りませんね。。。

ただ、API では無理ですが、ブラウザからは実行できるくらいに収まったようです。


まだ API からは実行できませんが、ここまででキリにしたいと思います。
それでは。

2016年8月2日火曜日

[C++] Shippable + Wandbox でテストしてテスト結果の集計までを行う

ブログズミ: Shippable + Wandbox で C++ の CI 環境構築
以前、上記記事で Shippable + Wandbox で C++ のテスト実行をするようにしたのですが、iutest v1.15.2(v1.15.1) で Wandbox でのテスト結果を xml 出力できるように対応したので、テスト結果の集計まで行うようにしました。

iutest + Wandbox
iutest の Wandbox 実行ツールを利用することで、iutest で記述されたテストコードを Wandbox 上で実行できます。iutest v1.15.2(v1.51.1) では、このツールに xml 出力機能が追加されました。
iuwandbox.py test.cpp --xml test_result.xml
--xml コマンドラインオプションを付けると、指定のパスにテスト結果の xml を出力します。

Shippable でテスト結果 xml の集計
Shippable では junit 形式のテストレポートが集計できます。
Shippable Build Configuration - Shippable Documentation

方法としては簡単です。
shippable/testresults フォルダを作成して、そのフォルダに xml ファイルをコピーするだけです。

e.g.
build:
  ci:
    - mkdir -p shippable/testresults
    - nosetests python/sample.py --with-xunit --xunit-file=shippable/testresults/nosetests.xml
詳しくはドキュメントを確認してください。
iutest の場合
iutest では以下のようにテストをしています。
(Shippable だけでなく Wercker + Wandbox でも同様の方法でテストを実行しています。)
language: python

python: 2.7
cache: true
parallelized_test: true

branches:
  except:
    - gh-pages

install:
  - pip install requests

before_script:
  - export PYTHONDONTWRITEBYTECODE=1
  - make -C tools/fused
  - mkdir -p shippable/testresults

script:
  - cd tools/wandbox
  - python ./iuwandbox.py --list_options ${WANDBOX_COMPILER}
  - python ./iuwandbox.py ../../test/syntax_tests.cpp -c ${WANDBOX_COMPILER} -f"-DIUTEST_USE_MAIN=1" --default --boost nothing --encoding utf-8-sig --expand_include --verbose --xml ../../shippable/testresults/test_result.xml

env:
  matrix:
    - WANDBOX_COMPILER=gcc-head
    - WANDBOX_COMPILER=gcc-6.1.0
    - WANDBOX_COMPILER=gcc-5.3.0
    - WANDBOX_COMPILER=gcc-5.2.0 # travis (5.2.1)
#    - WANDBOX_COMPILER=gcc-5.1.0 # wercker
#    - WANDBOX_COMPILER=gcc-4.9.2 # circle ci
#    - WANDBOX_COMPILER=gcc-4.9.1 # wercker
#    - WANDBOX_COMPILER=gcc-4.9.0 # wercker
#    - WANDBOX_COMPILER=gcc-4.8.2 # wercker
    - WANDBOX_COMPILER=gcc-4.8.1
    - WANDBOX_COMPILER=gcc-4.7.3
#    - WANDBOX_COMPILER=gcc-4.6.4 # drone
    - WANDBOX_COMPILER=gcc-4.5.4
#    - WANDBOX_COMPILER=gcc-4.4.7 # snap ci
    - WANDBOX_COMPILER=gcc-4.3.6
    - WANDBOX_COMPILER=clang-head
#    - WANDBOX_COMPILER=clang-3.8 # travis ci
#    - WANDBOX_COMPILER=clang-3.7 # circle ci / wercker
#    - WANDBOX_COMPILER=clang-3.6 # semaphore
#    - WANDBOX_COMPILER=clang-3.5 # c++config.h not found
    - WANDBOX_COMPILER=clang-3.4
#    - WANDBOX_COMPILER=clang-3.3 # wercker
#    - WANDBOX_COMPILER=clang-3.2 # wercker
#    - WANDBOX_COMPILER=clang-3.1 # wercker
    - WANDBOX_COMPILER=clang-3.0

after_success:
  - echo OK
  
notifications:
  email:
    on_success: change
    on_failure: always



最後に
Wandbox でのテスト結果を xml ファイルに出力できるようになったことで、テストツールとして完成されてきた感じがしてきました。
iutest のテストとしてはかなり便利に使わせていただいています。
もう個人的には最強の環境になったかなと思います。

ただ、複数ファイルのコンパイルができない(ヘッダーは可能)ので、まだちょっとプロダクトのテストをするとまでは至っていませんが、ヘッダーオンリーなライブラリーとかであれば、かなり良いテスト環境になるのではないでしょうか。

2016年7月25日月曜日

iutest v1.15.2 をリリースしました

C++ テスティングフレームワーク iutest v1.15.2 をリリースしました。
Github: https://github.com/srz-zumix/iutest/releases
OSDN: https://osdn.jp/projects/iutest/releases/66174
変更点は以下の通りです。
  • 追加
    • IUTEST_TYPED_TEST_P に対して friend できるように IUTEST_FRIEND_TYPED_TEST_P_DECLARATION/IUTEST_FRIEND_TYPED_TEST_P を追加
    • iuwandbox に --sprout/--msgpack オプションを追加
  • 変更
    • iuwandbox の --list_compiler オプションでバージョンを出力しないように変更。--verbose を付けると以前と同じバージョン付きの出力をする
    • deprecated: IUTEST_HAS_STRSTREAM は将来的に削除されます
    • deprecated: IUTEST_HAS_ARITHMETIC_EXPRESSION_DECOMPOSE は将来的に削除されます
  • 修正
    • iuwandbox で --expand_include オプションを付けなかった場合の include されたファイルの対応を修正
    • iuwandbox の --boost オプションが Python3 で使えない問題を修正
    • iuwandbox で未定義オプションを指定した場合にエラーにならない問題を修正
    • IUTEST(A, B_C) と IUTEST(A_B, C) が名前の衝突でコンパイルエラーになる問題を修正
    • 色付きコンソールの自動判定を修正
    • バグ修正

iuwandbox の修正が多いですね。
この辺あんまりテストしてなかったので色々直すところがありました。(yumetodo さんありがとうございました。)
テスト環境は構築予定なので、そのうちここで報告できると思います。

あとは、IUTEST_TYPED_TEST_P に friend する方法が提供されていなかったので追加したり、テスト名衝突問題をお直したり、色付きコンソール出力を改善したりしました。



1.15.1 のリリースはスキップしましたので、その履歴も載せておきます
  • 追加
    • stderr に xml の内容を出力するリスナーを追加
    • iuwandbox に xml 出力オプション(--xml, --junit)を追加
  • 変更
    • --help|spec|feature|version を同時に使用可能に変更 (e.g. --spec --feature)
  • 修正
    • CSV パラメータのパス解決処理を修正
    • バグ修正

v1.15.1 では主に fused-src の改善と Wandbox での実行結果を xml に出力する対応をしました。
あとは、バグ修正や環境周りの整備をしています。



今回の修正点について、少しだけ詳しく後日紹介したいと思います。
では。

2016年6月17日金曜日

iutest v1.15.1 のリリースを予定していましたがスキップします

現在 llvm apt repository が落ちており、一部のテストが回っていないため予定していていた iutest v1.15.1 のリリースはスキップさせていただきます。
(※ github のタグは更新されています)

Travis CI Build Failing - Stack Overflow
[llvm-dev] IMPORTANT: APT repo temporary switched off

2016年5月9日月曜日

Circle CI で Junit 形式 xml の集計

CI サービスで JUnit 形式の xml を集計できるものは、以下のものがあります。

Circle CI

Shippable


どちらを使ってもいいのですが、現在 iutest の開発では、
Shippable は Wandbox を使ったコンパイラーバージョン検証に利用しているので、Circle CI を使うことにしました。
ただ、Circle CI も今までは python ツールの検証用に使っていました。
今回、最適化オプションごとの検証用として再定義しなおしています。(もともとしてた python ツールのテストは別サービスに移行予定)

Circle CI で Junit 形式の xml 集計
さて、本題です。
Circle CI では、テスト結果は $CIRCLE_TEST_REPORTS ディレクトリに入れることになっています。
https://circleci.com/docs/test-metadata/
さらに、テストツールごとに階層がある構成になってます。(e.g. $CIRCLE_TEST_REPORTS/cucumber)
今回は JUnit 形式の xml を出力するので、junit ディレクトリに保存します。

iutest の場合:
test:
  post:
    - mkdir -p $CIRCLE_TEST_REPORTS/junit/
    - find . -type f -regex ".*/test/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;

集計結果は「Test Summary」に表示されます。
成功の場合:

失敗の場合:


簡単ですね。

2016年2月15日月曜日

iutest v1.15.0 をリリースしました

C++ テスティングフレームワーク iutest v1.15.0 をリリースしました。
変更点は以下の通りです。

  • 追加
    • --iutest_output オプションで repeat 回数のフォーマットに対応 e.g. --iutest_output=xml:test_%d.xml
    • CSV ファイルから値のパラメータ作成に対応
    • 値のパラメータ化テストのテスト名指定方法の Google Test 互換対応
  • 変更
    • IUTEST_ALIAS_TESTNAME_F,IUTEST_JAPANESE_NAME_F の引数の順番を変更
    • 値のパラメータ化テストのテスト名指定方法を変更
    • IUTEST_TYPED_TEST_APPEND_TYPENAME を IUTEST_HAS_TYPED_TEST_APPEND_TYPENAME に変更
  • 修正
    • バグ修正

今回 v1.15.0 の追加機能は、3つです。

1つ目は、--iutest_output オプションでテスト結果を出力する際に、リピート回数をファイル名に含められるようにしました。
今までリピート実行した場合に出力されるテスト結果のファイルは1つだけでしたが、フォーマット指定でリピート回数をファイル名に含めることで、リピート毎にファイルを出力できるようになりました。
e.g. --iutest_output=xml:test_%d.xml

2つ目は、CSV ファイルから動的に値のパラメータを生成できるようになりました。以下のように使います。
class CSVValuesTest : public ::iutest::TestWithParam<int> {};

IUTEST_P(CSVValuesTest, Test)
{
 int v = GetParam();
 IUTEST_SUCCEED() << v;
}
IUTEST_INSTANTIATE_TEST_CASE_P(A, CSVValuesTest, ::iutest::CSV<int>("csvparams.csv"));
::iutest::CSV 関数のテンプレートパラメータに型を指定してください。その型で csv をパースします。
第一引数に csv ファイルのパスを指定します。
(実行ファイルからの相対パス。パス解決方法をもう少しなんとかしたい…)
動的にパラメータを生成するので、リビルドすることなく csv ファイルを更新するだけでパラメータの変更ができるのがメリットです。

3つ目は、Google Test 互換の値のパラメータ化テストのテスト名指定方法に対応しました。
こちらの機能を含んだ Google Test はまだリリースされていませんが、github で確認できます。
(そろそろ出るかなぁ~と思っていたのですが、まだみたいですね。)



また、今回は破壊的変更が2件あります。
1つ目は IUTEST_ALIAS_TESTNAME_F と IUTEST_JAPANESE_NAME_F の引数の順番を入替えました。
これにより、このマクロを使用していたテストコードに変更が必要になりますが、
こちらの機能は C++03 環境でテスト名に日本語を使いたいために用意したもので、まぁそんなに使われいないだろうということで変えちゃいました。

2つ目は値のパラメータ化テストのテスト名指定方法を変更しています。
v1.14.0 で試験的に入れた機能でしたが Google Test の実装方法との互換性を考慮して、今回から変更がされています。

今回は以上です。

2015年12月16日水曜日

Boost.Test v3 を使ってみた

この記事は 初心者 C++er Advent Calendar 2015 16 日目の記事です。
<15日目: matsuokah さん「C++初心者ならビルドはBazelでラクしちゃいましょう
>17日目:yumetodo さん「C99からC++14を駆け抜けるC++講座

アドベントカレンダー用に書いてたものじゃないんですが、空いていたので滑り込みました。



Boost 1.59.0がリリースされました - Faith and Brave - C++で遊ぼう

Boost 1.59.0 で Boost.Test v3 になってます。
リンク先にも書かれているように、主な変更点は BOOST_TEST マクロと Data driven test 対応でしょう。
今回はこの2つを試してみました。

Windows + Visual Studio な環境で Boost を即座に使う方法
Boost の Nuget パッケージが公開されているので、それを使います。
NuGet Gallery | boost 1.59.0
既にやり方がまとめてられています。こちらのほうが画像もあって参考になると思います。



BOOST_TEST マクロ
Catch のアサーションのように、式の各値を出力してくれる機能がついたアサーションです。
Catch に関しては以前のブログを参考にしてください。

使い方はこんな感じで
#define BOOST_TEST_MODULE example
#include "boost/test/unit_test.hpp"

int f() { return 42; }

BOOST_AUTO_TEST_CASE(test_op_reportings)
{
 int a = 43, b = 42, c = 0;
 BOOST_TEST(a == b);
 BOOST_TEST(f() == a);
 BOOST_TEST(a < b);
 BOOST_TEST(a - 1 < b);
 BOOST_TEST(b > a - 1);

 BOOST_TEST((f() && c));
}

こんなふうに出力されます。

|| や && は () で囲う必要があります。( () の中身は展開できないようです。)

仕組みとしては、Catch と同様に operator ->* を利用したもののようです。
これはかなり便利な機能が追加されましたね!

Data-driven test
Google Test の値のパラメータ化テストのことです。
Boost.Test でも BOOST_PARAM_TEST_CASE を使うことで出来ていました。これは 2012年のアドベントカレンダーの補足(ブログズミ: Google Test ユーザーが Boost.Test を使ってみた (補足))で書きました。
ちょっと面倒くささがあったのですが、v3 になって Data-driven test に置き換えられました。

基本
まずは簡単な例から
#define BOOST_TEST_MODULE example
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/data/monomorphic.hpp>
#include <iostream>

namespace bdata = boost::unit_test::data;

BOOST_DATA_TEST_CASE(test1, bdata::xrange(5))
{
    std::cout << "test 1: " << sample << std::endl;
    BOOST_TEST((sample <= 4 && sample >= 0));
}
BOOST_DATA_TEST_CASE(test2, bdata::xrange(5), var)
{
    std::cout << "test 2: " << var << std::endl;
    BOOST_TEST((var <= 4 && var >= 0));
}

BOOST_DATA_TEST_CASE の第一引数がテスト名、第二引数がデータセットです。
この例では、0~4 の値でテストが実行されます。
パラメータは何も指定しなければ、「sample」変数で取得できます。(test1)
BOOST_DATA_TEST_CASE マクロの第三引数以降に名前を指定すると、指定した名前で取得できます。(test2)

データセット生成器
データセット生成器は、xrange, random, make の3つが提供されています。 Datasets generators - 1.59.0
xrange は任意の範囲の値を、random はランダムな値を、make は任意の値を指定することができます。

以下は make の例
BOOST_DATA_TEST_CASE(test3, bdata::make(1))
{
    std::cout << "test 3: " << sample << std::endl;
}

struct Hoge
{
    int x, y;
};

//::std::ostream& operator << (::std::ostream& os, const Hoge& hoge)
//{
//  return os << "X:" << hoge.x << " Y:" << hoge.y;
//}

BOOST_TEST_DONT_PRINT_LOG_VALUE(Hoge);

const char* a[] = { "ABC", "DEF", "G", "H" };
Hoge x[4] = { {0,1}, {2,3}, {4,5}, {6,7} };

BOOST_DATA_TEST_CASE(test4, bdata::make(a), v)
{
    std::cout << "test 4: " << a << << std::endl;
}
BOOST_DATA_TEST_CASE(test5, bdata::make(x), v)
{
    std::cout << "test 5: " << v.x << ", " << v.y << std::endl;
}

test3 では単一の値、test4, test5 では配列からデータセットを作成しています。
構造体などを使用する場合は、ostream への operator << を定義するか BOOST_TEST_DONT_PRINT_LOG_VALUE を使う必要があります。


続いて random の例ですが、下記コードだと実行時に例外が投げられます。
BOOST_DATA_TEST_CASE(test6, bdata::random(0, 100))
{
    std::cout << "test 6: " << sample << std::endl;
}
random は要素数の定義がないためです。
random を使うにはデータセットの組み合わせが必要になります。

データセットの組み合わせ
データセットは複数設定することができます。 Operations on dataset - 1.59.0
BOOST_DATA_TEST_CASE の第三引数以降にデータセットを受け取る変数名をパラメータ数分指定してください。

Zips
まずは、random の例として Zips を使います。
BOOST_DATA_TEST_CASE(test7, bdata::xrange(5) ^ bdata::random(0, 100), i, sample)
{
    std::cout << "test 7: " << i << ": " << sample << std::endl;
}

'^' が Zips のオペレーターです。2つのデータセットをペアにします。
上記の例では、0~4 のインデックスと乱数がパラメータとして得られます。


複数のデータセットをまとめることができますが、有限のデータセットの場合は要素数を揃える必要があるので注意。
BOOST_DATA_TEST_CASE(test8, bdata::xrange(5) ^ bdata::xrange(10, 15) ^ bdata::xrange(100, 110, 2)
    , var1, var2, var3)
{
    std::cout << "test 8: " << var1 << ", " << var2 << ", " << var3 << std::endl;
}



Grid (Cartesian products)
次に、データセットから直積のパラメータを生成します。
これは Google Test の Combine と同じ機能になります。
BOOST_DATA_TEST_CASE(test9, bdata::xrange(5) * bdata::xrange(5), var1, var2)
{
    std::cout << "test 9: " << var1 << ", " << var2 << std::endl;
}

'*'Grid (Cartesian products) のオペレーターです。
2つのデータセットのすべての組み合わせがパラメータとして得られます。

Joins
最後になりましたが、データセットは連結することもできます。
BOOST_DATA_TEST_CASE(test10, bdata::xrange(5) + bdata::xrange(10, 15))
{
    std::cout << "test 10: " << sample << std::endl;
}

'+'Joins のオペレーターです。
上記例では 0~4 と 10~14 がパラメータとして得られます。


最後にこれらの組み合わせを使うことで、より複雑なデータセットを作ることもできます。
BOOST_DATA_TEST_CASE(test11, (bdata::xrange(5) + bdata::xrange(10, 15)) ^ bdata::random(0,100), var1, var2)
{
    std::cout << "test 11: " << var1 << ", " << var2 << std::endl;
}


まとめ
Boost.Test v3 になってすごく便利に、そして書きやすくなってました。
個人的にはオペレーターで組み合わせ作れるのがいいなーと思ったので、あとは使う機会があればって感じです。
もし、Boost を業務で使うことがあれば、テスティングフレームワークは Boost.Test を使おうと思います。

2015年12月9日水曜日

[Catch] REQUIRE の式が展開される仕組み

こちらは C++ Advent Calendar 2015 9日目の記事になります。
前の日は plasma_effector さんで「plasma.ADTの紹介 」でした。


ブログズミ: C++ Testing Framework の Catch を使ってみた
以前、Catch を紹介したときに REQUIRE マクロに渡した式が展開されることを書きました。

その仕組について、簡単ではありますが説明しておこうと思います。
(大分昔に書き上げていたものの、アップするタイミングを失っていたのですが、こうしてアドベントカレンダーとして公開することができました。)

#define CATCH_CONFIG_MAIN // main の定義を catch に任せる
#include <catch.hpp>

int f()
{
    return 1;
}

TEST_CASE("Test", "[sample]")
{
    CHECK( f() == 2 );
    REQUIRE( f() <= 0 );
}

-------------------------------------------------------------------------------
Test
-------------------------------------------------------------------------------
main.cpp(9)
...............................................................................

main.cpp(11): FAILED:
  CHECK( f() == 2 )
with expansion:
  1 == 2

main.cpp(12): FAILED:
  REQUIRE( f() <= 0 )
with expansion:
  1 <= 0

===============================================================================
1 test case - failed (2 assertions - both failed)

こちらが「ブログズミ: C++ Testing Framework の Catch を使ってみた」で書いたコードと実行結果です。

REQUIRE および CHECK に渡した式の中の f() が返した値が出力されています。
この仕組を説明します。


マクロを追う
REQUIRE や CHECK マクロがどのような実装になっているのか追っていきます。

まず、REQUIRE や CHECK はこのように書かれています。
#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )

どちらも INTERNAL_CATCH_TEST を使っています。
INTERNAL_CATCH_TEST は以下のようになっています。
#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
    do { \
        Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
        try { \
            ( __catchResult->*expr ).endExpression(); \
        } \
        catch( ... ) { \
            __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
        } \
        INTERNAL_CATCH_REACT( __catchResult ) \
    } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
(include/internal/catch_capture.hpp)

REQUIRE と CHECK の違いは resultDisposition と macroName の部分です。
macroName はただの名前なので特に気にしなくて OK です。 resultDisposition では続行可能か不可能かを分けています。

さて、ここで重要なのが
( __catchResult->*expr ).endExpression();
のところです。
->* は間接メンバポインタ演算子という演算子で、オーバーロード可能な演算子の1つです。
これが f() の戻り値が表示される仕組みの肝になります。

実際に最初のコードを例に説明をします。

式の分解
最初に示したコードの REQUIRE 文を展開します。

do {
    Catch::ResultBuilder __catchResult( "REQUIRE", CATCH_INTERNAL_LINEINFO, "f() <= 0", Catch::ResultDisposition::Normal );
    try {
        ( __catchResult->*f() <= 0 ).endExpression();
    }
    catch( ... ) {
        __catchResult.useActiveException( Catch::ResultDisposition::Normal );
    }
    INTERNAL_CATCH_REACT( __catchResult )
} while( Catch::isTrue( false && (f() <= 0) ) )

さて、改めて
( __catchResult->*expr ).endExpression();
に注目しましょう。
これは上記の展開されたコードでは、
( __catchResult->*f() <= 0 ).endExpression();
のようになっています。
ここで、
__catchResult->*f() <= 0
はどのような順番で処理されると思いますか?



正解は、
  1. f()
  2. __catchResult->*f()
  3. __catchResult->*f() <= 0
です。
これは演算子の優先順位により、<= よりも ->* が先に評価されるためです。
C++ Operator Precedence - cppreference.com

簡単に挙動確認コードを書きました。気になる方はこちらも参照してください。
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

というわけで、「f() <= 0」 から 「f()」と「<= 0」とに分解できました。
ResultBuilder(__catchResult) には f() の戻り値が入ってくるので、f() の結果が Catch できるのです^^

分解できたのであとはイイ感じするだけです。ついでなので説明します。

残った式の処理
Catch::ResultBuilder::operator ->* を詳しく見てみましょう。
class ResultBuilder {
public:
    ResultBuilder(  char const* macroName,
                    SourceLineInfo const& lineInfo,
                    char const* capturedExpression,
                    ResultDisposition::Flags resultDisposition );

    template<typename T>
    ExpressionLhs<T const&> operator->* ( T const& operand );
    ExpressionLhs<bool> operator->* ( bool value );

template<typename T>
inline ExpressionLhs<T const&> ResultBuilder::operator->* ( T const& operand ) {
    return ExpressionLhs<T const&>( *this, operand );
}

inline ExpressionLhs<bool> ResultBuilder::operator->* ( bool value ) {
    return ExpressionLhs<bool>( *this, value );
}
(include/internal/catch_result_builder.h)

ResultBuilder::operator->* はなんらかの値を受け取り、ExpressionLhs を返します。
(bool で特殊化されていますがここでは無視します)

ExpressionLhs はこのように定義されています。
template<typename T>
class ExpressionLhs {
    ExpressionLhs& operator = ( ExpressionLhs const& );
#  ifdef CATCH_CPP11_OR_GREATER
    ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
#  endif

public:
    ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
#  ifdef CATCH_CPP11_OR_GREATER
    ExpressionLhs( ExpressionLhs const& ) = default;
    ExpressionLhs( ExpressionLhs && )     = default;
#  endif

    template<typename RhsT>
    ResultBuilder& operator == ( RhsT const& rhs ) {
        return captureExpression<Internal::IsEqualTo>( rhs );
    }

    template<typename RhsT>
    ResultBuilder& operator != ( RhsT const& rhs ) {
        return captureExpression<Internal::IsNotEqualTo>( rhs );
    }

    template<typename RhsT>
    ResultBuilder& operator < ( RhsT const& rhs ) {
        return captureExpression<Internal::IsLessThan>( rhs );
    }

    template<typename RhsT>
    ResultBuilder& operator > ( RhsT const& rhs ) {
        return captureExpression<Internal::IsGreaterThan>( rhs );
    }

    template<typename RhsT>
    ResultBuilder& operator <= ( RhsT const& rhs ) {
        return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
    }

    template<typename RhsT>
    ResultBuilder& operator >= ( RhsT const& rhs ) {
        return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
    }

    ResultBuilder& operator == ( bool rhs ) {
        return captureExpression<Internal::IsEqualTo>( rhs );
    }

    ResultBuilder& operator != ( bool rhs ) {
        return captureExpression<Internal::IsNotEqualTo>( rhs );
    }

    void endExpression() {
        bool value = m_lhs ? true : false;
        m_rb
            .setLhs( Catch::toString( value ) )
            .setResultType( value )
            .endExpression();
    }

    // Only simple binary expressions are allowed on the LHS.
    // If more complex compositions are required then place the sub expression in parentheses
    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );

private:
    template<Internal::Operator Op, typename RhsT>
    ResultBuilder& captureExpression( RhsT const& rhs ) {
        return m_rb
            .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
            .setLhs( Catch::toString( m_lhs ) )
            .setRhs( Catch::toString( rhs ) )
            .setOp( Internal::OperatorTraits<Op>::getName() );
    }

private:
    ResultBuilder& m_rb;
    T m_lhs;
};
(include/internal/catch_expression_lhs.hpp)

長いですが、まずここで注目するのは各種 operator のオーバーロードです。
それぞれ値を受け取り captureExpression 関数を通して ResultBuilder の参照を返しています。

captureExpression では、Internal::compare でオペレーターごとに式の評価が行われ、その結果と左辺・右辺の文字列、オペレーターの文字列が ResultBuilder に設定されます。このように、Catch では operator オーバーロードを利用してそれぞれの情報を集めつつ評価がされていく仕組みになっています。


ちなみに真ん中辺りにある STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& を返すオペレーター(+,-,/,*,&&,||)はこの仕組が使えません。つまり、REQUIRE( a && b ) のような書き方はできませんのでご注意。

他のテスティングフレームワークの対応状況は?
Boost.Test では?
Boost.Test では v1.59 から同様のアサーションが使えるようになってます。
(Catch ではできないオペレーターにも対応しています。)
BOOST_ - 1.59.0
Boost 1.59.0がリリースされました - Faith and Brave - C++で遊ぼう

Google Test では?
Google Test には残念ながらそのようなアサーションはありません。

iutest では?
iutest は私が作っているテスティングフレームワークです。 https://github.com/srz-zumix/iutest
iutest でも同様の記述ができ、これも operator ->* のオーバーロードで実現させています。実装はだいたい似たような感じですが、iutest では Catch では使えないオペレーターにも対応してます。

int f(void)
{
    return 42;
}

IUTEST(ExpressionTest, Test)
{
    IUTEST_EXPECT(f() + f() == 2);
}




最後に
Catch にしろ、Boost.Test にしろ、iutest にしろ、所謂 PowerAssert は便利な機能です。
普段 Google Test をよく使っているので、これがないとテストが書けないわけではありませんが、ASSERT_EQ(a, b) などと書くよりも ASSERT( a == b ) と書けたほうが、より直観的でわかりやすいですよね。

Google Test も(まだまだ開発進んでいるので)対応することを期待しつつ、これで締めたいと思います。
C++ Advent Calendar 2015 10日目は hmito さんで「[C++] csvファイル入出力用のiteratorを作ってみた話 - Qiita」です。

2015年11月11日水曜日

iutest v1.14.0 をリリースしました

C++ テスティングフレームワーク iutest v1.14.0 をリリースしました。
変更点は以下の通りです。

  • 追加
    • 大幅なリファクタリング
  • 修正
    • ::iutest::Range を Enum に対応
    • tools の python 3.x 系対応


今回は細かいバグ修正をして、v1.13.1 としてリリースするつもりでしたが cpplint などの対応をしていたら、影響の大きな変更が入ったため v1.14.0 としてリリースしました。
ですので、今回は新しい機能はありません。

cpplint はまたブログにします。それでは。

2015年9月28日月曜日

Google Mock の Matcher を使ってみた

Google Mock とは Google 製の C++モッキングフレームワークです。
Google Test はよく使っているのですが、Google Mock は存在は知りつつも実用したことは今までありませんでした。
モッキングフレームワークですから、モック作成がメイン機能になりますが、Google Mock は Google Test の機能拡張版として、Google Test の書き方をしつつより便利なアサーションを使うことができます。

今回はその便利なアサーションについてお話しようと思います。

THAT!!
THAT。そうそのアサーションは ASSERT_THAT,EXPECT_THAT という名前で定義されています。
THAT は引数に Matcher を取ります。この Matcher にマッチするかどうかを検証します。
Matcher については日本語ドキュメントに詳しくまとまっているので、そちらを参考にしてください。
Google Mock ドキュメント日本語訳
(v1.6.0 当時のものなので注意)

これらの Matcher は組み合わせて使うこともでき、Google Test の ASSERT_EQ や ASSERT_LE など検証内容が固定のアサーションよりも、統一的な記法でより柔軟にテストを書くことができます。その例を以下に示します。
※以下のコードは適切に using されているものとします。

基本的な比較
Eq,Ne,Le,Lt,Ge,Gt,IsNull,NotNull および浮動小数点数比較など、基本的な比較 Matcher は Google Test でも同等のアサーションがありますので、省きます。

OR 条件
AnyOf Matcher を使用することで OR 条件を表現できます。
TEST(Matcher, AnyOf)
{
   int a=1;
   ASSERT_THAT(a, AnyOf(Eq(1), Eq(10)));
}

これは、「a == 1 || a == 10」であることを検証しています。
Google Test ではスマートに書くことができなかった OR 条件が非常に簡単に書くことができます。

AND 条件
今度は逆に AND 条件をどう書くか、です。
Google Test の場合は以下のように書けました。
TEST(Test, And)
{
    int a=1;
    ASSERT_GT(a, 0);
    ASSERT_LT(10, a);
}
もちろん、Google Mock でも上記のような書き方もできますが、AllOf Matcher が用意されています。
Matcher のメリットは組み合わせができることです。特に理由がない限り AllOf Matcher を使うのがよいでしょう。
TEST(Matcher, AllOf)
{
    int a=1;
    ASSERT_THAT(a, AllOf(Gt(0), Lt(10)));
}

これは、「a > 0 && a < 10」であることを検証しています。

コンテナ
Google Test でコンテナの各要素の検証は、できなくはないですがやや面倒です。
Matcher にはコンテナの要素やクラス・構造体メンバーへのアクセスをするものが用意されています。
これを使うことでかなり簡単に要素チェックができるようになります。

すべての要素が指定条件にマッチする
TEST(Matcher, Each)
{
    int a[3] = {1, 2, 3};
    ::std::vector b { 1, 2, 3};
    ASSERT_THAT(a, Each(Gt(0)) );
    ASSERT_THAT(b, Each(Gt(0)) );
}
Each Matcher はコンテナの要素すべてが指定条件にマッチするかを検証します。
上の例だと、コンテナ a/b の要素がすべて、 0 より大きいことを検証しています。

指定条件にマッチする要素を含む
TEST(Matcher, Contains)
{
    int a[3] = {1, 2, 3};
    ::std::vector b { 1, 2, 3};
    ASSERT_THAT(a, Contains(Eq(1)) );
    ASSERT_THAT(b, Contains(Eq(1)) );
}
Contains Matcher は Each とは違い、指定条件にマッチする要素を含むかどうかを検証します。
上の例だと、コンテナ a/b の要素に、 1 を含むかどうかを検証しています。

キーの検証
次はキーの検証です。map のキーを検証したいときなどに使用します。
TEST(Matcher, Key)
{
    ::std::map m = make_map();
    ASSERT_THAT(m, Key(Lt(10)) );
}

上記コードの場合、キーの値がすべて 10 未満であることを検証しています。

ペアで検証する
map の要素(ペア)を両方検証したい場合は、Pair Matcher を使います。
TEST(Matcher, Key)
{
    ::std::map m = make_map();
    ASSERT_THAT(m, Pair(Lt(10), StrNe("hoge")) );
}
上記コードの場合、m は 10 より小さいキーであり、値の文字列が "hoge" でないことを検証しています。


メンバーの検証
Key と Pair は map の要素に対してのアクセス Matcher でした。
今度は、任意のメンバー変数や関数にアクセスする Matcher です。
struct X {
    int a;
};
TEST(Matcher, Field)
{
    X x = {1};
    ASSERT_THAT(x, Field(&X::a, Eq(1)) );
}
上記コードは、ASSERT_THAT(x.a, Eq(1)); と同じ意味です。
なんの役に立つかは、後述の複雑な組合せでします。

コンテナの各要素それぞれに Matcher を指定する
Each や Contains には各要素に対し1つの Matcher しか指定できませんでした。
しかし、コンテナの先頭は条件X、残りの要素は条件Yで検証したい場合などもあると思います。
そのような場合に使用するのが、ElementsAre Matcher です。
IUTEST(Matcher, ElementsAre)
{
    int a[3] ={ 0, -1, 3 };
    ASSERT_THAT(a, ElementsAre(Ge(0), Lt(0), Gt(0)));
}

こちらは、下記のコードと同じです。
TEST(Matcher, ElementsAre)
{
    int a[3] ={ 0, -1, 3 };
    ASSERT_THAT(a[0], Ge(0))
    ASSERT_THAT(a[1], Lt(0))
    ASSERT_THAT(a[2], Ge(0))
}

また、配列版の ElementsAreArray もあります。
TEST(Matcher, ElementsAreArray)
{
    int a[3] ={ 0, 1, 3 };
    int b[3] ={ 0, 1, 3 };
    EXPECT_THAT(a, ElementsAreArray(b));
}

ワイルドカード
任意の数値にマッチするワイルドカードも用意されています。
この Matcher は常にマッチする Matcher で一部分だけ検証を無視したい場合などに使えます。
ワイルドカードには2種類あり、常にマッチする '_' と 指定の型にマッチする 'A<type>' があります。

TEST(Matcher, Wildcard)
{
    EXPECT_THAT(42, _);
    EXPECT_THAT(42, A<int>());
}

複雑な組合せ
ここまで紹介した Matcher を組み合わせることで、複雑な条件も簡単に記述できるようになります。

struct X { int a, b; }

TEST(Matcher, Member)
{
    std::map<int, X> m;
    for( int i=0; i < 10; ++i )
    {
        m.insert(::std::pair<int, X>(i, X{i, 100}));
    }
    EXPECT_THAT(m, Each(Pair(Le(10), Field(&X::b, Ge(0)))));
}

こちらは、intをキーとする構造体のマップから、各マップ要素の
キーが10以下、構造体のメンバー b が 0 以上であることを検証しています。
これらの検証を1つずつ記述するのは面倒ですが、Each や Pair などを組み合わせることによって上記のように簡潔に記述ができます。

また、ワイルドカードを使えば検証したくない所を無視することができます。
TEST(Matcher, Member)
{
    std::map<int, X> m;
    for( int i=0; i < 10; ++i )
    {
        m.insert(::std::pair<int, X>(i, X{i, 100}));
    }
    EXPECT_THAT(m, Each(Pair(_, Field(&X::b, Ge(0)))));
}

iutest では?
恒例の iutest の対応状況を書いておきます。
iutest は自作の C++ テスティングフレームワークです。
https://github.com/srz-zumix/iutest

iutest でも THAT アサーションと Matcher が使えます。
Matcher は Google Mock v1.7.0 相当のものが使えるようになってます。
詳しくはドキュメントを参照してください。

http://iutest.osdn.jp/doc/html/modules.html
http://iutest.osdn.jp/doc/html/d4/d14/group___m_a_t_c_h_e_r_s.html

最後に
Google Mock はモッキングフレームワークですが、アサーションの拡張としてだけでも使う価値がありそうです。
(iutest ではそれ単体で Matcher が使えますので、こちらもよろしくお願いします)