2012年2月22日水曜日

neocomplcache-snippets-complete 色々対応してもらった

neocomplcache-snippets-completeのprev_wordって何,とか書いてたら,
この素晴らしいプラグインの生みの親の@ShougoMatsuさんが
さっとドキュメントを修正してくれた上に,この動作ってこれでいいの,とか
話していたのまで拾ってイイ感じに修正してくれた.神じゃなかろうか?

とりあえず,prev_word '^'を書いておくと,そのsnippetは行頭じゃないと
補完候補にも挙がりません.今まではsnippet名さえ合っていれば補完はされないけど
展開されていたのが,今回展開もされないようになりました.

ついでに,前に書かなかった他の便利そうな機能も書いておこう.

snippet c
abbr C++ Class
prev_word '^'
    /*
        @author `$USER`
     */
    class ${1} {};

とこんな感じに,``を使うと式を評価してくれてその結果に置き換えてくれる.
何というか,こうサポートしてもらえるともっと使いたいって気になるよね.

2012年2月21日火曜日

neocomplcache-snippets-completeいいよ

実は,neocomplcacheのsnippetを利用していなかったので,ふと思い立ちインストールして使ってみた.簡単な使い方が分かっただけでもこれ便利だわって感じ.

インストールと設定

neocomplcacheはインストールして設定済みの前提で,neobundle.vimでneocomplcache-snippets-completeをインストールする.
" .vimrc
NeoBundle 'Shougo/neocomplcache-snippets-complete'

" snippetの配置場所
g:neocomplcache_snippets_dir='~/.vim/snippets'

" キーマップ
imap <C-k> <plug>(neocomplcache_snippets_expand)
smap <C-k> <plug>(neocomplcache_snippets_expand)

Snippetの作成
g:neocomplcache_snippets_dirで設定した場所に,ファイルタイプ名.snipでsnippetを書いておくファイルを用意する.
とりあえず,C++のBoost.Test用のコードのsnippetを用意してみた.

snippet     batc
abbr        BOOST_AUTO_TEST_CASE
prev_word   '^'
    BOOST_AUTO_TEST_CASE(${1:TestName})
    {
        BOOST_FAIL("Fail");
    }

後は,C++のソースコードでbatcと入力して,を押せばsnippetが展開される.${数字}または${数字:デフォルト値?}で
プレースホルダを設定できて,で次へ次へと飛んでいけるみたい.

ただ,何故かVimを再起動しないと上手くsnippetを読み込んでくれなかった.

プレースホルダの同期
更にあるプレースホルダで設定した内容を他の部分に反映ということまでやってくれる.

snippet     c
abbr        C++ class
prev_word   '^'
    class ${1:name} {
    public:
        $1();
        $1($1 const &);
        ~$1();
    private:
    };

これで,クラス名を入力すると,自動的にコンストラクタ,コピーコンストラクタ、デストラクタが宣言される.
${数字}で入力した内容を$数字に反映できる.

これだけでも十分使えるよなぁ.後はsnippetを増やしていけば、本当に便利そう.何で今まで使ってなかったのか、と思うね.

ところで、このsnippetの文法というか構文というかは、neocomplcache-snippets-completeのドキュメントだけで完結しているのかな?
ざっと読んだ感じだとprev_wordって何か分からなかったんですが.

2012年2月12日日曜日

Boost.Test Step 5

後はファイルをテストスイート毎に分割できると良いかな,ってことで分割してみた.

とりあえず,メイン.たぶんこのファイル中のテストスイートも外に出せる.
// main.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>

bool isOdd(int n)
{
    return n % 2 != 0;
}

BOOST_AUTO_TEST_SUITE(OddTest)
BOOST_AUTO_TEST_CASE(oddTest)
{
    BOOST_CHECK_EQUAL(isOdd(0), false);
}
BOOST_AUTO_TEST_SUITE_END()

偶数判定用のテストスイートはa.cppというファイルに.
// a.cpp
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>

bool isEven(int n)
{
    return n % 2 == 0;
}


BOOST_AUTO_TEST_SUITE(EvenTest)
BOOST_AUTO_TEST_CASE(evenTest)
{
    BOOST_CHECK_EQUAL(isEven(0), false);
}
BOOST_AUTO_TEST_SUITE_END()

これをつないでビルドすれば実行できる.
$ g++ -o main main.cpp a.cpp -lboost_unit_test_framework
$ ./main --report_level=detailed
a.cpp:13: error: in "evenTest": check isEven(0) == false failed [true != false]

