JUnit4のassertThat()って便利なの?

JUnit4ではhamcrestライブラリーが統合されており、伝統的なassertEquals()を使った比較以外に汎用的なassertThat()が使えます。これを使うとより英語的に自然に読めるアサーションを記述できるとされています。しかし、Classクラス同士の比較ができないといった問題もありますし、そもそも日本人にとって便利なのかという疑問もわきます。
10
Ryo Asai @ryoasai74

初歩的な疑問だけど、JUnitのassertThat()の形式でClassクラス同士を比較することはできないのかな?この場合はassertEquals()を使う必要があるのだろうか?

2011-04-29 00:32:15
🍻 @kompiro

@ryoasai74 assertThat(actual.class, is(expected.class)では不十分ですか?

2011-04-29 00:39:02
Ryo Asai @ryoasai74

@kompiro is()メソッドでタイプトークンをとるメソッドがオーバーロードされていて、この比較だと、第一パラメーターが第二パラメーターで指定したクラスのインスタンスであることが判定されてしまうのですよね。 http://bit.ly/mhMie7

2011-04-29 00:43:11
Ryo Asai @ryoasai74

英語ネイティブ的にはis(String.class)はis(instanceOf(String.class))と同じ意味だと解釈したいのでしょうが、これだとクラス自身が比較できないな。static importも面倒だし、個人的にはあまり便利とは思えないなassertThat()

2011-04-29 00:48:53
🍻 @kompiro

@ryoasai74 ほんとですね。英語ネイティブ的というより、オブジェクト指向的な表現と僕は思いました。クラス自身を比較するのであれば、Class.getCanonicalName()とか、何らかの回避ができないですかねー。そこまで無理して使わなくてもいいともおもいますけど。

2011-04-29 00:57:37
🍻 @kompiro

(クラス同士を厳密に比較するのってアンチパタンな気がしてきた)

2011-04-29 01:00:18
Ryo Asai @ryoasai74

@kompiro そうなりますかね。何事もgolden hammerであってはいけませんし、いずれにしても、assertEquals()との使い分けは必要なのかもしれませんが、型安全性とエラーメッセージの可読性はhamcrestの利点かもしれません。

2011-04-29 01:02:00
Tadayoshi Sato / 佐藤 匡剛 @tadayosi

@ryoasai74 今までJUnit4でテストコードをかなり書いてきましたが、正直クラスの比較をしたいと思ったことは一度もなかったです。static importはEclipseの設定次第で便利になりますよ。

2011-04-29 01:02:16
Ryo Asai @ryoasai74

@tadayosi @kompiro 業務ロジックのレイヤではそうかもしれませんが、例えば、以下のようなテストはどうしますか? https://gist.github.com/946477

2011-04-29 01:03:54
Ryo Asai @ryoasai74

assertThat()はDSLの一種で上位レイヤ向けなので、リフレクションを扱うのような低水準のインフラレイヤではassertEquals()を使う比重が大きくなるということかなと理解しましたが。

2011-04-29 01:11:47
Tadayoshi Sato / 佐藤 匡剛 @tadayosi

@ryoasai74 @kompiro なるほど。インフラ層のテストコードは確かにクラスを比較するケースもありますね。 assertThat(Xxx.class == aClass, is(true)) とか?

2011-04-29 01:14:50
koichik @koichik

@tadayosi いつも public static Matcher<Object> sameClass(Class<?> clazz) って作ってる... http://ow.ly/4J1XG みたいなやつのテストでは必要.

2011-04-29 01:15:27
🍻 @kompiro

@ryoasai74 @tadayosi TypeDescriptorのラーニングテストですかね。TypeDescriptorが果たすインタフェースの確認ができればいいので、isで十分いいかなと。もし内部でProxy作って返してきてたら、厳密に比較したらfailしませんか?

2011-04-29 01:15:44
Ryo Asai @ryoasai74

@tadayosi なるほど、そのイディオムは使えるか。あとは、慣れの問題か。Groovyで括弧が省略できればもっと自然かもしれません。

2011-04-29 01:17:28
🍻 @kompiro

(なんか、眠くて間違った事言っている気がしてきた。Proxy関係ない)

2011-04-29 01:17:48
Tadayoshi Sato / 佐藤 匡剛 @tadayosi

@ryoasai74 @kompiro @koichik ググったら typeCompatibleWith っていうMatcherありますね。これはどうでしょう? Matcher定義するのは簡単なので、最悪自分で作っちゃうのもありですね。

2011-04-29 01:19:52
Ryo Asai @ryoasai74

@kompiro @tadayosi is()では以下のエラーなり、意図した比較になりません。 Expected: is an instance of java.lang.String got: <class java.lang.String>

2011-04-29 01:23:08
🍻 @kompiro

@tadayosi @ryoasai74 @koichik あと、hamcrest-library っていうMatcherの拡張みたいなのにisA(Class)っていうMatcherもありました。 http://bit.ly/kHSAQm

2011-04-29 01:25:48
🍻 @kompiro

(あれ?JUnitのassertThatはhamcrest由来じゃなかった?)

2011-04-29 01:26:43
Ryo Asai @ryoasai74

@tadayosi @kompiro typeCompatibleWithだと意味が変わってしまうため、だめですね。代入互換性でなく、正確なクラスの比較ができなくてはなりません。

2011-04-29 01:28:25
Ryo Asai @ryoasai74

@kompiro @koichik @tadayosi isA()はクラスとそのインスタンスの比較だから、is()と意味的に同じなのではないかな。英語的な読みやすさの違いだけなのでは。僕はFW開発をする関係上クラスの比較って結構必要なイメージなのですが、標準でないのは意外ですね。

2011-04-29 01:32:30
🍻 @kompiro

@ryoasai74 @koichik @tadayosi isA()はソースコードみたら、is()を中で読んでいました。@koichik さんの紹介された、SeasarのMatcherがいいですね。ありがとうございます。

2011-04-29 01:40:43
Ryo Asai @ryoasai74

@kompiro @koichik @tadayosi 皆さん、どうもありがとうございました。今後使えるところでは、なるべくassertThat()を使ってみようと思います。

2011-04-29 01:42:38
Tadayoshi Sato / 佐藤 匡剛 @tadayosi

@ryoasai74 assertThat 私も好きで使っていますが、JavaだったらJDaveとか使ってBDDやってみるのもいいかもしれませんね。ScalaだったらSpecsがありますが。

2011-04-29 22:00:25
Ryo Asai @ryoasai74

@tadayosi BDDは今のところ未開拓ですね。assertThat()もそうですが、非常に残念なことながら普通のSI案件では使いこなすのを想像できないところがありますね。小規模のアジャイルな案件でTDDでやるなら是非採用したいところです。

2011-04-29 22:04:50