A Day In The Life

とあるプログラマの備忘録

DBテスト用基底クラス

DBテスト用基底クラスを作成したので紹介します。

/**
 * DBテストクラス用基底クラス
 * @author glass-_-onion
 * @history 
 */
public abstract class BaseDatabaseTestCase
                    extends DatabaseTestCase {
    private Log log = LogFactory.getLog(
                        this.getClass().getName());
    private File file = null;
    private IDatabaseConnection conn = null;
    private String[] tableNames = null;
    public BaseDatabaseTestCase() {
        super();
    }
    public BaseDatabaseTestCase(String name) {
        super(name);
    }
    /**
     * テスト対象のテーブル名を取得するメソッド
     */
    protected final String getTableName(int index) {
        return tableNames[index];
    }
    /**
     * テストデータXmlファイルの名前を取得するメソッド
     */
    protected abstract String getSelectFileName();
    /**
     * テストデータXmlファイルの名前を取得するメソッド(Insert)
     */
    protected String getInsertFileName() {
        return null;
    }
    /**
     * テストデータXmlファイルの名前を取得するメソッド(Update)
     */
    protected String getUpdateFileName() {
        return null;
    }
    /**
     * テストデータXmlファイルの名前を取得するメソッド(Delete)
     */
    protected String getDeleteFileName() {
        return null;
    }
    /**
     * ログオブジェクトをを取得するメソッド
     */
    protected Log getLog() {
        return log;
    }
    /**
     * @see DatabaseTestCase#getSetUpOperation()
     */
    protected DatabaseOperation getSetUpOperation()
                throws Exception {
        return DatabaseOperation.NONE;
    }
    /**
     * @see DatabaseTestCase#getTearDownOperation()
     */
    protected DatabaseOperation getTearDownOperation()
                throws Exception {
        return DatabaseOperation.NONE;
    }
    /**
     * @see DatabaseTestCase#setUp()
     */
    protected void setUp() throws Exception {
        super.setUp();
        try {
            conn = getConnection();
            IDataSet dataset = getDataSet(getSelectFileName());
            tableNames = dataset.getTableNames();
            //元データ退避
            QueryDataSet partialDataSet = new QueryDataSet(conn);
            for(int i = 0, n = tableNames.length; i < n; i++) {
                partialDataSet.addTable(tableNames[i]);
            }
            file = File.createTempFile("tmp", ".xml");
            FlatXmlDataSet.write(
                partialDataSet, new FileOutputStream(file));
            //テストデータ投入
            DatabaseOperation.CLEAN_INSERT.execute(conn, dataset);
        } catch (Exception e) {
            log.error(e, e);
            super.fail(e.toString());
        }
    }
    /**
     * @see DatabaseTestCase#tearDown()
     */
    protected void tearDown() throws Exception {
        try {
            //元データ復元
            IDataSet dataset = new FlatXmlDataSet(file);
            DatabaseOperation.CLEAN_INSERT.execute(conn, dataset);
        } catch (Exception e) {
            log.error(e, e);
            super.fail(e.toString());
        } finally {
            if(conn != null) conn.close();
        }
        super.tearDown();
    }
    /**
     * @see DatabaseTestCase#getDataSet()
     */
    protected IDataSet getDataSet() throws Exception {
        return getDataSet(getSelectFileName());
    }
    /**
     * @see DatabaseTestCase#getConnection()
     */
    protected IDatabaseConnection getConnection()
                throws Exception {
        Connection connection = ConnectionUtil2.getJDBCConnection();
        String schema = connection.getMetaData().getUserName();
        IDatabaseConnection conn = new DatabaseConnection(
                connection, schema);
        DatabaseConfig config = conn.getConfig();
        config.setProperty(
            DatabaseConfig.PROPERTY_DATATYPE_FACTORY,
            new OracleDataTypeFactory());
        return conn;
    }
    /**
     * ファイルの取得
     */
    private InputStream getFileStream(String filePath) {
        return this.getClass().getResourceAsStream(filePath);
    }
    /**
     * ファイル名を指定してデータセットを取得する
     */
    private IDataSet getDataSet(String fileName) throws Exception {
        ReplacementDataSet expectedDataSet = new ReplacementDataSet(
            new XlsDataSet(getFileStream(fileName)));
        expectedDataSet.addReplacementObject(
            "[SYSDATE]",
            new Date(System.currentTimeMillis()));
        expectedDataSet.addReplacementObject("[NULL]", null);
        return expectedDataSet;
    }
    /**
     * テスト結果として期待されるデータを取得する
     */
    protected final ITable getExpectedTable(int index, String fileName)
                throws Exception {
        return getExpectedTable(getTableName(index), fileName);
    }
    /**
     * テスト結果として期待されるデータを取得する
     */
    protected ITable getExpectedTable(String tableName, String fileName)
                throws Exception {
        IDataSet expectedDataSet = getDataSet(fileName);
        ITable expectedTable = expectedDataSet.getTable(tableName);
        return expectedTable;
    }
    /**
     * データベースに登録されているデータを取得する
     */
    protected ITable getActualTable(int index)
                throws Exception {
        return getActualTable(getTableName(index));
    }
    /**
     * データベースに登録されているデータを取得する
     */
    protected ITable getActualTable(String tableName)
                throws Exception {
        IDatabaseConnection conn = null;
        ITable actualTable = null;
        try {
            conn = getConnection();
            IDataSet actualDataSet = conn.createDataSet();
            actualTable = actualDataSet.getTable(tableName);
        } catch (Exception e) {
            log.error(e, e);
            super.fail(e.toString());
        } finally {
            if(conn != null) conn.close();
        }
        return actualTable;
    }
    /**
     * データベースに登録されているデータ件数を取得する
     */
    protected int getTableRowCount(String tableName)
                throws Exception {
        IDatabaseConnection conn = null;
        ITable actualTable = null;
        try {
            conn = getConnection();
            IDataSet actualDataSet = conn.createDataSet();
            actualTable = actualDataSet.getTable(tableName);
        } catch (Exception e) {
            log.error(e, e);
            super.fail(e.toString());
        } finally {
            if(conn != null) conn.close();
        }
        return actualTable.getRowCount();
    }
    /**
     * 2つのテーブルを比較する
     */
    protected void assertEqualsTable(ITable expectedTable,ITable actualTable)
                throws Exception {	
        for(int i = 0, rowCount = expectedTable.getRowCount();
            i < rowCount; i++){
            for(int j = 0, colCount =
                expectedTable.getTableMetaData().getColumns().length;
                j < colCount; j++) {
                Column[] col = expectedTable
                                .getTableMetaData()
                                .getColumns();
                String colName = col[j].getColumnName();
                String expectedColValue = String.valueOf(
                    expectedTable.getValue(i, colName));
                String actualColValue = String.valueOf(
                    actualTable.getValue(i, colName));
                assertEquals("Line:" + i + " Column:" + colName,
                            expectedColValue, actualColValue);
            }
        }
    }
}

