2012年12月27日木曜日

Google Test ユーザーが Boost.Test を使ってみた (補足)

この記事は、C++ Advent Calendar 2012: 17日目「Google Test ユーザーが Boost.Test を使ってみた」の補足記事になります。

本編では書ききれなかったことや、訂正なども含めて補足をしたいと思います。

値をパラメータ化したテスト
Boost.Test でも使えます。リファレンスはこちらです。

(Boost.Test Example)
#include <boost/test/included/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>
using namespace boost::unit_test;

//____________________________________________________________________________//

void free_test_function( int i )
{
    BOOST_CHECK( i < 4 /* test assertion */ );
}

//____________________________________________________________________________//

test_suite*
init_unit_test_suite( int argc, char* argv[] )
{
    int params[] = { 1, 2, 3, 4, 5 };

    framework::master_test_suite().
        add( BOOST_PARAM_TEST_CASE( &free_test_function, params, params+5 ) );

    return 0;
}

//____________________________________________________________________________//

こちらですが、自動でテストケースを認識・実行してくれる AUTO マクロがありません。
そのため、明示的に add する必要があります。

それはちょっと面倒臭い

ということで、簡単にマクロを用意してみました。
#include <boost/test/included/unit_test.hpp>
#include <boost/test/parameterized_test.hpp>
 
#define BOOST_AUTO_TEST_CASE_PARAM( function, begin, end )    \
BOOST_AUTO_TU_REGISTRAR( BOOST_JOIN(registrar, __LINE__)  )(  \
    BOOST_PARAM_TEST_CASE(function, begin, end) )
 
void free_test_function( int i )
{
    BOOST_CHECK( i < 4 /* test assertion */ );
}
 
int params[] = { 1, 2, 3, 4, 5 };
BOOST_AUTO_TEST_CASE_PARAM( &free_test_function, params, params+5 );
(ideone)



テストの中断
Boost.Test では REQUIRE 、Google Test では ASSERT フレーバーが失敗時にテストの中断をします。
ただ、両者でこの中断の挙動が違うので補足をしておきます。

Boost.Test
void SubFunc(void)
{
    BOOST_REQUIRE_EQUAL(0, 1);
    BOOST_REQUIRE_EQUAL(1, 2);
}

BOOST_AUTO_TEST_CASE(Sub)
{
    SubFunc();
    BOOST_REQUIRE_EQUAL(2, 3);
}
Google Test
void SubFunc(void)
{
    ASSERT_EQ(0, 1);
    ASSERT_EQ(1, 2);
}

TEST(Test, Sub)
{
    SubFunc();
    ASSERT_EQ(2, 3);
}
どちらも、アサーションを記述したサブ関数をテストから呼び出しています。
さて、ここで SubFunc(); 後のアサーションに到達するかが、ここでのお話です。
実際の出力を見てみましょう。



Boost.Test
Google Test
ご覧のように、Boost.Test は最初のアサーションの失敗で中断されていますが、Google Test は ASSERT_EQ(2,3); まで到達しています。
これは Google Test の中断が return 文を使った仕組みになっているからです。
なぜこのような実装になっているかは、こちらをご覧ください。

もし、SubFunc 内で失敗したときに、以降の処理を中断したい場合は以下のように書くことができます。
void SubFunc(void)
{
    ASSERT_EQ(0, 1);
    ASSERT_EQ(1, 2);
}

TEST(Test, Sub)
{
    ASSERT_NO_FATAL_FAILURE( SubFunc() );
    ASSERT_EQ(2, 3);
}
ASSERT_NO_FATAL_FAILURE(statement); は、statement で失敗があったかどうかを検証するアサーションです。


このように、SubFunc の失敗によりテストが中断します。

テスト以外での利用
Boost.Test や Google Test などテスティングフレームワークのアサーションは、ログに詳細な情報が出力されるので、普通の assert よりもとても有益な検証になります。
通常、テストの検証として使用するこれらアサーションを、テスト以外の場所でも使おうという話です。

Boost.Test の場合
#define BOOST_TEST_NO_MAIN
#include <boost/test/included/unit_test.hpp>

int main(int , char**)
{
    BOOST_CHECK_EQUAL(2, 3);
    BOOST_REQUIRE_EQUAL(1, 2);
    return 0;
}

特にログも出ずに死亡。うーん、残念。

Google Test の場合
#include <gtest/gtest.h>

void f(void)
{
    ASSERT_EQ(1, 2);
}

