S2JUnit4ユニットテストをやってみた

id:idesakuさんの記事を見てS2JDBCでもS2JUnit4を使えることが分かったのでやってみた。
S2JDBC + S2JUnit4でハマる - idesaku blog
そもそもS2JUnit4も使ったことが無かったので一から調べた。
以下のサイトが分かりやすい。

以下は本家のS2JUnit4のマニュアル

自分はDBテストのやり方とかはRailsで学んだ口なので、まずテストデータベースを用意してそれにどうやってデータを入れるかなとか考えていたんだけど、S2JUnit4ではテスト用のデータベースは必要なく、テストが実行される度にロールバックされる(デフォルトでは)仕組みになっている。そのためテストしたからってデータがどうかなるって心配はない。ということで、ローカルには一つのDBだけあればいい。ただ、シーケンスだけはどうしても汚れてしまうので、これを考慮してテストを作らないといけない。

そして、テスト用のデータはExcelからロードして投入することが出来る。(もちろんDBに入っているデータをそのまま使うことも出来る)データは、テストクラス+テストメソッド名.xlsという名前でテストクラスと同じパッケージに入れておけばテストメソッドが実行される直前にロードされる。
このExcelは1シートが一つのテーブルと関連付いているので、一つのExcelブックに複数のテーブルのデータを入れることが出来る。
Excelが無くてもOpenOfficeExcel形式で保存したファイルでも大丈夫みたい。

そして、テストメソッド内で、更新とかの処理をテストすると思うのだけど、その更新処理結果の期待値っていうのも事前にExcelデータを用意しておき検証できる。
この期待値は「テストクラス+テストメソッド名_Expected.xls」というファイル名で保存しておけば簡単に取得できる。以下のようにテストメソッド内で記述していれば、対応するExcelのデータがDataSetオブジェクトに読み込まれる。

DataSet expected = ctx.getExpected();

このDataSetオブジェクトと検索して取得したList等を比較すればよい。(ちなみにこのassertEqualsはS2Assertで定義されたもの)

assertEquals(expected, list);

ここで、さっき言ったシーケンスの問題がでてくる。シーケンスはどうしてもテストのたびに変わっていいってしまうので期待値として予め考慮することが出来ない。そこで、この期待値にシーケンスで取得した値が入る列(IDとかの列)を削除しておく、そうすることでこの列は無視して検証が行われるので、毎回データが変わっても問題にはならない。同様に作成日とか更新日とかも期待値のデータからは抜いておくのがいいと思う。

このほかにassertEqualsIgnoreTableOrderというアサーションがあるんだけど、これは並び順を気にせずにデータを比較するものになっている。便利だなーと思ったら引数に2つのDataSetしか入れられない。つまりassertEqualsIgnoreTableOrder(DataSet expected, List result)みたいな事が出来ない。この結果(List result)をDataSetにするにはどうするかなと思ってたんだけど、どうやら、以下のメソッドが使えそう。

DataSet expected = ctx.getExpected();
DataSet result = accessor.readDb(expected);

これはDataSetから判断したテーブル内のデータをロードしてくる。だけど、そのテーブルの全データなんだよね。だから、これを使ってassertEqualsIgnoreTableOrderするには、getExpectedで取得される期待値もテーブルの全データ分用意しておかなければならない。ちょっと大変かも?(テスト用のデータだから、あんまり大量のデータは入らないのかも知れないけど。いや、そもそも、並び順も考慮しておくべきなのか。)

あとは、この繰り返しでテストを書いていけばよい。
データにアクセスする方法とかいろいろ在るみたいなので、これから徐々に覚えていこう。

そうそう、意外とこのExcelデータを作るのが面倒なんだけど、A5:SQL Mk2というソフトを使うとExcel形式でデータを保存できるので便利かも。ただしODBCで接続するので対応しているDBしかダメだけど。PostgreSQLは大丈夫でした。

A5:SQL Mk-2 - フリーの汎用SQL開発ツール/ER図ツール
なんか、前使ってたときより進化してる。これすげぇ。