2015年6月29日月曜日

iutest を NuGet パッケージにして公開しました

NuGet で公開しました。
パッケージインストールするだけで、すぐさま iutest を使ったテストが書けるようになりました!

パッケージ作成の備忘録
参考URL:
Past We Saw - 原文: Deep Dive into NuGet Native (Part One)
NuGet パッケージを作って公開する - しばやん雑記
Nuspec Reference

iutest の場合、インクルードオンリーなフレームワークですので、必要なのはヘッダーファイルとそのパスを通すための .targets ファイルです。
それらのファイルをパッケージングするようにした .nuspec を用意したら終わりです。

実際に書いたファイルは、以下で確認できます。
https://github.com/srz-zumix/iutest/tree/master/projects/nuget

ローカルでテスト
参考URL:
NuGet をオフラインで使用する - THE TRUTH IS OUT THERE - Site Home - MSDN Blogs

パッケージできたら、本番環境にデプロイするまえにテストしたいですよね。
NuGet のパッケージソースは、ローカルパスにも対応しています。
ツール > NuGet パッケージ マネージャー > パッケージ マネージャーの設定 > パッケージ ソース で追加することができます。


これで、ローカルパスを追加して、パッケージのインストールをすることができます。
社内向けとかプライベートなパッケージも置くことができますね。

Appveyor で自動デプロイ
参考URL:
AppVeyor で NuGet パッケージの作成とデプロイを自動化 | grabacr.nét

最初、この設定でやってみたのですが、どうやら .csproj の場合しかやってくれないっぽい。
ということで、この方法は諦め。

参考URL:
Appveyor でNuget Packageの発行を自動化する - 銀の光と碧い空

続いて、こちらを参考にして PowerShell でパッケージ作成をしました。
まず、ビルドスクリプトでパッケージを作成します。
$nuspecPath = "projects\nuget\iutest.nuspec"
Write-Output "Building NuGet package"
nuget pack $nuspecPath -OutputDirectory ".\"

iutest では、.nuspec ファイルのバージョンは手付でやるので、上書きとかはせず単純にパッケージ作成をしました。

次に Artifacts の設定でビルドで作成した .nupkg ファイルを成果物として保存します。
「DEPLOYMENT NAME」 には適当な名前を入れてください。あとで使います。


最後に、Delpoyment の設定をします。
Provider を NuGet に設定し、API Key を設定してください。
そして、その下の Artifact(s) のところに先ほど設定した 「DEPLOYMENT NAME」 を設定します。


というわけで

NuGet で公開されてます。
是非、使ってみて下さい

2015年6月22日月曜日

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

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

  • 追加
    • Matcher に MatchesRegex,ContainsRegex を追加
    • Matcher に ElementsAreArrayForward を追加
    • IUTEST_*_MATCHES_REGEXEQ,NE、IUTEST_*_CONTAINS_REGEXEQ,NE 追加
    • --iutest_filter=@filter.txt のようにファイルからフィルター指定できるように対応
    • quick_exit 対応
    • Visual Studio 2015 RC 対応
    • twilio 対応
    • Nuget パッケージ公開
  • 変更
    • IUTEST_PACKAGE v2 (多重定義制限の撤廃)
    • ElementsAreArray で要素数の一致チェックを行うように変更(以前までの ElementsAreArray は ElementsAreArrayForward に変更)
    • IUTEST_REPORT_SKIPPED を IUTEST_HAS_REPORT_SKIPPED に変更
  • 修正
    • IUTEST_MAKE_PEEP で関数ポインターの typedef をしなくてもいいように修正
    • バグ修正

今回は、正規表現 Matcher と Assertion の追加が大きな変更点です。
以前のバージョンから挙動を変更している部分もありますので、ご注意ください。


今回更新した機能の一部を紹介したいと思います。
正規表現アサーション
IUTEST(AssertionTest, MATCHES_REGEXEQ)
{
  const char test[] = "te0123st";
  IUTEST_ASSERT_MATCHES_REGEXEQ("te[0-9]*st", test);
}
アサーションとして追加したのは、以下の4つ
  • IUTEST_*_MATCHES_REGEXEQ
  • IUTEST_*_MATCHES_REGEXNE
  • IUTEST_*_CONTAINS_REGEXEQ
  • IUTEST_*_CONTAINS_REGEXNE
完全一致と部分一致それぞれ、EQとNE 2つずつです。
これらアサーションは拡張機能なので、Google Test モードでも使用できます。

また、アサーションとは別に正規表現 Matcher も追加しています。
こちらは、Google Mock 同等の MatchesRegex, ContainsRegex が使用できます。


ファイルからのフィルター指定
--iutest_filter=@filepath
のように、@ を付けてパス指定をすることでファイルからフィルターの指定をできるようにしました。
コマンドライン引数には、長さの上限があるのでとても長いフィルターを指定したい場合に役立ちそうです。
また、CI 環境でテストの推移によってフィルターを変える、というような使い方もできそうですね。


IUTEST_PACKAGE v2 (多重定義制限の撤廃)
最後は地味な修正ですが、IUTEST_PACKAGE の制限を撤廃しました。
これまで、IUTEST_PACKAGE は一つのパッケージに付き、一箇所でしか使用できませんでした。
なので、以下のようにヘッダーファイルで IUTEST_PACKAGE(pkg1) をしたら、ソースファイルでは普通に namespace pkg1 と書く必要がありました。

// ヘッダー
IUTEST_PACKAGE(pkg1)
{
}

// ソース
namespace pkg1
{
}

