MiniTest::Assertionsはモジュールであることについて考えてみた

初めてのRuby』によると、モジュールは拡張機能(または名前空間など)に使われる習慣があるようです。例としてNumericクラスがRailsではモジュール(ActiveSupport::CoreExtensions::Numeric::Bytes)で拡張されているのが紹介されています。

MiniTest::TestCaseとMiniTest::Assertionsとの関係は、NumericとActiveSupport::CoreExtensions::Numeric::Bytesの関係と同じでしょうか。全く同じではないことはすぐに分かります。Numericの実装者はそのモジュールのことは知らないけれども、TestCaseの実装者は(おそらく)Assertionsのことを知っています。

モジュールが色々なクラスにincludeされるような、抽象クラス的な使われ方も考えられます。でも、これもAssertionsの場合に当てはまりません。じゃあやっぱりTestCaseの拡張機能でしょうか。

多分、それで正しいと思います。なぜならば、TestCaseのサブクラスに実装されるテストメソッドの中で使われるassert_xxx関数が無くてもテストメソッドは書けます。ここで「テストメソッドが書ける」というのは、テストの成功、失敗、エラーの全てが扱えるということです。ちょっと考えてみると、まず成功はあたり前として、エラーも考えてみれば、もともと大抵はassert系の関数の外で発生します。失敗はどうでしょうか。失敗は例外MiniTest::Assertionをraiseすれば良いので問題ありません。

テストメソッドが通常の意味で書けるのですから、テストケースもMiniTest::Assertionsモジュールをincludeしなくてもテストランナー(MiniTest::Unit)はそれをテストケースとして扱えるわけです。また、Assertionsモジュールにメソッドを足せば新しいassert系関数を足すこともできるわけです。

ruby-unit-test20120326.epubの続きをどう書こうかなぁと思って、こんなことを考えてました。まぁでも、assert_xxxは意味的にAssertionsとして個別に定義してincludeする方が可読性は上がりますよね。