*

JUnit入門その6[Eclipse4.4のJUnitプラグインとDBUnitの併用(便利に利用するためのユーティリティの作成)]

公開日: : 最終更新日:2015/05/03 DBUnit, Eclipse, Java, JUnit


スポンサードリンク



JUnit入門その4[Eclipse4.4のJUnitプラグインとDBUnitの併用(環境構築と基本)]
でDBUnitの環境構築を説明させていただきました。

今回は、前提値データをデータベースに登録する部分の処理を、各テストケースのクラスで簡単に利用できるようにするためのユーティリティクラスの作成を行いたいと思います。

本エントリーの内容は以下の通りです。

  1. 前回のエントリーのコードの問題点の検証
  2. 前回エントリーの問題点を解決するユーティリティクラスの作成
  3. 作成したユーティリティクラスの利用例

 

1 前回のエントリーのコードの問題点の検証

前回エントリーのサンプルコードは以下の通りでした。import文は省略しています。

JUnitテストケースでもない上記のソースなのですが、多くのテストケースを実装していくとの前提とした時の問題点を以降で記載させていただきます。

JUnitのライブラリがプロジェクトから参照されていない

JUnitのライブラリをプロジェクトから参照します。

プロジェクトを選択し、マウスの右クリックを表示し、「プロパティー」をクリックします。
スクリーンショット 2015-03-31 17.45.51

次に「Javaのビルドパス」を選択後に、「ライブラリー」の「ライブラリーの追加」をクリックします。

以下の画面が表示されますので、「JUnit」を選択し「次へ」ボタンをクリックします。
スクリーンショット 2015-03-31 17.46.37

次に表示される画面では、JUnitのバージョンを選択します。デフォルトで4系となっていますので、何も変更せずに「完了」ボタンをクリックします。
スクリーンショット 2015-03-31 17.46.08

これでビルド・パスにJUnitが追加されましたので、「OK」ボタンをクリックして変更を確定します。
スクリーンショット 2015-02-13 17.35.18

これでJUnitのライブラリをプロジェクトから参照できるようになりました。
スクリーンショット 2015-03-31 17.46.58

JDBCのドライバー名とDBの接続情報が直書きとなっている

実際の開発で、本番環境(サービスリリース前の場合はデモ環境など)でユニットテストを実行することはあり得ないです。
実行しちゃうと大変な事になります。

各開発者用の個別のDBや、共通DBの個別のスキーマ等を利用することが一般的だと言えます。

本番環境は「Oracle」や「Postgresql」で、ユニットテストを実行する環境は「HyperSQL」(旧HSQLDB)や「Java DB」である場合も結構多いと思います。

このように、テスト実行時に接続先DBとスキーマを切り替える仕組みは必須です。
これについてはJavaのpropertiesファイルを利用します。

まあ、本番環境の接続先DBとスキーマを切り替える仕組みもpropertiesファイルを利用することが一般的ですので、敢えて説明するほどの事でもないですが・・・

前提値データがmainの引数で指定されているのでJUnitでは利用できない

これについては、JUnitの@Beforアノテーションを付与したメソッド内でテストデータを指定するとの方法が良く利用されます。

しかし、前提値データのファイル名さえテストクラスに知らせてあげれば、各テストクラスで前提値データをDBにセットアップする処理を記述する必要は無くなります。

結局、その処理は前提値データのファイル名が異なるだけですから・・・

DBコネクションが複数テストケースで利用可能でない

main関数の中でDBコネクションを作成しているので、全てのテストケースで利用できるようにする必要があります。
全てのテストケースでコネクションを作成するのは非効率ですよね。

2 前回エントリーの問題点を解決するユーティリティクラスの作成

前回サンプルコードをJUnitのテストクラスに変更

mainメソッドを無くす

ユーティリティクラスの作成に先立って、前回のサンプルソースをJUnitのテストクラスに変更します。
変更後のソースは以下のようになりました。

mainメソッドをなくして、その内部で行っていた処理をDBUnitを利用したJUnitのテストクラスの処理にそれぞれ委譲しています。
ポイントとしては、以下の4つが上げられると言えます。

  • 基底クラスをDatabaseTestCaseに変更
  • DatabaseTestCaseで抽象メソッドとして定義されているgetConnectionをオーバーライド
  • DatabaseTestCaseで抽象メソッドとして定義されているgetDataSetをオーバーライド
  • 処理が全く内テストメソッドtestSampleを作成