こらが、v1.12.0 以降からはすべて IUTEST_PACKAGE(pkg1) のように統一した書式で書けるようになります。
// ソースでもヘッダーでも
IUTEST_PACKAGE(pkg1)
{
}




今回はこれで以上となります。
Twilio 対応、NuGet 対応については、別途ブログに書いてますので、そちらを参照してください。
ブログズミ: Twilio を使ってみた - その5

NuGet は次週。それでは。


2015年6月16日火曜日

[C++] Private な関数のテスト

本記事で扱うテスティングフレームワーク
Google Test
iutest (Google Test ライクなヘッダーオンリーテスティングフレームワーク)

C++ でテスト書いていると問題になるのが、private なメンバー関数をどうテストするか、です。
成功法としては、テストクラスを friend することです。
間違っても #define private public などとしてはいけません。

friend
Google Test の場合、テストクラスを friend する FRIEND_TEST マクロが用意されています。
また、テストフィクスチャクラスに対して friend 宣言すれば、そのテストケースではアクセス可能になります。

参照: GoogleTestでprivateメンバ関数をテストする | Geospatial屋
詳しいことは参照先を見ていただくとして、簡単に使い方を例として示します。

例1: FRIEND_TEST
// テスト対象クラス
class Hoge
{
   FRIEND_TEST(HogeTest, A); // TEST(HogeTest, A) から見えるようにする
   FRIEND_TEST(HogeTest, B); // TEST(HogeTest, B) から見えるようにする
private:
   int GetA() { return 1; }
   int GetB() { return 2; }
};

// テスト
TEST(HogeTest, A)
{
   Hoge hoge;
   ASSERT_EQ(1, hoge.GetA());
}
TEST(HogeTest, B)
{
   Hoge hoge;
   ASSERT_EQ(2, hoge.GetB());
}
テスト毎に FRIEND_TEST しないといけないので、ちょっと面倒ではありますが private メンバーにアクセスできるようになります。
例では書きませんでしたが、テストフィクスチャを使った場合(TEST_F)でも使用できます。
(※ 型付けテストでは使用できません。)

例2: friend TestFixture
2番目の方法は、テストフィクスチャクラスを friend する方法です。
// テスト対象クラス
class Hoge
{
   friend class HogeTest; // HogeTest フィクスチャーに対して friend
private:
   int GetA() { return 1; }
   int GetB() { return 2; }
};

// テスト
class HogeTest : public ::iutest::Test 
{
protected:
    Hoge hoge;
    // アクセサを書く
    int GetA() { return hoge.GetA(); }
    int GetB() { return hoge.GetB(); }
};
TEST_F(HogeTest, A)
{
    ASSERT_EQ(1, GetA());
}
TEST_F(HogeTest, B)
{
    ASSERT_EQ(2, GetB());
}
テストフィクスチャが必要になるので、TEST(Hoge, A) のようなテストには使えませんが、
FRIEND_TEST の時とは違ってテストケースすべてに対してアクセスを許可することができるので、使い勝手は良いです。

ただ、テストフィクスチャクラスでアクセサを書く必要があります。これは Google Test がテスト毎にテストフィクスチャを継承したクラスを定義しているからです。
とはいえ、一度テストフィクスチャを定義してしまえば使い回しが可能ですし、テストコード側の変更だけでテストを追加できるのが、この方法のメリットでしょう。

iutest でも、もちろん上記方法が使えます。

Google Test の問題
Google Test が用意している FRIEND_TEST マクロは、型付けテストには使えません
template<typename T> をつければいいだけなので、以下のようにマクロを追加すれば OK です。

#define FRIEND_TYPED_TEST template<typename T>FRIEND_TEST

iutest は、FRIEND_TYPED_TEST に対応済みです。

プロダクトコードに変更を加えない方法
さて、friend を使った方法は、プロダクトコード側に friend 宣言をする必要がありました。
その程度の記述は大したことないかもしれませんが、やはりプロダクトコードを1行も変えずにアクセスできたら便利ですよね。
(テスト名を書かないといけないのも個人的には面倒だなと思います。)

iutest では非侵入的に private メンバーにアクセスする方法を提供しています。


// テスト対象クラス
class Hoge
{
private:
   int GetA() { return 1; }
   int GetB() { return 2; }
};

typedef int (Hoge::* HogePrivateFunc)(); // iutest v1.12.0 からは typedef 不要になります
IUTEST_MAKE_PEEP(HogePrivateFunc, Hoge, GetA);
IUTEST_MAKE_PEEP(HogePrivateFunc, Hoge, GetB);

// テスト
IUTEST(HogeTest, A)
{
   Hoge hoge;
   IUTEST_ASSERT_EQ(1, IUTEST_PEEP_GET(hoge, Hoge, GetA)());
}
IUTEST(HogeTest, B)
{
   Hoge hoge;
   IUTEST_ASSERT_EQ(1, IUTEST_PEEP_GET(hoge, Hoge, GetB)());
}

なんか記述量増えてるし、マクロやばそうと思われる方もいると思いますが、
この方法であれば、完全にプロダクトコードを汚すことなく private なメンバーのテストが書けます。

private メンバーにアクセスする方法は、こちらで紹介されている方法を使いました。
privateメンバに外部から非侵入的にアクセスする - redboltzの日記 (archive)
 (追記: Wayback Machine にアーカイブが残っていた)

いや~凄いですね。
さて、来週に iutest v1.12.0 のリリースを予定してます。
正規表現アサーションの他、いろいろ更新されてますのでよろしくお願いします。