Test suite "Master Test Suite" failed with:
  1 assertion out of 2 passed
  1 assertion out of 2 failed
  1 test case out of 2 passed
  1 test case out of 2 failed

  Test suite "OddTest" passed with:
    1 assertion out of 1 passed
    1 test case out of 1 passed

    Test case "oddTest" passed with:
      1 assertion out of 1 passed

  Test suite "EvenTest" failed with:
    1 assertion out of 1 failed
    1 test case out of 1 failed

    Test case "evenTest" failed with:
      1 assertion out of 1 failed

基本的な使い方はこれで一通り把握できたかなぁ.しかし相変わらずドキュメントが読みにくかった.

Boost.Test Step 4

テストケースをいくつかまとめたものをテストスイート(この場合のスイートはsuiteであって,sweetじゃない.)と言う.
BOOST_AUTO_TEST_SUITE(スイート名),BOOST_AUTO_TEST_SUITE_END()で囲めば良い.

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>

bool isOdd(int n)
{
    return n % 2 != 0;
}

bool isEven(int n)
{
    return n % 2 == 0;
}

BOOST_AUTO_TEST_SUITE(OddTest)
BOOST_AUTO_TEST_CASE(oddTest)
{
    BOOST_CHECK_EQUAL(isOdd(0), false);
}
BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(EvenTest)
BOOST_AUTO_TEST_CASE(evenTest)
{
    BOOST_FAIL("Fail");
}
BOOST_AUTO_TEST_SUITE_END()

これを実行すると,こんな感じ.

$ ./main --report_level=detailed
Test suite "Master Test Suite" failed with:
  1 assertion out of 2 passed
  1 assertion out of 2 failed
  1 test case out of 2 passed
  1 test case out of 2 failed
  1 test case out of 2 aborted

  Test suite "OddTest" passed with:
    1 assertion out of 1 passed
    1 test case out of 1 passed

    Test case "oddTest" passed with:
      1 assertion out of 1 passed

  Test suite "EvenTest" failed with:
    1 assertion out of 1 failed
    1 test case out of 1 failed
    1 test case out of 1 aborted

    Test case "evenTest" aborted with:
      1 assertion out of 1 failed

オプションに,--report_level=detailedを入れないとここまで詳細に出ない.他にも自動的に組み込まれるオプションがいくつかある.--show_progress=yesでテストの進捗を表示したり.--helpで確認可能.

Boost.Test Step 3

とりあえず奇数判定を行う関数を実装し,適当にテストしてみる.

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE OddTest
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>

// 奇数判定を実装
// 奇数は2で割った余りが1になる数?
bool isOdd(int n)
{
    return n % 2 == 1;
}

BOOST_AUTO_TEST_CASE(oddTest)
{
    // 非負偶数の場合
    BOOST_CHECK_EQUAL(isOdd(0), false);
    BOOST_CHECK_EQUAL(isOdd(2), false);

    // 非負奇数の場合
    BOOST_CHECK_EQUAL(isOdd(1), true);
    BOOST_CHECK_EQUAL(isOdd(3), true);
}

実行結果はこんな感じ.

Running 1 test case...

*** No errors detected

正しく動作するものを書いたので,当然成功する.ところが,テストケースにちょっと判定文を追加すると,テストに失敗する.

BOOST_AUTO_TEST_CASE(oddTest)
{
    // 非負偶数の場合
    BOOST_CHECK_EQUAL(isOdd(0), false);
    BOOST_CHECK_EQUAL(isOdd(2), false);

    // 非負奇数の場合
    BOOST_CHECK_EQUAL(isOdd(1), true);
    BOOST_CHECK_EQUAL(isOdd(3), true);

    // 負偶数の場合
    BOOST_CHECK_EQUAL(isOdd(-2), false);
    BOOST_CHECK_EQUAL(isOdd(-4), false);

    // 負奇数の場合
    BOOST_CHECK_EQUAL(isOdd(-1), true);
    BOOST_CHECK_EQUAL(isOdd(-3), true);

}

出力結果は次のようになる.

Running 1 test case...
main.cpp:27: error: in "oddTest": check isOdd(-1) == true failed [false != true]
main.cpp:28: error: in "oddTest": check isOdd(-3) == true failed [false != true]

*** 2 failures detected in test suite "OddTest"

原因は奇数の定義を2で割った余りが1になるとしたこと.この割った余りを正数にするか,
負数にするかっていうのは言語によって違うのだけれど,この場合,2で割り切れなければ奇数,つまり2で
割った余りが0で無ければ良いので,関数を修正する.

bool isOdd(int n)
{
    return n % 2 != 0;
}