各ポイントにつきましてはソースに記載しているコメントをご覧いただければご理解いただけると思います。
肝はtestSample()メソッドを実行する前に実行されるDatabaseTestCaseのsetUpメソッド内で
getConnectionとgetDataSetが呼び出され、それぞれの戻り値を引数としてDatabaseOperation.CLEAN_INSERT.executeが実行されるので、テストケースが実行される前に前提値データがDBにセットアップされる。との流れとなります。

DatabaseTestCaseのJavaDocはDBUnitの公式ページをご覧ください。
http://dbunit.sourceforge.net/apidocs/org/dbunit/DatabaseTestCase.html

テストデータがソースコード内にリテラルで指定されるようになってしまいましたが・・・
これについても後ほど解消します。

JDBCの各種情報を外部ファイルに記載

次にJDBCドライバーの情報や、JDBCのコネクションの接続先情報をJavaのpropertiesファイルに記載し、その値を参照してテストが実行されるように変更します。

変更部分は
getJdbcConnectionメソッドと
java.util.ResourceBundleをインポートするだけですので、変更後のgetJdbcConnectionメソッドだけを記載させていただきます。

この変更も特に説明は不要と思います。ソースに直書きしていた各種設定をdb.propertiesファイルから読み込むようにしただけです。

db.propertiesはsrc直下に作成します。
db.propertiesの内容は以下の通りです。

ユーティリティクラスの作成

テストデータの非リテラル化

まずは、テストデータがリテラル文字列になっている問題を解決します。

解決する方法としては、独自アノテーションを作成し、アノテーションで前提値データ(.xlsのパス)を指定できるようにします。
アノテーションが付与できる場所はクラスとメソッドとします。テストクラスで単一の前提値データを利用することもあるし、テストメソッド毎に前提値データを指定することもあります。

しかし、テストメソッド毎に前提値データを作成するのは、変更に強いとは言いがたいです。
何事にも絶対はありませんが、できるだけ「変更に強い」との言葉を意識しておくことは重要であると思います。

作成したアノテーションは以下の通りです。

作成したアノテーションを利用して、前提値データを指定するようにDBUnitSetupを変更します。
クラスレベルでTestDataアノテーションを付与し、そのアノテーションからbaseDataを取得し、この値を前提値データのxlsファイルとして利用します。

変更後のコードは以下の通りです。

アノテーションの追加以外は、getDataSetを変更しただけです。

これで前提値データをリテラルで記載しなくてOKとなりました。
(アノテーションで記載しているのでリテラルと言えばリテラルなので、微妙ですが・・・)

DatabaseTestCaseを継承したクラスの作成

上述の変更によって、複数テストケースでほとんどの処理が共通に利用できる下地ができましたので、DatabaseTestCaseを継承したクラスを作成し、DBUnitSetupの基底クラスをそのクラスに変更します。

クラス名は、安易ですが、DatabaseTestCaseExとしました。
DatabaseTestCaseExは以下のようになりました。

DBUnitSetupは以下のようになりました。

完全に処理がDatabaseTestCaseExに委譲されていますね、これで複数のテストクラスを作成しても@TestDataのアノテーションのbaseDataを書き換えるだけで前提値データがDBにクリーンインサートされるようになりました。

3 作成したユーティリティクラスの利用例

ユーティリティクラスは作成できましたが、ユニットテストの中身が空っぽですので、USERTBLの検索用Daoの作成と、対応するテストケースをユーティリティクラスを利用して実装してみたいと思います。

テストケースの実装

テストファーストで行ってみたいと思います。
UserDAOクラスを作成し、そのクラスのfindByNameメソッドのテストを実装します。
前提値データに含まれるnameを指定した時のテストメソッドと前提値データに含まれないnameを指定した時のテストメソッドの2つを作成します。

テストメソッドは1つにしても良いのですが、2つに分割した方がテストメソッドがテストしたい内容が明確になるため、このようにします。まあこの辺は好みが分かれる所ではあると思います。

前提値データに含まれるnameを指定した時のテストメソッド

前提値データに含まれるnameを指定して検索した時のテストメソッドは以下のようになりました。
とは言え、UserDAOも作成してないのでこの時点ではコンパイルエラーだらけです。

