Hatena::ブログ(Diary)

Fly me to the Juno! このページをアンテナに追加 RSSフィード

2011-06-12

assertion養成ギプスを作ってみた

ちょっと前、id:t-wadaさんらがtogetterで「デフォルトでテスト成功にするという JUnit の設計判断とその功罪について」っていうテーマでいろいろつぶやかれてましたね。

http://togetter.com/li/138798

あったら便利かもしれないので、assertion養成ギプスをjavaagentとして作ってみました。

http://kompiro.org/maven/junit/extensions/quick/training.assert/0.0.1/training.assert-0.0.1.jar

Eclipseだと、プロジェクトの直下に上記のJARを配置し、VM Argumentsに下記のように「-javaagent:training.assert-0.0.1.jar」と加え、

f:id:kompiro:20110612231249p:image:medium

javassit 3.12.1に依存しているため、それもダウンロードしてクラスパスに含めて実行してください。

javaagentは初めて作った上、maven3で1個のJARに固めるやり方がよく分からなかったので、どなたか教えてくだし。

id:cuctusman さんにfatjarを使うやり方を教わったYo!javassistも同梱してます。

ソースコードhttps://github.com/kompiro/training.assert に公開してます。

2011-02-28

Test Doubleを使うとテストの信頼性/保守性が下がるのか?

最近はユニットテストを行うテストコードにおいて、Test Doubleを多用してます。Test DoubleとはMockとStubを合わせた総称です。Test Doubleを用いると、信頼性や保守性が下がると言われることがあります。しかし、それはTest Doubleの用法を誤っているためではないかと僕は思うのです。Test Doubleの用途はユニットテストのスコープをテスト対象のクラスに限定するために用いるべきものです。実感として、Test Doubleを使っているからと言って、ユニットテストの信頼性/保守性が下がったとはあまり感じていません。

良く誤解されていますが、Test Doubleはスローテスト問題を解決するための手段ではありません。Test Doubleをうまく利用すれば、結果的にスローテスト問題を解決できます。しかし、スローテスト問題を解決するための手段ではないのです。スローテスト問題の手段としてTest Doubleを用いてしまうと、DBのセットアップが不要などの理由により、安易にファンクショナルテストやシステムテストなど、複数のクラスを串刺ししたテストにも用いようと考えます。そうしたより高いテスティングのレイヤにおいてTest Doubleを用いてしまうと、インタフェースの不整合がおき、想定していたデータと違うデータがTest Doubleから与えられてしまい、信頼性や保守性が下がってしまうのではないでしょうか。

ユニットテストにおいて、検証すべき事柄は、そのクラスに実装されているロジックが意図した通りに動作しているか、と言う事です。なので、相手にするスコープに限定してあれば十分です。UIのテストをしているのに、DBやファイルのセットアップが必要だとすれば、そのテストはユニットテストとしてのスコープを越えてしまっています。UIのユニットテストでは描画や操作に必要なオブジェクトのモックで十分テストができます。

クラスとクラスを串刺しにしたテストは、ユニットテストよりも上のレイヤーのテストで確認します。すなわちファンクショナルテストなり、全てのテストをまたいだ統合テストで確認します。それぞれのレイヤではユニットテストで行うほど、細かな観点でテストすべきではありません。いくつかのクラスを結合したテストですから、それぞれのオブジェクトのインタラクションを確認し、エンドツーエンドでの動作を確認することが目的です。

ところで、読みやすく、分かりやすいコードを書くには、実装時にクラスとAPIが担う責務を明確にし、それぞれを小さく保つことはもはや定石の一つと言ってよいでしょう。単一責務の原則も、1メソッド辺りの行数の指標も、変数のスコープを制限し、カプセル化しておくことも実は同じことを言っています。一度に考えなければならないことを減らすように実装をする事を指しているのです。

ユニットテストにおいても同じです。確認すべき事項を細かくあげ、一度に多くの事柄を相手にしない、というのは、一つ一つの確認において、複雑に考えなくてもよいようにするためなのです。

そう捉えてみると、Test Doubleの使いどころが見えてきます。テスト対象以外のクラスからの振る舞いに影響をできる限り受けないように実装するのです。そのためのMockであったり、Stubです。だから、ユニットテストでDBを直接操作するクラスのテストを書いている訳でもないのに、DBのセットアップを行うのは、ユニットテストの役割を考えると過剰な作業です。普段は起きないような例外が起きたとき、それがきちんと扱えているかチェックするテストコードをリグレッションテスト出来る方が重要です。

と言う事で、自分のTest Doubleに対する考えをまとめてみました。

2011-01-11

次第に腐るテストコード

結論を最初に書くと、

テストコードを書くだけではダメで、デイリービルドなりCIしないと意味ないんじゃないっすか?という事です。

最近Hudsonを使っていてすごいいいなぁ、と思うのがこの画面。

f:id:kompiro:20110111214152p:image

「リグレッション」という表現はすごい的を射ているなぁ、と思います。以前は「失敗」となっていたと記憶しています。

なんで的を射ているかと思ったかと言うと、テストコードって回帰テストの中で動かされると、その結果は「成功」と「失敗」だけではありませんよね。仕様変更による影響がテストコードので、テストコードが失敗すると言う事もある訳で。確かid:hyoshiokさんのブログだったかで拝見したかなんかだったんですが、Oracleでは毎朝デベロッパが出社すると、QA担当の人から失敗した回帰テストが回覧し、デベロッパに「これは障害なのか、仕様変更による影響なのか」を判断してもらった、と言う話を目にしました。テストコードは毎朝結果を確認しないといけないくらいセンシティブな生き物なのでしょう。

なので、テストコードを書いているから、「テスト自動化してます」なんて言ってたら微妙なのではないかと。そう。気づいた時にはリグレッションで動かないテストコードだらけ。あなたの周りに腐ったテストコードないですか?

と言う事で2011年初エントリ。みなさま、今年もよろしくお願い致します。

2010-05-27

JUnitの実行結果をGrowlに通知するEclipse Plugin(2)

id:yamkazu氏とid:nobeans氏からの要望に答え、OKとFailureとErrorでNotificationを切り替えるようにしました。

http://kompiro.org/download/junit.extensions.eclipse.quick.mac.growl_0.2.0.201005272351.jar

にあげました。取り急ぎ。

2010-05-26

JUnitの実行結果をGrowlに通知するEclipse Plugin

作りました。

f:id:kompiro:20100526224514p:image

Quick JUnitシリーズになるかどうかは相談したいところなのですが、パッケージ等はそうなったらいいなと思ってそうつけました。

http://kompiro.org/download/junit.extensions.eclipse.quick.mac.growl_0.1.0.201005252224.jar

に置いておいたので、興味があればダウンロードして頂いて、dropinsフォルダにでも置いてみてください。

重要:動作が確認された環境

  • Mac OSX 10.6 (64bitカーネルでもおk)
  • JRE 1.6(こちらも64bit有効でもおk)
  • Eclipse 3.5.2 cocoa 32bit版

5/26 23:45追記

このバージョンはMac OSX 10.6でビルドしているネイティブライブラリが入っています。それ以外の環境では動きません。ごめんなしあ><

5/27 0:14追記

導入したらEclipseが立ち上がらない、と言う話もあったので、いったん公開を停止します。

5/27 1:06追記

32bit版のEclipseであれば動作します!

5/27 1:11追記

Eclipseが64bit版では動作しない事を確認しました。id:yamkazu氏とid:nobeans氏ありがとうございました!