int main(int, char**)
{
    EXPECT_EQ(2, 3);
    f();
    return 0;
}


ログが出力されて正常終了しました。
また、GTEST_FLAG マクロを使って失敗時ブレークポイントを有効にすれば、より使い勝手が上がります。
int main(int, char**)
{
    ::testing::GTEST_FLAG(break_on_failure) = true; // break point を有効にする
    EXPECT_EQ(2, 3);
    f();
    return 0;
}

終わり
ちょっとしたことでしたが、補足はこれで終わりです。
また機会があればテスティングフレームワークについて書きたいと思います。

それでは、また来年!

2012年12月17日月曜日

Google Test ユーザーが Boost.Test を使ってみた

この記事は、C++ Advent Calendar 2012: 17日目の記事になります。
お題は「Google Test ユーザーが Boost.Test を使ってみた」です。
(2012/12/27: 補足記事を書きました。)

これまで、C++ の testing framework には Google Test を使ってきたのですが、
この機会に Boost.Test に挑戦したいと思います。
今年2月に行われた「Boost.勉強会 #8 大阪」の参加報告で Boost.Test 使うぜ!っと意気込んでおいて今更かという感じではありますが・・・

では、なぜ今まで使わなかったのかというと
  • boost の導入がめんどくさそう
  • 日本語情報が少ない
  • Google Test が使いやすかった
と、いう勝手なイメージがあったからです。最後のが一番大きな理由でした。
でも、他のフレームワークのことも知らずに「Google Test がいいよ!」というのもあれですよね。

それでは、そろそろ本題に入ります。
以下は、今回この記事を書くにあたって参考にさせて頂いたところです。

はじめに
実は、そもそも boost を使ったことありません。
というわけで、まずは boost のセットアップからしました。

開発環境は、Visual Studio 2012 Express 2012 for Windows Desktop です。
boost のバージョンは 1.52.0 です。

~~~略~~~

思っていた以上に簡単にできました!
(本題ではないので別記事にしました。)
include オンリーでも使えた
boost をビルドしたんですが、実はヘッダオンリーでも使えました。
ヘッダオンリーだと気軽に試せるので良いですね!

では、まずはヘッダーオンリーでテストを書いてみましょう。
簡単な例
まずは、簡単なテストから見ていきたいと思います。

#define BOOST_TEST_MAIN    // main関数を定義
#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(sample)

BOOST_AUTO_TEST_CASE(hoge)
{
    BOOST_CHECK_EQUAL(2*2, 4);
}

BOOST_AUTO_TEST_CASE(fuga)
{
    BOOST_CHECK_EQUAL(2*3, 6);
}

BOOST_AUTO_TEST_SUITE_END()

この辺は特に問題ないですね。
BOOST_AUTO_TEST_SUITE でグループ化できて、BOOST_AUTO_TEST_CASE でテストの中身が書けます。
書いたテストは Boost.Test が自動に検出して実行してくれます。
ちなみに、BOOST_AUTO_TEST_SUITE は必須ではありません。

Google Test と比較してみました。
Google Test
//

TEST(sample, hoge)
{
    EXPECT_EQ(2*2, 4);
}

TEST(sample, fuga)
{
    EXPECT_EQ(2*3, 6);
}

//
Boost.Test
BOOST_AUTO_TEST_SUITE(sample)

BOOST_AUTO_TEST_CASE(hoge)
{
    BOOST_CHECK_EQUAL(2*2, 4);
}

BOOST_AUTO_TEST_CASE(fuga)
{
    BOOST_CHECK_EQUAL(2*3, 6);
}

BOOST_AUTO_TEST_SUITE_END()


テストスイートが Google Test における TestCase に、
テストケースが Test(Info) にあたる感じです。
アサーション
値が等しいか検証する BOOST_CHECK_EQUAL など基本的なアサーションはそろっています。
どんなアサーションがあるかは、Boost.Test のリファレンスを参照してください。
(BOOST_CHECK_EQUAL_COLLECTIONS は Google Test にはないアサーションでイイなぁーと思いました。)

また、 Boost.Test のアサーションにはレベルが3種類あって、REQUIRE,CHECK,WARN が使えます。これらのレベルのことを Boost.Test ではフレーバー(flavor)といいます。

Google TestBoost.Testエラーカウントテストの実行
ASSERTREQUIRE増加中断
EXPECTCHECK増加継続
---WARNそのまま継続
(※ Boost.Test の中断は例外を使ったテストの中断、Google Test は return 文でのテスト関数の中断)