前提値データは以下のようになっています。
スクリーンショット 2015-03-31 19.26.06

ファイルが存在する場所は、プロジェクトの直下のディレクトリとなります。
スクリーンショット 2015-03-31 19.27.11

ここからEclipseのエラー訂正機能を活用してUserDAOを実装していきます。
エディタ部分no13行目のエラーのアイコンにマウスのフォーカスを当てます。
スクリーンショット 2015-03-31 19.34.13

すると、以下のようなTipが表示されます。予想通りの内容ですね。
スクリーンショット 2015-03-31 19.40.35

フォーカスを当てたままマウスの右クリックを行います。
すると以下の画面が表示されますので、「クラス’UserDAO’を作成します」をクリックします。
スクリーンショット 2015-03-31 19.43.43

後は「完了」ボタンをクリックするだけです。
(デフォルトパッケージですが・・・)
スクリーンショット 2015-03-31 19.46.45

UserDAOのコンストラクタの部分のエラーは解消されました。
スクリーンショット 2015-03-31 19.48.42

同様にUserDtoも生成します。今度はUserDtoの下に表示されている赤線にフォーカスを当てて以下の画面を表示させてから生成します。
スクリーンショット 2015-03-31 19.51.09

これでUserDtoの箱自体はOKとなりました。
スクリーンショット 2015-03-31 19.55.15

次にUserDAOのfindByNameを作成します。
findByNameにフォーカスを当て、メソッドを生成することも可能ですが、スクリーンショットが取れないので、14行目のエラーアイコンをクリックした時に表示される画面から生成します。
スクリーンショット 2015-03-31 20.00.28

上記画面の「型’UserDAO’のメソッド’findByName’を作成します。」をクリックします。
(画面切れてますが・・・)

UserDAOは以下のようになりました。UserDAO.javaをセーブすれば14行目のエラーも解消されました。

いよいよ、15行目のコンパイルエラーが取れればテストが実行可能となります。
どうせprivateなインスタンスメンバーとゲッター、セッターを作成するのでUserDtoは普通に実装しました。

nameとaddrをprivateなStringのメンバとして定義した後に、右クリックメニューの
「ソース」>「getterおよびsetterの生成…」をクリックします。
スクリーンショット 2015-03-31 21.00.45

nameとaddrのgetterとsetterを生成するようにチェックを入れて「OK」ボタンをクリックします。
スクリーンショット 2015-03-31 21.10.18

最終的にはUserDto.javaは以下のようになりました。

これでテストが実行できるようになりましたので、実行してみます。

実行結果は以下のようになりました。
スクリーンショット 2015-03-31 21.27.11

失敗するのは予想通りなのですが、発生する例外が想定外です。

うーん、もしやテストメソッドがtestから始まってないからか?、と思い”testFindResulUserDto_ヒットする時”に変更してみると想定通りの結果になりました。

@Testアノテーションっていったい・・・、前からこんな仕様だったっけ?

気を取り直して、”testFindResulUserDto_ヒットする時”のテストが通るようにUserDaoを実装してみました。

なんて実装なんだ!?、と思われる方ばかりだと思いますが、シンプルにテストを成功させるにはこのコードが最適です。

テストを再度実行すると成功しました。
スクリーンショット 2015-03-31 21.36.36

前提値データに含まれないnameを指定した時のテストメソッド

まじめにUserDAOを実装するのに先立って、JDBCコネクションを生成するユーティリティクラスを作成します。

処理自体はDatabaseTestCaseExに存在している実装でOKですが、UserDAOでも同じようにJDBCコネクションを生成したいためです。

JDBCConnectionUtil.javaを作成し、内容を以下のようにしました。

DatabaseTestCaseExのgetConnectionメソッドも以下のように変更しました。

前提値データに含まれないnameを指定した時のテストメソッドは以下のようになりました。

前提値データに存在しないnameが指定された時はnullが返却されるとの検証を行っています。
当然ですが、実行すると失敗します。

いよいよ、UserDAOのfindByNameをまじめに実装します。
内容は以下のようになりました。

JDBCでDBを検索する処理を久々に書きましたが、これで2つのテストメソッドとも成功するはずです。

テストの実行結果は何故は失敗しました。
スクリーンショット 2015-04-01 17.45.32

結果比較画面を見ると、何故!?との情報が表示されています。
スクリーンショット 2015-04-01 17.51.49

