S2JUnit4はJUnit4を拡張したテスティングフレームワークです。
S2JUnit4はアノテーションと命名規則の双方を利用し少ないコードで効率のよいテストを可能にします。
Seasar2ではテスティングフレームワークとしてすでにS2Unitを提供していますが、S2JUnit4はJUnit4の対応に加えS2Unitの次の機能を自動化することを特長としています。
- diconファイルのinclude
- Excelに用意した事前データのデータベースへの書き出し
- トランザクションの開始とロールバック
S2JUnit4の主な機能には次のものがあります。
- javaee5.diconを自動でincludeします。
- public、非static、引数なし、戻り値なしのメソッドをテストメソッドとみなします。Testアノテーションがついているものもついていないものも等しくテストメソッドとみなします。
- beforeXxx、afterXxx、という命名規則に従ったメソッドを個別のテストメソッドの前後に実行します。(S2UnitにおけるsetUpXxx、tearDownXxxに相当します。)
- テストメソッド実行前に自動的にトランザクションを開始し、トランザクション終了後に自動的にロールバックを行います。トランザクションの振る舞いはTxBehaviorアノテーションを使うことで変更できます。TxBehaviorアノテーションに指定できるTxBehaviorTypeにはNONE(トランザクションを開始しない)、COMMIT(トランザクションをコミットする)、ROLLBACK(トランザクションをロールバックする)の3種類があります。ROLLBACKがデフォルトの振る舞いです。
- 「テストクラス名_.dicon」という名称のdiconファイルがテストクラスと同一のパッケージもしくはクラスパスのルートに存在すればテストメソッド実行前に自動的にincludeします。
- 「テストクラス名_テストメソッド名.xls」もしくは「テストクラス名.xls」という名称のExcelがテストクラスと同一のパッケージもしくはクラスパスのルートに存在すればテストメソッド実行前に自動的に読み込みデータベースに書き込みます。S2JUnit4は最初に「テストクラス名_テストメソッド名.xls」を存在検査し存在すれば「テストクラス名_テストメソッド名.xls」を使用し、存在しない場合は「テストクラス名.xls」を使用します。
- インターフェース型のフィールドがテストクラスに宣言されている場合、その型のコンポーネントがコンテナに存在すればS2JUnit4はそのコンポーネントをフィールドに設定します。
- 非static、非finalなフィールドがテストクラスに宣言されている場合、その名前からアンダースコア(_)を除いた名前のコンポーネントがコンテナに登録されていれば、S2JUnit4はそのコンポーネントをフィールドに設定します。
- DataAccessorクラスがテストクラスのフィールドに宣言されている場合、S2JUnit4はDataAccessorクラスのインスタンスをフィールドに設定します。DataAccessorクラスはExcelとデータベースにアクセスするためのメソッド群を持ちます。
- S2Assertクラスのメソッドをstatic importすることでS2JUnit4固有のアサーションメソッドを実行できます。
- diconファイルを使い、上に述べた機能をカスタマイズすることができます。たとえば、beforeXxx、afterXxxという命名規則を変更したり、独自アノテーションを使って振る舞いを拡張したりすることができます。
S2Unitのサンプルと同様、従業員を従業員番号で検索するDAOをサンプルとします。
シナリオとして従業員番号9900で検索をかけると、従業員番号9900の従業員テーブルと部署番号99の部署テーブルをジョインして返す想定とします。
このケースをテストするためには、検索のための従業員テーブルと部署テーブルのデータと検索した結果を検証するためのデータが必要です。
データはExcelで用意します。データの作り方などについては適宜S2Unitのサンプルを参照してください。
従業員テーブルと部署テーブルの事前データのExcelはS2JUnitが自動で読み込みデータベースへ書き込めるように「テストクラス名_メソッド名.xls」、すなわちここでは「EmployeeDaoImplTest_getEmployee.xls」という名前にし、テストクラスと同一パッケージ内に置きます。
検索した結果を検証するための期待値データのExcelはテストメソッド内で明示的に指定します。
ここではわかりやすく「EmployeeDaoImplTest_getEmployee_Expected.xls」という名前にします。
examples.s2junit4.EmployeeDaoImplTest.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<include path="javaee5.dicon"/>
<component class="examples.s2junit4.EmployeeDaoImpl">
<property name="getEmployeeHandler">
<component class="org.seasar.extension.jdbc.impl.BasicSelectHandler">
<property name="sql">
"SELECT e.empno, e.ename, e.deptno, d.dname FROM emp e, dept d
WHERE e.empno = ? AND e.deptno = d.deptno"
</property>
<property name="resultSetHandler">
<component class="org.seasar.extension.jdbc.impl.BeanResultSetHandler">
<arg>@examples.s2junit4.Employee@class</arg>
</component>
</property>
</component>
</property>
</component>
</components>
diconファイルではDAOの実装の設定を行います。
S2JUnit4が自動でdiconファイルをincludeできるようにdiconファイルは「テストクラス名.dicon」すなわち「EmployeeDaoImplTest.dicon」という名前とし、テストクラスと同一パッケージ内に置きます。
examples.s2junit4.EmployeeDaoImplTest
package examples.s2junit4;
import static org.seasar.framework.unit.S2Assert.assertEquals;
import org.junit.Ignore;
import org.junit.runner.RunWith;
import org.seasar.extension.dataset.DataSet;
import org.seasar.framework.unit.DataAccessor;
import org.seasar.framework.unit.Seasar2;
@RunWith(Seasar2.class)
public class EmployeeDaoImplTest {
private EmployeeDao dao;
private DataAccessor da;
public void getEmployee() throws Exception {
Employee emp = dao.getEmployee(9900);
DataSet expected = da
.readXls("EmployeeDaoImplTest_getEmployee_Expected.xls");
assertEquals("1", expected, emp);
}
@Ignore("not implemented.")
public void getEmployeeByName() throws Exception {
}
}
S2JUnit4でテストクラスを実行するには@RunWith(Seasar2.class)の指定が必要です。public、非static、引数なし、戻り値なしのメソッドがテストメソッドとして実行されます。Ignoreアノテーションが指定されているテストメソッドは実行されません。従って、ここではgetEmployeeメソッドのみが実行されます。
インターフェース型でインスタンス変数(dao)を宣言しておけば、テストメソッドを開始する前にS2Containerから取り出されて自動的に設定されます。
期待値をもつExcelを読み込むためにはDataAccessorクラスのreadXlsメソッドを使います。DataAccessorクラスのインスタンスは宣言しておけば自動的に設定されます。
DataSetとBeanを比較し値が等しいことを検証するにはS2AssertクラスのassertEqualsメソッドを利用します。このメソッドはstatic importの宣言をしておくことで簡潔に利用できます。
テストメソッドを実行する処理の流れをgetEmployeeメソッドの実行に則して説明すると次のようになります。
- Ignoreアノテーションが指定されていないことを確認する(指定されていれば以下の一連の処理は行わない)
- javaee5.diconが存在すれば自動でincludeする
- EmployeeDaoImplTest.diconが存在すれば自動でincludeする
- Beforeアノテーションが指定されたメソッドが存在すれば実行する
- beforeGetEmployeeメソッドが存在すれば実行する
- EmployeeDaoImplとDataAccessorのインスタンスをフィールドに設定する
- トランザクションを開始する
- EmployeeDaoImplTest_getEmployee_.xlsが存在すれば読み込んでデータベースに書き込む
- EmployeeDaoImplTest.xlsが存在すれば読み込んでデータベースに書き込む
- getEmployeeメソッドを実行する
- トランザクションをロールバックする
- afterGetEmployeeメソッドが存在すれば実行する
- Afterアノテーションが指定されたメソッドが存在すれば実行する
diconファイルにコンポーネントを指定することでS2JUnit4の振る舞いを変更することができます。
カスタマイズのためのコンポーネントを含むdiconファイルのパス名には、org.seasar.unit.s2junit4.config をキーとして取得できるシステムプロパティが存在する場合はその値が使われ、存在しない場合はクラスパスのルートに存在するs2junit4.diconが使われます。
diconファイルに設定できるコンポーネントはorg.seasar.framework.unitパッケージ内の次のインタフェースの実装のすべてまたはいずれかです。
- Seasar2.Configurator
- Seasar2.Provider
- S2TestClassMethodsRunner.Provider
- S2TestMethodRunner.Provider
- TestIntrospector
|