DbUnit
16590 ワード
ユニットテストをしたことがある人はJUnitに詳しいと思いますが、今日ご紹介するDbUnit(http://dbunit.sourceforge.net/ )はデータベーステストに特化したJUnitの拡張であり、テスト対象データベースをテストループ間の状態にすることができる.現在、国内でDbUnitを紹介するシステムチュートリアルが珍しいことを考慮して、本文は理論と実例の2つの方面からDbUnitのすばらしい世界を理解します.
DbUnitの設計理念でユニットテストに詳しい開発者は、データベースのユニットテストを行う際に、通常採用される案はシミュレーションオブジェクト(mock objects)とstubsの2種類があることを知っています.データベース操作のシミュレーションテストは、JDBCなどの関連するデータベース・アクセス・クラスを分離することによって達成されます.しかし、いくつかの特殊なシステム、例えばEJBのCMP(container-managed persistence)を利用したシステムでは、データベースのアクセスオブジェクトが最下位で隠れているため、この2つのソリューションはこれらのシステムに力が入らないように見えます.
DBUnitの設計理念はテストの前に、データベースをバックアップして、それから対象データベースに私たちの必要な準備データを植え込んで、最後に、テストが終わった後に、バックアップデータベースを読み込んで、テスト前の状態に遡ります;また、DBUnitはJUnitの拡張であるため、開発者はテスト・インスタンス・コードを作成し、これらのテスト・インスタンスのライフサイクル内でデータベースの操作結果を比較することができます.
DbUnitテストの基本概念とプロセスDbUnitに基づくテストの主なインタフェースはIDataSetである.IDataSetは、1つまたは複数のテーブルのデータを表します.データベース・モードのすべての内容は、単一のIDataSetインスタンスとして表すことができます.これらのテーブル自体はItableインスタンスによって表されます.IDataSetの実装は多く、それぞれが異なるデータソースまたはロードメカニズムに対応しています.最も一般的ないくつかのIDataSetは、FlatXmlDataSet:データの単純平面ファイルXMLがQueryDataSetを表す:SQLクエリで得られたデータDatabaseDataSet:データベーステーブル自体の内容の一種XlsDataSet:データのexcel表現
一般に、DbUnitを用いてユニットテストを行うプロセスは、1業務に応じて、テスト用の準備データと予想結果データを作成し、通常xml形式のファイルに準備する.2 setUp()メソッドでデータベース内の関連テーブルをバックアップします.3 setUp()メソッドに準備データを読み込みます.4試験クラスの対応試験方法を実装する:対象方法を実行し、データベースの実際の実行結果と予想結果を比較する.5 tearDown()メソッドで、データベースをテスト前の状態に復元します.
DbUnitの開発例DbUnitの実際の運用例を以下に示す.
インスタンスは、たとえば、次のように構成された学生テーブル[student]を用意します.
id char(4)pk学号name char(50)名前sex char(1)性別birthday date生年月日
準備データは次のとおりです.
id name sex birthday 0001翁仔m 1979-12-31
0002王翠花f 1982-08-09
テスト対象クラスはStudentOpen.javaで、findStudent(String id):プライマリ・キーidに基づいてレコードaddStudent(Student student):レコードを追加する2つの方法があります.
addStudioメソッドをテストするとき、次のデータを追加するつもりです.
id name sex birthday 0088王耳m 1982-01-01
では、このメソッドを実行すると、データベースのstudentテーブルのデータは次のようになります.
id name sex birthday 0001翁仔m 1979-12-31 0002王翠花f 1982-08-09 0088王耳m 1982-01-01
次に,この2つの方法についてセルテストの方法を説明する.
インスタンス展開1準備データと予想データをxmlファイルに変換更新、追加、削除などの方法は、Assert.assertEquals()メソッドを利用して、テーブル全体を比較することができます. 全体比較テーブルの場合、個別のフィールドで比較を必要としない場合は、DefaultColumnFilter.excludedColumnsTable()メソッドを使用して、指定したフィールドを比較範囲外に除外できます.例えば、上記の例でbirthdayというフィールドを比較する必要がなければ、 というコードで処理することができる.
以前はDbunitをデータベースをテストするものとしていましたが(実はもともと)、最近Appfuseを研究しているときにDbunitがデータベースのデータに対してloadとexportを行うのはとても便利で、特に自動的にデータベースを埋め込んだり、データをエクスポートしたりするとき(2つは逆方向に行うことができます)、あるいはWebTestテストのとき、特に重要で、簡単ないくつかの言葉、データのロード、エクスポート、またはクエリーが完了します.次の例で説明します.ただし、パスを設定することに注意してください.EclipseではAntのClassPathを設定するときにDbunitとデータベースのドライバJarパッケージを追加し、その他は次の例でOKです
まずexportを実行すると、自動的にデータエクスポートファイルが生成され、あれば上書きされ、loadメソッドでデータベースにさっき生成したデータをロードさせることができます.具体的なロード方法はdbunitのoperation属性を設定します.UPDATE、INSERT、DELETE、DELETE_があります.ALL, REFRESH, CLEAN_INSERT, MSSQL_INSERT, MSSQL_REFRESH, MSSQL_CLEAN_INSERTなどのパラメータはこのようにしてプロジェクトが継続的に集積する時ずっと便利になって、データベースのものについてすべてDbunitが自動的に生成したので、Xpの方法の1つのデータベースの実践と言えるでしょう.http://www.dbunit.org/以上の例はDbunit 2.1でテストに合格した.
DbUnitの設計理念でユニットテストに詳しい開発者は、データベースのユニットテストを行う際に、通常採用される案はシミュレーションオブジェクト(mock objects)とstubsの2種類があることを知っています.データベース操作のシミュレーションテストは、JDBCなどの関連するデータベース・アクセス・クラスを分離することによって達成されます.しかし、いくつかの特殊なシステム、例えばEJBのCMP(container-managed persistence)を利用したシステムでは、データベースのアクセスオブジェクトが最下位で隠れているため、この2つのソリューションはこれらのシステムに力が入らないように見えます.
DBUnitの設計理念はテストの前に、データベースをバックアップして、それから対象データベースに私たちの必要な準備データを植え込んで、最後に、テストが終わった後に、バックアップデータベースを読み込んで、テスト前の状態に遡ります;また、DBUnitはJUnitの拡張であるため、開発者はテスト・インスタンス・コードを作成し、これらのテスト・インスタンスのライフサイクル内でデータベースの操作結果を比較することができます.
DbUnitテストの基本概念とプロセスDbUnitに基づくテストの主なインタフェースはIDataSetである.IDataSetは、1つまたは複数のテーブルのデータを表します.データベース・モードのすべての内容は、単一のIDataSetインスタンスとして表すことができます.これらのテーブル自体はItableインスタンスによって表されます.IDataSetの実装は多く、それぞれが異なるデータソースまたはロードメカニズムに対応しています.最も一般的ないくつかのIDataSetは、FlatXmlDataSet:データの単純平面ファイルXMLがQueryDataSetを表す:SQLクエリで得られたデータDatabaseDataSet:データベーステーブル自体の内容の一種XlsDataSet:データのexcel表現
一般に、DbUnitを用いてユニットテストを行うプロセスは、1業務に応じて、テスト用の準備データと予想結果データを作成し、通常xml形式のファイルに準備する.2 setUp()メソッドでデータベース内の関連テーブルをバックアップします.3 setUp()メソッドに準備データを読み込みます.4試験クラスの対応試験方法を実装する:対象方法を実行し、データベースの実際の実行結果と予想結果を比較する.5 tearDown()メソッドで、データベースをテスト前の状態に復元します.
DbUnitの開発例DbUnitの実際の運用例を以下に示す.
インスタンスは、たとえば、次のように構成された学生テーブル[student]を用意します.
id char(4)pk学号name char(50)名前sex char(1)性別birthday date生年月日
準備データは次のとおりです.
id name sex birthday 0001翁仔m 1979-12-31
0002王翠花f 1982-08-09
テスト対象クラスはStudentOpen.javaで、findStudent(String id):プライマリ・キーidに基づいてレコードaddStudent(Student student):レコードを追加する2つの方法があります.
addStudioメソッドをテストするとき、次のデータを追加するつもりです.
id name sex birthday 0088王耳m 1982-01-01
では、このメソッドを実行すると、データベースのstudentテーブルのデータは次のようになります.
id name sex birthday 0001翁仔m 1979-12-31 0002王翠花f 1982-08-09 0088王耳m 1982-01-01
次に,この2つの方法についてセルテストの方法を説明する.
インスタンス展開1準備データと予想データをxmlファイルに変換
student_pre.xml
--------------------------------------------------------------------------------
<?xml version='1.0' encoding="gb2312"?>
<dataset>
<student id="0001" name=" " sex="m" birthday="1979-12-31"/>
<student id="0002" name=" " sex="f" birthday="1982-08-09"/>
</dataset>
--------------------------------------------------------------------------------
student_exp.xml
--------------------------------------------------------------------------------
<?xml version='1.0' encoding="gb2312"?>
<dataset>
<student id="0001" name=" " sex="m" birthday="1979-12-31"/>
<student id="0002" name=" " sex="f" birthday="1982-08-09"/>
<student id="0088" name=" " sex="m" birthday="1982-01-01"/>
</dataset>
--------------------------------------------------------------------------------
2 setUp , 。
--------------------------------------------------------------------------------
protected void setUp() {
IDatabaseConnection connection =null;
try{
super.setUp();
// postgresql
Class.forName("org.postgresql.Driver");
// DB
Connection conn=DriverManager.getConnection("jdbc:postgresql:testdb.test","postgres","postgres");
// DB
connection =new DatabaseConnection(conn);
// student
QueryDataSet backupDataSet = new QueryDataSet(connection);
backupDataSet.addTable("student");
file=File.createTempFile("student_back",".xml");//
FlatXmlDataSet.write(backupDataSet,new FileOutputStream(file));
//
IDataSet dataSet = new FlatXmlDataSet( new FileInputStream("student_pre.xml"));
DatabaseOperation.CLEAN_INSERT.execute(connection,dataSet);
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(connection!=null) connection.close();
}catch(SQLException e){}
}
}
--------------------------------------------------------------------------------
3 , 。
* , assertEquals() , 。
--------------------------------------------------------------------------------
// findStudent
public void testFindStudent() throws Exception{
// findStudent
StudentOpe studentOpe=new StudentOpe();
Student result = studentOpe.findStudent("0001");
//
assertEquals(" ",result.getName());
assertEquals("m",result.getSex());
assertEquals("1979-12-31",result.getBirthDay());
}
-
public void testAddStudent() throws Exception{
// addStudent
StudentOpe studentOpe=new StudentOpe();
//
Student newStudent = new Student("0088"," ","m","1982-01-01");
//
Student result = studentOpe.addStudent(newStudent);
//
IDatabaseConnection connection=null;
try{
//
IDataSet expectedDataSet = new FlatXmlDataSet(new FileInputStream("student_exp.xml"));
ITable expectedTable = expectedDataSet.getTable("student");
//
Connection conn=getConnection();
connection =new DatabaseConnection(conn);
IDataSet databaseDataSet = connection.createDataSet();
ITable actualTable = databaseDataSet.getTable("student");
//
Assertion.assertEquals(expectedTable, actualTable);
}finally{
if(connection!=null) connection.close();
}
}
-
ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"birthday"});
ITable filteredActualTable = DefaultColumnFilter.excludedColumnsTable(actualTable,new String[]{"birthday"});
Assertion.assertEquals(filteredExpectedTable, filteredActualTable);
--------------------------------------------------------------------------------
4 tearDown() ,
--------------------------------------------------------------------------------
protected void tearDown() throws Exception{
IDatabaseConnection connection =null;
try{
super.tearDown();
Connection conn=getConnection();
connection =new DatabaseConnection(conn);
IDataSet dataSet = new FlatXmlDataSet(file);
DatabaseOperation.CLEAN_INSERT.execute(connection,dataSet);
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(connection!=null) connection.close();
}catch(SQLException e){}
}
}
以前はDbunitをデータベースをテストするものとしていましたが(実はもともと)、最近Appfuseを研究しているときにDbunitがデータベースのデータに対してloadとexportを行うのはとても便利で、特に自動的にデータベースを埋め込んだり、データをエクスポートしたりするとき(2つは逆方向に行うことができます)、あるいはWebTestテストのとき、特に重要で、簡単ないくつかの言葉、データのロード、エクスポート、またはクエリーが完了します.次の例で説明します.ただし、パスを設定することに注意してください.EclipseではAntのClassPathを設定するときにDbunitとデータベースのドライバJarパッケージを追加し、その他は次の例でOKです
<project name="SimpleTest" basedir="." default="load">
<property name="dbDriver" value="oracle.jdbc.driver.OracleDriver" />
<property name="dbUrl" value="jdbc:oracle:thin:@192.168.104.47:1521:esample" />
<property name="dbUser" value="esample" />
<property name="dbPassword" value="esample" />
<taskdef name="dbunit" classname="org.dbunit.ant.DbUnitTask" />
<target name="load" description="Loads the database with sample data">
<property name="operation" value="CLEAN_INSERT" />
<property name="file" value="partial.xml" />
<dbunit driver="${dbDriver}" url="${dbUrl}" userid="${dbUser}" password="${dbPassword}">
<operation type="${operation}" src="${file}" format="xml" />
</dbunit>
</target>
<target name="export">
<dbunit driver="${dbDriver}" url="${dbUrl}" userid="${dbUser}" password="${dbPassword}">
<export dest="partial.xml" format="xml">
<query name="QueryExhibtion" sql="SELECT Exhibition_Id FROM Ex_exhibition " />
<table name="ex_exhibition" />
</export>
</dbunit>
</target>
</project>
まずexportを実行すると、自動的にデータエクスポートファイルが生成され、あれば上書きされ、loadメソッドでデータベースにさっき生成したデータをロードさせることができます.具体的なロード方法はdbunitのoperation属性を設定します.UPDATE、INSERT、DELETE、DELETE_があります.ALL, REFRESH, CLEAN_INSERT, MSSQL_INSERT, MSSQL_REFRESH, MSSQL_CLEAN_INSERTなどのパラメータはこのようにしてプロジェクトが継続的に集積する時ずっと便利になって、データベースのものについてすべてDbunitが自動的に生成したので、Xpの方法の1つのデータベースの実践と言えるでしょう.http://www.dbunit.org/以上の例はDbunit 2.1でテストに合格した.