なんでやねん!、varcharなのに・・・、と思いDBViewerでusertblを見てみるとcharになっています。

SELECT文のWHERE句では正しく処理されているから、定義がcharになっているはずはないのですが・・・

スクリーンショット 2015-04-01 17.53.56

な、なんでやねん!!、再度テーブルを作成しなおしてもcharになります。
どうしようもないのでchar(20)でテストケースも対応しました。

めでたく両テストが成功しました。
スクリーンショット 2015-04-01 17.59.20

って、ちっともめでたくないですが・・・、「DBViewer」プラグインの問題なのか「Java DB」の問題なのか不明ですが、次回からはHyperSQL(HSQLDBの後継)を利用してみようと思います。

JDBCの検索結果も「DBViewer」プラグインの表示内容もcharとなっているので、「Java DB」の問題のように見えますが・・・、よく使われるプロダクトにそんなバグがあるとは思えないのですが・・・

JUnit入門その6[Eclipse4.4のJUnitプラグインとDBUnitの併用(便利に利用するためのユーティリティの作成)]は以上となります。


スポンサードリンク



関連記事

利用すると生産性が格段に向上する厳選Eclipseショートカット集

今回のエントリーは、利用すると生産性が格段に向上するEclipseのショートカット集となります。

記事を読む

Eclipseの使い方(Eclipse4.4のブックマーク機能とタスク機能)

今回は、Eclipseのブックマーク機能とタスク機能の説明をさせていただきます。 両機能とも効率的

記事を読む

Eclipse4.3のチュートリアル機能で”Hello World”アプリケーションの作成方法を説明する。

Eclipseのインストールが終了したので、各画面エリアの名称の説明、各画面エリアの使い方の説明を

記事を読む

java8(JDK8)の新機能[大幅に強化されたコレクションAPI:java.util.List] をeclipseとJUnitで確認する。

Java8(JDK8)では、ラムダ式の導入を前提とした、コレクションAPIの新機能が追加されました。

記事を読む

Eclipseの「DBViewer」プラグインの使い方[前編]

「HyperSQL」の環境を作成し、Eclipseの「DBViewer」プラグインを利用してSQLを

記事を読む

Eclipseのインストールと日本語化とJDK8(Java8)対応[Eclipse4.4とEclipse4.3]

インストールするEclipseのバージョンですが、とりあえず4.3をターゲットとしておき、 4.4

記事を読む

Mac(OS X)におけるJava8(jdk8)等のインストール、アップデート、アンインストール方法

Windowsとは異なりMac(OS X)ではJDKの管理(インストール、アンインストール)が難しい

記事を読む

Eclipse4.4(Java)におけるビルド・パス関係の設定方法[ビルド・パス上のソース・フォルダー]

Eclipse4.4(Java)におけるビルド関係のビルド・パス上のソース・フォルダーの利用方法を説

記事を読む

Eclipse(4.4)でJava言語のリファクタリング機能の使い方[「メソッド・シグニチャーの変更」と基本的な抽出処理、及び「インライン化」、「定数の抽出」]

本エントリーでは、Eclipse(4.3)でJava言語のリファクタリング機能の使い方に引き続き

記事を読む

Java8のラムダ式とStream APIを利用してコーディング量の削減サンプル集

Java8になりラムダ式と「Stream API」が利用できるようになりました。 C#では一足早く

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Selenium入門その6[Selenium3でWebDriver(Java/Junit4)の環境を作成しEdge,Chrome,Firefoxで確認してみる]

Selenium3も3.0.1がリリースされましたし、今後は本格的にS

Selenium利用時のトラブルシューティング方法[クリック編]

Seleniumは便利なテスト自動化ツールですし、今後は更なる利用者の

Java8のラムダ式とStream APIを利用してコーディング量の削減サンプル集

Java8になりラムダ式と「Stream API」が利用できるようにな

Selenium入門その5[ページオブジェクトパターン(Page Object Design Pattern)を利用して変更に強いテストを作成する方法]

Selenium入門その2 では「UIマップファイル」と言う仕組みが

Javaによる非同期処理入門その1[非同期処理の実装方法の概説]

Javaによる非同期処理に関するエントリーを前々から作成したいと思って

→もっと見る

Optimization WordPress Plugins & Solutions by W3 EDGE
PAGE TOP ↑