goo blog サービス終了のお知らせ 

N2 ToolBox(跡地)

跡地です。引っ越しました。http://d.hatena.ne.jp/nosen

mavenでAspectJを使う

2004-06-29 00:54:27 | 開発手法/方法論
そもそもAspectJでDesign by ContractをやるためにMaven AspectJ Pluginを使おうとしたのですが、これがなかなか動いてくれなくて。。。結局はしょうもないことではまっていたのですが。というわけで、MavenでAspectJを使うためのメモです。
なお、Mavenのバージョンは1.0rc3を前提とします。

1. Maven AspectJ Pluginをバージョンアップする。
以下のコマンドを実行します。
maven plugin:download -DgroupId=maven -DartifactId=maven-aspectj-plugin -Dversion=3.1

なにしろドキュメントも全部バージョン3.1ベースですし、これをやらないと始まりません。

2. project.xmlの編集
dependencyにaspectjrt-1.2.jarを追加し、build要素の子要素としてaspectSourceDirectoryを追加します。
こんな感じになります。

3.maven.xmlの作成。
今回はテストケースに対してWeavingを行いたかったのですが、そのような場合はtest:compileのpreGoalとしてaspectj:test-compileを設定します。
本体のソースコードにWeavingをかけたい時はjava:compileのpreGoalとしてaspectj:compileを設定します。こんな感じになります。

これで、あとはチェック対象クラスのメソッド呼び出しの前後に事前条件/事後条件/不変表明のチェックを行うアスペクトを書いて、

maven test

を実行すると、JUnitのテストケースにWeavingされてうまいことチェックがかかります。本体でなくテストケースにWeavingするところがミソです。この方がテスト対象をいじくり倒すよりも安心ですし、特別なことをしなくてもmavenのjar goalで作成されるjarには当然チェック抜きのコードがはいりますから。
ただ、複雑な場合でもテスト対象をいじらないで済むかどうかは非常に疑問です。。。

明日は、実際にDbCをAspectJで実現したサンプルコードを紹介したいと思います。

EasyMock vs jMock

2004-05-30 00:01:33 | 開発手法/方法論
昨日もちょっと書きましたが、どちらも動的にMockObjectを生成するタイプのツールであるEasyMockjMockを両方ちょっとだけ試してみました。
機能的には大差なくて、どちらも以下のような事ができます。
  • 動的プロキシの機構を使ったインターフェースのMockObject生成
  • cglibを使った拡張ライブラリによるクラスのMockObject生成
  • 予期されるメソッド呼び出しの設定と検証
  • 予期されるメソッド呼び出しに対する戻り値または例外の設定
予期されるメソッド呼び出しは複数回分を設定できますし、順番を指定することもできます。
違うのは、予期されるメソッド呼び出しの設定方法です。
EasyMockだと以下のようになります。

MockControl ctrl = MockControl.createControl(Foo.class);
//MockObjectの生成
Foo mockFoo = (Foo) ctrl.getMock();
Bar foo = new Bar(mockFoo);

String arg = "arg";
//予期されるメソッド呼び出しの設定
mockFoo.bar(arg);
ctrl.setReturnValue(1);
//テスト開始
ctrl.replay();
int rv = foo.doBar(arg);

jMockだと以下のようになります。
Mock mock = new Mock(Foo.class);
//MockObjectの生成
Foo mockFoo = (Foo) mock.proxy();
Bar foo = new Bar(mockFoo);

String arg = "arg";
//予期されるメソッド呼び出しの設定
mock.expects(once()).method("bar").with(same(arg))
.will(returnValue(1));
//テスト実行
int rv = foo.doBar(arg);

さあ、どちらがわかりやすいでしょうか?
EasyMockはMockObjectに対して予期されるメソッド呼び出しを"記録”するというアプローチです。jMockのやり方は細かいメソッドに分けて予期される動作を設定しており、一見分かりづらいのですが、JavaDocをよ~くながめると、「ふーんなるほど」と納得できます。これはこれでなかなか筋のとおったやり方です。
どっちがいいのか?と言われると難しいのですが、僕はjMockの方が好きですね。EasyMockはぱっと見はわかりやすいのですが、ちょっとややこしいことをやろうとするとすぐごちゃっとしたコードになってしまいそうな気がします。一方jMockは一見分かりづらいのですが、一度理解してしまうと、柔軟性も高いし、複雑な振る舞いもさくっと設定できそうです。そんなに使い込んでないんで、わからないですが。
ただ、ぱっと見のわかりやすさも実際の開発では結構大事なんですよねぇ。以前4人のXPプロジェクトを回したときに、ソースコードを生成するタイプのMockObjectツールを使ったのですが、僕も含めて全員が生成されたMockObjectの使い方が分からなくてハマったという苦い経験があります。
MockObjectというもの自体、うまく使えばテストの効率がすごく向上するけど、使いどころを間違えると大変なことになるものだという気がしています。基本的にはあんまり複雑なインターフェースには適用しない方がよさそうです。HttpServletRequestのMockObjectを作るよりは、素直にコンテナの中でテストしたほうが良いと思います。

EasyMock

2004-05-29 01:37:05 | 開発手法/方法論
なんのかんのいっても僕はMockObjectを使ってテストをすることが多いのですが、MockObjectのソースコードを生成するタイプのツールはちょっと面倒だな、と感じていました。
そんな中、最近見つけたのが、EasyMock。これはソースコードを生成するのでなく、JDK1.3から使える動的プロキシの仕組みを使って実行時にMockObjectを生成するタイプのツールらしいです。
さらに特徴的なのは、予想される引数や、戻り値、例外の設定方法。
従来型のMockObjectだと、addExpectedなんちゃらなどという難しい名前のメソッドを経由して予想される値を設定してあげないといけなかったのですが、EasyMockは違います。
あらかじめMockObjectに対して予想されるメソッド呼び出しを"記録"し、実際にテストを実行するときに以前記録した操作と、実際の操作の差異をMockObject側で比較し、異なる場合はAssertionFailedErrorを投げる、という仕組みらしい。
これは確かにシンプルで分かりやすいやり方のような気がします。

同様に動的にMockObjectを生成するアプローチのツールとして、jMockというものもあるらしいです。こっちも気になります。
テストを効率良く実施できるかどうかは、ソフトウェア開発にとって死活問題ですから、是非検証してみたいですね。