とこんな感じです。
このクラスではコネクションの設定や元データの退避を行ってテストデータをロードする機能を提供します。

このクラスを継承して作成したテストケースは1データパターン※のテストが実施できます。

複数のデータパターンをテストする場合はテストクラスを分けてTestSuiteで実行してください。

テストデータはExcelファイルで用意されていることを想定しています。

※select,insert,update,delete処理に対してそれぞれ1つのデータを使用すること

テスト手順

前準備

検索系テストで使用するデータファイルを設定する

getSelectFileName()をオーバーライド、return値にファイル名を指定

Insert系テストで使用するデータファイルを設定する

getInsertFileName()をオーバーライド、return値にファイル名を指定

Update系テストで使用するデータファイルを設定する

getUpdateFileName()をオーバーライド、return値にファイル名を指定

Delete系テストで使用するデータファイルを設定する

getDeleteFileName()をオーバーライド、return値にファイル名を指定

検索系テスト

検索条件なしで全件データを取ってくるか確認
1件もヒットしない条件を指定してデータが取得できないことを確認
1件ヒットする条件を指定して期待されるデータが取得できているか確認
1件以上ヒットする条件を指定して期待されるデータが取得できているか確認

Insert系

データ件数が1件増えることを確認

挿入したデータが期待されるデータと同じことを確認

主キーを重複して指定した場合、DatabaseExceptionがスローされることを確認

Update系

変更前データ件数と変更後データ件数が同じことを確認

変更したデータが期待されるデータと同じことを確認

Delete系

削除前と削除後のデータ件数の確認

削除したデータをセレクトしても該当データなしになるか確認

削除後のデータが期待されるデータと同じことを確認