まだリリース版に入っていませんが、groongaのリポジトリにはMuninプラグインが入っています。
プラグインは5種類あり、それぞれ以下の値をグラフにします。
グラフの実例: rurema.clear-code.comのもの
必ずしもすべてのプラグインを使った方がよいというわけではありません。ユースケース毎に利用した方がよいプラグインは以下の通りです。
これらのプラグインは、groonga(のHEAD)をインストールすると$PREFIX/share/groonga/munin/plugins/以下にインストールされます。例えば、以下のようにインストールした場合は$HOME/local/share/groonga/munin/plugins/以下にインストールされます。
% git clone git://github.com/groonga/groonga.git % cd groonga % ./autogen.sh % ./configure --prefix=$HOME/local % make % make install
まず、インストールされたプラグインのシンボリックリンクをMuninのプラグイン置き場へ置きます。Debian GNU/Linuxでは/usr/share/munin/plugins/がMuninのプラグイン置き場なので以下のようになります。
% cd /usr/share/munin/plugins % sudo ln -fs ~/local/share/groonga/munin/plugins/* ./
groonga_n_recordsとgroonga_statusはRubyで書かれていて、JSONライブラリを必要とします。これらのプラグインを使う場合はRubyとRubyのJSONライブラリをインストールしておく必要があります。Debian GNU/Linuxの場合は以下のようにインストールできます。
% sudo aptitude -V -D -y install libjson-ruby
次に、プラグインの設定をします。Debian GNU/Linuxであれば、以下のような内容の/etc/munin/plugin-conf.d/groonga.confを作成します。(groongaサーバを起動していて、起動中のgroongaサーバのプロセスIDが/var/run/groonga/groonga.pidに書いてある場合。)
[groonga_*] env.pid_file /var/run/groonga/groonga.pid
例えば、以下のように起動すると、/var/run/groonga/groonga.pidにプロセスIDが記録されます。
% sudo mkdir -p /var/run/groonga % sudo chown groonga:groonga /var/run/groonga % groonga -d /var/lib/groonga/db 2>/var/run/groonga/groonga.pid
この設定をすることで、以下の3つのプラグインを利用できます。
また、gqtp(groonga独自プロトコル)でgroongaサーバを起動していれば以下のプラグインも利用できます。
もし、標準以外のポートでgroongaサーバを起動しているときはenv.portも設定する必要があります。以下はgroongaサーバを20041番ポートで起動している場合の例です。
[groonga_*] env.port 20041
rroongaなど直接データベースを操作している場合は、同じデータベースを指定してgroongaサーバを起動してください。groongaは複数のプロセスで同じデータベースを操作することができるので、rroongaで操作しているデータベースの内容をgroongaサーバから参照することも問題なくできます。
例えば、~/local/var/lib/groonga/dbにデータベースを置いている場合は以下のようにして、Munin用にgroongaサーバを起動できます。
% groonga -i 127.0.0.1 -d ~/local/var/lib/groonga/db
上記のように/usr/bin以外の場所にgroongaをインストールした場合はenv.groongaでgroongaコマンドのパスを指定します。
[groonga_*] env.groonga /home/groonga/local/bin/groonga
設定ファイルを作成したら必要なものだけ有効にします。
これらのプラグインはautoconfに対応しているので(参考: Muninプラグインの作り方)、以下のコマンド(Debian GNU/Linuxの場合)で必要なものだけインストールできます。
% sudo -H /usr/sbin/munin-node-configure --shell --remove-also | sudo -H sh
munin-nodeの再起動を忘れないようにしましょう。
% sudo /etc/init.d/munin-node restart
最近追加されたgroonga用のMuninプラグインのインストール方法を紹介しました。
groonga_memoryなどはgroonga専用ではなく、もっと汎用的に利用できます。groongaのMuninプラグインを参考にするなど、自分用のMuninプラグインを作ってみてはいかがでしょうか。
あわせて読みたい: Muninプラグインの作り方
先月、オライリージャパンからセキュリティの神話という本が出版されました。McAfeeの人が書いたセキュリティに関するエッセイ集の翻訳です。
セキュリティ業界の人が建前無しでどんなことを考えているか、を気軽に読みたいならよい本でしょう。この本を読んでセキュリティの考えを深めたいというよりも、セキュリティについて視点を広げたいという方に向いているでしょう。
それぞれの章の内容はほぼ独立していて、アンチウィルスのこと以外の話題も多くあります。それぞれの章は、最初に話題の概要を話して、それに関する著者が思いつく考えをいくつも話して、最後に簡単にまとめる、という流れになっています。真ん中の著者の考えのところでは、1つの話題に対して何パターンも考えを書いています。おそらく、自分はそうは考えなかったという新しい視点が見つかるでしょう。
ただ、その考えがすべてがすべて素晴らしいものと感じるものではないでしょう(当然ですが)。むしろ、多くの考えはうーんと感じるかもしれません。
たびたび「McAfeeいいよ」みたいなことが書かれていますが、その一方で「ちゃんとセキュリティ対策ソフトを使え。俺は使わないけどね。」みたいなことが書かれています。「自分のところで作っているものを自分は使わないのに、いいよって言われても。。。」と感じてしまうところですが、おそらく、著者がホントに思っていることを書いたのが本書なんでしょう。そのため、セキュリティ業界にいる人の率直な考えを読むことができるといえます(よくも悪くも)。
著者が使っているほぼ100%検出する迷惑メール対策の方法も書かれています。個人でやるにはそれでもいいかもね、というような内容です。概要が書かれているだけですが、それを読む感じだといくつか問題がありそうです。
オープンソースソフトウェアとセキュリティについても書かれています。エリック・レイモンドの伽藍とバザールを参照して、「オープンソースの方がクローズドなソフトウェアよりもセキュアと言われているけど、そうじゃないよね」、という話題です。ただ、脚注にも以下のように伽藍とバザールの内容が引用されている通り、エリック・レイモンドは「オープンソース=セキュア」とは言っていないですよね。
ベータテスタと共同開発者の基盤さえ十分大きければ、ほとんどすべての問題はすぐに見つけだされて、その直し方もだれかにはすぐわかるはず。
[伽藍とバザールより引用]
オープンソースにしたからといってバザール方式でうまくまわるとは限らないということは、実際にやってみるとすぐにわかります。
ここでは、最終的に「オープンかクローズドかは関係ないよね」となるのですが、そこに至るまでに7個の考えを出しています。このようにいろいろなパターンの考えを読めるのは魅力でしょう(考えの内容が納得できるかどうかは別として)。
他にも「Googleは邪悪?」では、「Googleのやり方はよくない」みたいなことを書いています。同じようなことはMcAfeeには言えないだろうか、などと考えながら読むのもよいかもしれません。
セキュリティの神話という本の内容を紹介しました。気軽に読めるセキュリティ関係の読み物として読んでみてはいかがでしょうか。読みやすい日本語になっているところと、話題についての日本での状況が脚注として追加されているところは、原書にはない翻訳版ならではの嬉しいところでしょう。
Web上にいくつか言及しているページがあったので、リンクしておきます。
いくつか誤植があるので、読んでがっかりする前に、まず正誤表を見てこのくらいあるんだなと思っておいた方がよいでしょう。読んでいるうちにいくつか見つけものがありましたが、それは報告してあるので、しばらくすれば正誤表に反映されたり、増刷の時に書籍に反映されたりするでしょう。
最近のセキュリティまわりの話題にも興味がある場合はセキュリティExpert 2010も読んでみるとよいでしょう。
git関連の様々なユーティリティソフトウェアのパッケージであるgit-utilsのバージョン0.0.1をリリースしました。このパッケージには、gitリポジトリ用のコミットメール送信スクリプトcommit-email.rbが入っています。以下からダウンロードできます。
今回のリリースはgit-utilsの最初のリリースです。
このパッケージに同梱されているcommit-email.rbを使うことで、gitリポジトリにpushされたコミットのコミットメールを送信することができます。
gitでは複数のコミットを一度にリポジトリに追加することができます。これはpushと呼ばれています。commit-email.rbはインストールしたリポジトリに対してpushが発生する度に実行されます。そして、そのpushの中にあるコミットごとに差分付きでメールを送信します。gitで標準でインストールされるコミットメール送信ソフトウェアだとpushごとに一通のメールが送信されます。
差分も付いているのでコミットの中身を調べ直すためにローカルのリポジトリを参照する必要はありません。なので、しっかりとソースコードの修正を含めてリポジトリの変更をフォローしていきたい、尚且つ、メールのみでリポジトリの変更を把握したい場合に適しています。
それでは早速実際に使ってみましょう。今回は、コミットメールの送り先として、Unix-likeなOSに標準で付いているスプール方式のメールボックスにコミットメールを送ることにします。メールアドレスが「ローカルマシンのユーザー名@localhost」となります。
まずはコミットメールを送信するためのgitリポジトリを作成します。今回はローカルで作業しますが、このリポジトリはサーバー上にある公開用のgitリポジトリだと思って下さい。
$ git clone --bare http://git.clear-code.com/git-utils git-utils
次に新しく作成したgitリポジトリでcommit-email.rbを動かすように設定します。userの部分をローカルマシンで使っているあなたのユーザー名に置き換えてください。
$ cd git-utils $ cat <<'EOC' > ./hooks/post-receive #!/bin/bash /usr/bin/ruby ./hooks/commit-email.rb --repository="$(pwd)" --to user@localhost EOC $ chmod +x ./hooks/post-receive
上の2行のコマンドではbareなgitリポジトリに移動し、commit-email.rbを実行するpost-receiveと呼ばれるフックスクリプトを作成し、実行権限を付与しています。
次にcommit-email.rbをpost-receiveから実行できるようにファイルを用意する必要があります。上のリンクからgit-utils-0.0.1.tar.gzをダウンロードし、展開後、commit-email.rbというファイルを./hooksディレクトリにコピーして下さい。
これでコミットメールを送信するリポジトリ側の設定は完了です。次にこのリポジトリからcloneして作業用のリポジトリを作成します。そして、コミットを作成し、pushして実際にメールが送信されるかを確認してみましょう。
$ cd .. $ git clone git-utils git-utils-work $ cd git-utils-work
./test-commit-email.rbを最新開発版のRuby 1.9.3devで動かしてみると分かりますが、Time#succ
はobsoleteされtime + 1
を使うように警告されます。今回はこれを直しましょう。git diffすると以下のようになるように編集してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
diff --git a/test-commit-email.rb b/test-commit-email.rb index c4a7024..8f1857f 100755 --- a/test-commit-email.rb +++ b/test-commit-email.rb @@ -658,7 +658,7 @@ module HookModeTest end def advance_timestamp - @timestamp = @timestamp.succ + @timestamp += 1 end def delete_output_from_hook |
それではいよいよコミットしpushして見ましょう。
$ git commit -m "use time + 1 instead of Time#succ" ./test-commit-email.rb $ git push origin master
これで以下のようなメールがメールボックスに追加されているはずです。
Ryo Onodera 2010-05-18 13:05:56 +0900 (Tue, 18 May 2010) New Revision: a6841ded1d2cc70d6d98d03de023c5a57f3c0f85 Log: use time + 1 instead of Time#succ Modified files: test-commit-email.rb Modified: test-commit-email.rb (+1 -1) =================================================================== --- test-commit-email.rb 2010-05-13 18:59:25 +0900 (c4a7024) +++ test-commit-email.rb 2010-05-18 13:05:56 +0900 (8f1857f) @@ -658,7 +658,7 @@ module HookModeTest end def advance_timestamp - @timestamp = @timestamp.succ + @timestamp += 1 end def delete_output_from_hook
git-utils 0.0.1の初リリースの告知とその中に同梱されているcommit-email.rbの説明とインストール方法を紹介しました。
Python用単体テストフレームワークであるPikzieのバージョン0.9.7をリリースしました。
Cutter、UxUと同じように、ついにPikzieでもデータ駆動テストをサポートしました。
例えば、今までこのように書いていたテストがあるとします。
test_prime.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import pikzie def test_zero(): assert_false(is_prime(0)) def test_unit(): assert_false(is_prime(1)) def test_small(): assert_true(is_prime(2)) def test_square(): assert_false(is_prime(4)) |
単体テストを書き始めたばかりの人は以下のように1つにまとめてしまうかもしれません。
test_prime.py:
1 2 3 4 5 6 7 |
import pikzie def test_is_prime(): assert_false(is_prime(0)) assert_false(is_prime(1)) assert_true(is_prime(2)) assert_false(is_prime(4)) |
しかし、このような書き方はおすすめできません。異なるパターンのテストは別のテストにするべきです。そうすると、1つのパターンが失敗しても他のパターンはその影響を受けずに実行することができます。
例えば、is_prime(1)
が失敗するとしましょう。そのとき、前者は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 実行される。パスする。 def test_zero(): assert_false(is_prime(0)) # 実行される。失敗する。 def test_unit(): assert_false(is_prime(1)) # 実行される。パスする。 def test_small(): assert_true(is_prime(2)) # 実行される。パスする。 def test_square(): assert_false(is_prime(4)) |
test_unit()が失敗しても他のパターンはテストできます。
一方、後者は以下のようになります。
1 2 3 4 5 |
def test_is_prime(): assert_false(is_prime(0)) # 実行される。パスする。 assert_false(is_prime(1)) # 実行される。失敗する。 assert_true(is_prime(2)) # 実行されない。 assert_false(is_prime(4)) # 実行されない。 |
is_prime(1)
以降が実行されないため、is_prime(1)
のパターンだけが失敗するようになったのか、他のパターンも一緒に失敗するようになったかがわかりません。
問題を解決する時は、まず、どのようなときに発生するのかを見極める、つまり、原因を見極める必要があります。そのとき、問題が発生するときの情報を多く得られると、原因を見極めるために役立ちます。そのため、独立したパターンは独立して実行されるようにしておく方がよいのです。
しばらくテストを書いたり読んだりしていると、実は、前者の書き方には上記の理由以上に大事なことがあることがわかります。それは、テストする内容に名前をつけていることです。プログラミングは名前をつける作業である、と言っても過言ではありませんが、それについてはまたいつか書く機会があるといいですね。
だいぶ前置きが長くなりましたが、データ駆動テスト機能を使う場合は以下のように書きます。
test_prime.py:
1 2 3 4 5 6 7 8 9 10 11 |
import pikzie @pikzie.data("small", 2) def test_true(number): assert_true(is_prime(number)) @pikzie.data("zero", 0) @pikzie.data("unit", 1) @pikzie.data("square", 4) def test_false(number): assert_false(is_prime(number)) |
@pikzie.data()
でテスト(ここではtest_true
とtest_false
)にデータの名前とデータを登録します。データを登録するとあとはPikzieがデータを引数としてテストを実行します。
それぞれのテストデータは独立しているので、1つのテストデータでテストが失敗しても、他のテストデータは影響を受けません。あるテストデータに対してテストが失敗したかどうかに関わらず、すべてのテストが実行されます。つまり、データ駆動テストを使用していない2つの例のうち、前者と同じ挙動になるということです。
is_prime(1)
が失敗する場合は、以下のようになります。
1 2 3 4 5 6 7 8 9 |
@pikzie.data("small", 2) # 実行される。パスする。 def test_true(number): assert_true(is_prime(number)) @pikzie.data("zero", 0) # 実行される。パスする。 @pikzie.data("unit", 1) # 実行される。失敗する。 @pikzie.data("square", 4) # 実行される。パスする。 def test_false(number): assert_false(is_prime(number)) |
データ駆動テスト機能を使うと、テストの内容には「どのようにテストしたいか」という本質的な部分だけが残ります。また、テストパターンを追加するときは、パラメータ化したテストデータの方に注目することができます。これにより、メンテナンスのしやすいテストを書くことができます。
Pikzie 0.9.5から0.9.7の間で追加された大きな機能であるデータ駆動テスト機能について紹介しました。
いろいろなパターンがあるテストでデータ駆動テスト機能を使ってみてはいかがでしょうか。
今年も夏に日本Ruby会議が開催されますが、昨年に引き続き今年もスポンサーになりました。
日本Ruby会議2010のトップページで微妙に公開されていますが、るりまサーチについて発表する予定です。
いくつかの企画にも参加します。今のところ、るびまでActiveLdapの記事などを書いている高瀬さんのLDAPに関する企画とRuby 1.9コミッタQ&Aに参加する予定です*1。
日本Ruby会議2010でのクリアコード関連情報のお知らせでした。
Ruby関連といえば、最近、クリアコードもAsakusa.rbデビューしました。
*1 どちらかというと企画側で。