Google Test には WARN フレーバーがありませんが、コードを加えることで対応可能です。
詳しくはこちらを参考にしてください。
ブログズミ - Google Test で Boost.Test の WARN flavor を実現する

あと、大事な点を注意書きで済ませてしまってますが、まぁそこは気をつけてくださいってことで。

グループ化
先の説明で Boost.Test のテストスイートが Google Test の TestCase にあたると書きましたが、Boost.Test では namespace のように BOOST_AUTO_TEST_SUITE を複数ネストして使えます。
これは Google Test ではできないことです。

BOOST_AUTO_TEST_SUITE(sample)

BOOST_AUTO_TEST_SUITE(group1)

BOOST_AUTO_TEST_CASE(hoge)
{
    BOOST_CHECK_EQUAL(2*2, 4);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()

テストフィクスチャ
Boost.Test でもテストフィクスチャが使用できます。
テストフィクスチャはグローバル、テストスイート、テストケースの3箇所で設置できます。
テストフィクスチャの役割は、主に
  • テスト開始前のセットアップ
  • テストに関する特定の状態の提供
  • テスト終了後の後片付け
の3つです。

この辺は Google Test と変わりませんが、テストフィクスチャの構成や挙動に違いがあるので下記サンプルで説明していきます。
struct Fixture1 {
    Fixture1() : fix1(1) { ::std::cout << "F1 ->" << ::std::endl; }
    ~Fixture1() { ::std::cout << "<- F1" << ::std::endl; }
    int fix1;
};

struct Fixture2 {
    Fixture2() : fix2(2) { ::std::cout << "F2 ->" << ::std::endl; }
    ~Fixture2() { ::std::cout << "<- F2" << ::std::endl; }
    int fix2;
};

struct Fixture3 {
    Fixture3() : fix3(3) { ::std::cout << "F3 ->" << ::std::endl; }
    ~Fixture3() { ::std::cout << "<- F3" << ::std::endl; }
    int fix3;
};

BOOST_GLOBAL_FIXTURE(Fixture1);

BOOST_FIXTURE_TEST_SUITE(sample, Fixture2)

BOOST_FIXTURE_TEST_CASE(hoge, Fixture3)
{
//  BOOST_CHECK_EQUAL(1, fix1); // グローバルはできない?
//  BOOST_CHECK_EQUAL(2, fix2); // Fixture2 は適応されないみたい
    BOOST_CHECK_EQUAL(3, fix3); // フィクスチャメンバーにアクセスできる
}

BOOST_AUTO_TEST_CASE(fuga)
{
//  BOOST_CHECK_EQUAL(1, fix1);
    BOOST_CHECK_EQUAL(2, fix2);
    ++fix2;
}

BOOST_AUTO_TEST_CASE(bar)
{
//  BOOST_CHECK_EQUAL(1, fix1);
    BOOST_CHECK_EQUAL(2, fix2);
    ++fix2;
}

BOOST_AUTO_TEST_SUITE_END()

まず、挙動に関してです。

テストケースでは、テストフィクスチャの状態(メンバー)にアクセスすることができます。
しかし、複数のテストフィクスチャは適応されないようで、BOOST_FIXTURE_TEST_CASE(hoge, Fixture3) では Fixture2 が実行されないようです。
当然、Fixture2 の状態にもアクセスできません。

また、fuga, bar のテストフィクスチャである Fixture2 もテストケース毎に生成/削除されるようです。

Google Test ユーザーとしては、最初「?」となりました。
この辺は実際の出力をご覧ください。

(※ --log_level=test_suite で実行)

続いて、構成です。

Google TestBoost.Test
グローバル::testing::EnvironmentBOOST_GLOBAL_FIXTURE
テストスイート毎
(テストケース毎)
::testing::Test::SetUpTestCase,
::testing::Test::TearDownTestCase
テストケース毎
(テスト毎)
::testing::Test::SetUp,
::testing::Test::TearDown
BOOST_FIXTURE_TEST_SUITE
BOOST_FIXTURE_TEST_CASE
(※ ()書きは Google Test の場合)
(※ SetUp/TearDown に着目した表です。)

Boost.Test の場合、どこでも同じテストフィクスチャを使えますが、
Google Test の場合は、それぞれ書き方が違います。

同じテストフィクスチャでも Google Test と Boost.Test で大分異なりますね。

型をパラメータ化したテスト
複数の型に対して、同様のテストを書きたい場合の方法です。

(Boost.Test Example)
typedef boost::mpl::list<int,long,unsigned char> test_types;

BOOST_AUTO_TEST_CASE_TEMPLATE( my_test, T, test_types )
{
    BOOST_CHECK_EQUAL( sizeof(T), (unsigned)4 );
}

型リストには boost::mpl::list を使います。
この型リストの分だけテストが実行され、型は第二引数に指定した名前で参照します。

実行結果がこちら。

(※ --log_level=test_suite で実行)

型リストの分だけテストが実行されていることがわかると思います。
このように template 関数やクラスのテストを書くにあたって、型のパラメータ化テストが使えるとテストを非常に簡潔に書くことができます。
値をパラメータ化したテスト
Boost.Test に値のパラメータ化テストはない?
あって不思議じゃないんですが・・・リファレンス眺めた感じだと見あたらなかったです。

2012/12/20 追記:私の目が節穴だったようです。すみません。m(__)m

値のパラメータ化ありました。
リファレンスはこちらです。

実行時オプション
Boost.Test でもコマンドライン引数でテストの挙動を実行時に変更できます。
(※ 環境変数でも可能。詳しくはリファレンスを見てください。)

Google TestBoost.Test
テストのリスト表示gtest_list_tests
テストの選択gtest_filter=[filter]run_test=[filter]
無効テストの実行gtest_also_run_disabled_tests
シャッフルテストgtest_shufflerandom=[0|seed]
乱数シードgtest_random_seed=[seed]random=[seed]
繰り返しテストgtest_repeat=[count]
失敗時ブレークポイント停止gtest_break_on_failure
失敗時例外throwgtest_throw_on_failure
ログレベルlog_level=[level]
レポートレベルreport_level=[no|confirm|short|detailed]
ログフォーマット(gtest_output=xml[:path])output_format=[HRF|XML]
report_format=[HRF|XML]
色付き出力gtest_color=[yes|no|auto]
テスト時間出力gtest_print_time=[0|1|auto]
プログレス表示show_progress=[yes|no]
auto_start_dbg=[yes|no]
ビルド情報の出力build_info=[yes|no]
catch_system_errors=[yes|no]
framework での例外キャッチgtest_catch_exceptions=[0|1]
メモリリーク検出detect_memory_leak=[0|1|value > 1]
detect_fp_exceptions=[yes|no]
use_alt_stack=[yes|no]
終了コードresult_code=[yes|no]
ヘルプhelphelp
(※ 各オプションの前に "--" が必要です。)

ぱっと見ただけでも、Google Test と Boost.Test でできることが違うのがわかります。
テストの選択シャッフルテストはどちらも使えます。これは欠かせない機能ですね。
使い方がよくわからなかったオプションについては「?」としています。これは Boost.Test をもっと使っていけば分かるようになるんでしょう(きっと)。

Boost.Test ではログの出力レベルを細かく設定できます。その詳細です。
--log_level=test_suite はテストスイートの情報が表示されます。↑のサンプル画像を撮る際に使いました。
Value内容
allすべて表示
successall と同じ
test_suiteTestSuite のメッセージを表示
messageユーザーメッセージを表示
warning警告レポートを表示
errorエラーレポートを表示
cpp_exceptionキャッチされなかった例外を表示
system_error致命的でないシステムエラーの表示
fatal_error致命的なエラーの表示
nothingなにも表示しない
(※ 太字がデフォルト設定になります。)

Google Test の場合はログレベルの概念はありませんが、イベントリスナーをユーザーが定義することで独自の出力をさせることができます。
カスタムイベントリスナーの例はこちらを参照してください。
ブログズミ - Google Test で成功時のメッセージを非表示にする方法

テストレポート(XML)
Boost.Test の結果も Jenkins に集計させることができます!
個人的にこれがあるかないかで評価が大分変わってきます。

Google Test とは少し設定方法が違うので簡単に紹介をします。
Boost.Test で XML を出力するには、「--output_format=XML」オプションでできました。
また、Jenkins でのレポートの集計には、xUnit Plugin を使用します。
Jenkins の設定は Wiki を参考にしてください。

1点だけ注意。
--output_format=XML --log_level=all --report_level=no
Jenkins で集計してもらうためには、ログレベルなどのオプションも必要になります。

集計した結果はこんな感じで見れます。

イイ感じ!

ライブラリ版を使ってみる
ここまでヘッダーオンリーでテストを書いてきましたが、実運用で Boost.Test を使用する場合は Dynamic Library か Static Library を使うことをオススメします。ヘッダーオンリーでは、ソースファイルの分割ができないのと、コンパイルに時間がかかるからです。

ヘッダーオンリーからライブラリを使うように変更するのは簡単です。
まず、インクルードするヘッダーファイルを、
boost/test/included/unit_test.hpp から
boost/test/unit_test.hpp に変更します。
次に、[ライブラリディレクトリ]にビルドした boost の lib ファイルのあるパスを追加します。
リンクは unit_test.hpp でしてくれるので、あとは普通にビルドするだけです。

せっかくなので、ビルド時間を比較してみました。
struct Fixture1 {
 Fixture1() : fix1(1) { ::std::cout << "F1 ->" << ::std::endl; }
 ~Fixture1() { ::std::cout << "<- F1" << ::std::endl; }
 int fix1;
};

BOOST_AUTO_TEST_SUITE(GROUPNAME)

BOOST_AUTO_TEST_SUITE(a)

BOOST_AUTO_TEST_CASE(X)
{
    BOOST_CHECK_EQUAL(2*3, 6);
}

BOOST_AUTO_TEST_CASE(Y)
{
    BOOST_CHECK_EQUAL(2*3, 6);
}

BOOST_FIXTURE_TEST_CASE(Z, Fixture1)
{
    BOOST_CHECK_EQUAL(2*3, 6);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_FIXTURE_TEST_SUITE(b, Fixture1)

BOOST_AUTO_TEST_CASE(X)
{
    BOOST_CHECK_EQUAL(2*3, 6);
}

BOOST_AUTO_TEST_CASE(Y)
{
    BOOST_CHECK_EQUAL(2*3, 6);
}

BOOST_AUTO_TEST_SUITE_END()


typedef boost::mpl::list<int,long,unsigned char> test_types;

BOOST_AUTO_TEST_CASE_TEMPLATE( my_test, T, test_types )
{
    BOOST_CHECK_EQUAL( sizeof(T), (unsigned)4 );
}

BOOST_AUTO_TEST_SUITE_END()
上記コード x N個 (プリプロセッサで増やした) ものを
Windows7, メモリ: 4GB, CPU: Intel Core i3 2.53GHz, Visual Studio 2012 Express 2012 for Windows Desktop
でビルドしました。

結果
Nインクルードライブラリ
1000:00:16.8800:00:05.44
10000:00:20.3300:00:11.00
100000:04:04.3100:03:52.23
5000error C1060:
ヒープの領域を使い果たしました。
error C1001:
コンパイラで内部エラーが発生しました。
02:04:23.22
10000error C1060:
ヒープの領域を使い果たしました。
error C1001:
コンパイラで内部エラーが発生しました。
(※ /bigobj オプション付き)

テスト数に関係なくライブラリを使った方が、10秒ちょっと早い結果になりました。
もっと差が出るものかと思ったのですが…検証コードが良くなかったのか?

まとめ
まだまだ Boost.Test を説明しきれていないですが、
冒頭の Boost.Test を使わなかった理由がどのように変わったかで、まとめにしたいと思います。
  • boost の導入がめんどくさそう
    とても簡単に導入できました。
    ヘッダオンリーでも使えるので、試しに使いたい人はダウンロードするだけですぐに使えます。
  • 日本語情報が少ない
    この記事を書いているときに検索した感じでは、少なくはなかったです。
    ただ、もっと「ここがスゴイ!便利だ!」って感じの記事があるといいかもしれませんね。
  • Google Test が使いやすかった
    個人的にはやっぱり Google Test がいいなと思いました。
    理由としては値のパラメータ化テストとテストの繰り返し実行失敗時ブレークポイント停止がないのが大きいです。特にテストデータをランダム生成して --gtest_repeat=-1 --gtest_break_on_failure で失敗するまでエイジングする使い方をよくするので、それができないのが残念です。

最後に
なんだかまとまりのないブログになってしまいましたが、最後までお付き合い頂きありがとうございました。
内容に間違いなどありましたら、コメント下さい(^^ゞ

最後に宣伝。
オレオレテスティングフレームワーク開発中です!
Boost.Test を使ってみていいなと思った機能は自作テスティングフレームワークの iutest に取り込んでいきたいと思います(^^
そして本日、iutest v1.2.0 をリリースしました。


C++ Advent Calendar 2012: 次は、krustf さんで「Cer に知って欲しい C++」です。 →「krustf の雑記
See ya!

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

ダウンロードはこちらからできます。

今回の目玉アップデートは、「パッケージ機能」の追加です。
パッケージ機能については以前にブログに書いたので、そちらを見てください。

また、EQ_COLLECTIONS も追加しました。
各要素ごとに検証してログ出力してくれます。
IUTEST(Test, EqCollection)
{
    int  a[] = { 0, 1, 1, 3, 3 };
    int  b[] = { 0, 1, 2, 3, 4, 5 };
    ::std::vector c;
    for( int i=0; i < (sizeof(a)/sizeof(a[0])); ++i )
    {
        c.push_back(i);
    }
        
    IUTEST_EXPECT_EQ_COLLECTIONS(a, a+(sizeof(a)/sizeof(a[0])), b, b+(sizeof(b)/sizeof(b[0])));

    IUTEST_EXPECT_EQ_COLLECTIONS(a, a+(sizeof(a)/sizeof(a[0])), c.begin(), c.end());
}

あとはプログレス表示するイベントリスナーを追加しました。

さて、次は iutest_c v1.1 かなぁ

Visual Studio Express 2012 for Windows Desktop で boost をビルド

自分用備忘録です。

ビルド済みバイナリという選択
BoostPro Binary Installer for Visual C++
こちらからビルド済みバイナリが取得できるので、まずはこちらを確認してもいいのかも。

ダウンロード
Boost 公式からダウンロードします。
今回は、boost 1.52.0 をダウンロードしました。

ダウンロードしたら任意の場所に展開します。

ビルド
  1. [スタートメニュー]->[Microsoft Visual Studio 2012]->[Visual Studio Tools]->[VS2012 の開発者コマンド プロンプト] を実行する
  2. 展開したフォルダに移動する
  3. 「bootstrap.bat && b2.exe」と入力し実行
  4. 待つ
  5. 完了

リンク
ビルドしたライブラリは、 /stage/lib/ 以下に出力されます。
プロジェクトのプロパティのから、 /stage/lib を[追加のライブラリ ディレクトリ]に追加します。
また、[追加のインクルード ディレクトリ]に boost のパスを追加しておきます。

あとは、普通に使うだけです。


boostjp に書いてあった
ここまで書いて気づいたけど、boostjp に書いてありました f(^^;

2012年12月13日木曜日

Jenkins + CCTray(ジョブ監視ツール)

Jenkins の失敗通知をメールでしていると、
そのうちメールを読まなくなって失敗を放置、なんてことがあったりします。
(本当はちゃんと読まないとダメなんだけど・・・)

そこで私は、CCTray というタスクトレイ常駐型の通知ツールを使っています。
CCTray は、去年の Advent Calender でも取り上げられていました。
Jenkinsのモニタリング - Jenkins Advent Calendar 2011 - Day 12

とっても便利でずっと使ってたのですが、
最近 Anonymous の権限を変更したらジョブが見れなくなってしまいました。

できれば解決方法をここに書きたかったところですが、残念ながら未解決でございますm(_ _)m


でも、せっかくなので CCTray の紹介でもしておきたいと思います。
まずは、簡単にインストールから設定までを説明します。
インストール
CCTray は、こちらからダウンロードしました。(CruiseControl.NET-CCTray-1.8.2.0-Setup.exe)
http://en.sourceforge.jp/projects/sfnet_ccnet/releases/

ダウンロードしたら、インストーラーを起動し指示に従ってインストールするだけです。

設定
CCTray を起動したら [Settings...] を選択して設定ダイアログを開きます。
[Build Projects] タブを選択し、[Add...] ボタンを押します。

[AddServer] ボタンを押します。

[Supply a custom HTTP URL] を選択し、https://jenkins:port/cc.xml と入力します。
このアドレスは 「 jenkins のビューの URL + /cc.xml 」になります。
これはユーザーが作成したビューでも OK です。
URL を入力したら OK ボタンを押します。

[Available Projects]にプロジェクトがリストアップされるので、
この中から監視したいものを選択して、OK します。
(サーバーURL に指定した Jenkins のビューにあるプロジェクトがリストアップされます。)


これで設定は終わりです。

ビルドが失敗するとこのように表示されます。



read 権限がないと・・・
冒頭で書いた問題についてです。

Anonymous に read 権限がないとプロジェクトが見えません。


CCTray 設定の [Build Server] の [Configure] で、
[Server is secure] にチェックを入れて [User name/password authentication] を設定してみましたが、
こんな感じでうまくいきませんでした。





うーん。もうちょっと調べよう。。。