これで無事テストが通る.

Boost.Test Step2

とりあえず前回作ったファイルにテストケースを追加する.BOOST_TEST_MAINの代わりにBOOST_TEST_MODULEを定義する.

// 動的リンクを使用
#define BOOST_TEST_DYN_LINK
// テストモジュール名を定義
#define BOOST_TEST_MODULE OddTest
#include <boost/test/unit_test.hpp>
// BOOST_AUTO_TEST_CASE などに必要
#include <boost/test/unit_test_suite.hpp>

// とりあえず奇数判定のテストケースの枠だけ作って
// 失敗することを確認
BOOST_AUTO_TEST_CASE(oddTest)
{
    BOOST_FAIL("Fail");
}

実行結果はこんな感じ.

Running 1 test case...
main.cpp:11: fatal error: in "oddTest": Fail

*** 1 failure detected in test suite "OddTest"

どうでも良いことなんだけど,テストケース,という用語に違和感を覚えないでも無い.一揃いの入力をテストケース,その集合をテストセットと言うような研究を何年も見てきたからだと思う.ここで言うテストケースってテストセットのことだよね,という気がしてならない.まぁ,本当にどうでも良いことなんだけどね.

Boost.Test Step 1

とりあえず,Boost.Testの使い方を適当にまとめておこうかと.何ステップになるか分からないけれど.

最小(?)のファイル

// main.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

とりあえず,この3行の入ったコードをビルドすると最低限の処理が組み込まれる(コメントは除く).
なお,#defineは#includeの前に書いておかないと意味が無いので注意.

$ g++ -o main main.cpp -lboost_unit_test_framework
なお,Boostがインストールされている場所に,INCLUDEやLIBRARY_PATH,LD_LIBRARY_PATH,DYLD_LIBRARY_PATHといった環境変数が設定されているという前提。
Lionで実行したときは,DYLD_LIBRARY_PATHが適切に設定されていなくて動的ライブラリを見つけられずに上手く動かなかった.

これを実行すると,次のようにエラーが報告される.
$ ./main
Test setup error: test tree is empty

まだ何も登録していないので当然と言えば当然である.とりあえず,これでBoost.Testを使う準備はできたかな.

Boost.勉強会 #8 大阪に参加しました.

昨日Boost.勉強会 #8 大阪に参加してきました.
近くで開催されるということと,ゲーム開発会社が協賛ということで,色々と楽しみにしながら参加しました.

Test Driven Development
今回個人的に注目していたのは,テスト駆動開発(Test Driven Development, TDD)を
ゲーム開発で実践している,という話が聞けるということと,そのために使うBoost.Test
についての話が聞けるということでした.

結論から言うと,聞きたかったこととは若干外れていたかな,という感じです.テスト駆動開発については今から始めるということで,色々とライブラリが紹介されたのは良かったのですけど,個々のライブラリの比較はまだ出来てないのかな,と.今後実践していった結果のノウハウが紹介されることに期待です.

Boost.Testについては,ドキュメントの翻訳,という感じでした.ある程度経験を交えてかみ砕いているもののところどころで,よく分からないです,が入るのでいまいちただしいのかどうか分からなかったです.

メモリアロケータ
これも注目していた話の一つです.いくつかのメモリの管理手法が紹介され,その違い,使用されている具体例,実際に計測してみての速度差を見せる,と言った内容が分かりやすく,しかもテンポ良く説明しているので分かりやすかったです.ソースコードも公開されているので,後から勉強もしやすく良かったです.

Vim
今回目立ったのは,発表者の多くがVimを使っていたということでしょうか.
やはりVimは素晴らしいですね.人によってはほとんどの作業がVimの上で完結するという.
皆さんもVimを使いましょうw

その他の発表について
凄いけどついて行けない部分も,というのが正直な感想だったり.

全体的に
全体的に,参加者が固定されてきているのかなぁ,という感じがしました.もう何回も開催されている勉強会なので,顔なじみがいるのは当然のことですが,一番後ろの席に座っていると,前半分と後ろ半分の温度差が激しいなぁ,と感じました.発表者に絡んだネタも前半分だけに受けていたり.
ちょっとグダグダだったりするのも仕方ないと言えば仕方無いのですけれど,当日にも発表資料を作っているというような状況が当たり前のように受け入れられるのは良いのかな,と感じました.
どちらかというと勉強しに行く場,というよりもそういう人たちに会って直接話をして,ネタを集める場なのかなぁ,という感じでした.

とりあえず,Boost.Testについては気になったのでもうちょっと自分でも調べて行こうかなぁ,というつもりです.