Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その55 )( TestDataResource クラスの機能追加2 )
概要
Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その54 )( TestDataResource クラスの機能追加 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
参照したサイト・書籍
目次
- ksbysample.common.test.rule.db パッケージ配下のクラスで dataSource.getConnection() で取得した Connection オブジェクトをクローズしていない問題を修正する
- @TestData アノテーションを複数付加できるようにする
- TestDataResource クラス内の定数にルートパスを設定することで @BaseTestData, @TestData アノテーションではルートパスを除く部分のみ指定できるようにする
- 次回は。。。
手順
ksbysample.common.test.rule.db パッケージ配下のクラスで dataSource.getConnection() で取得した Connection オブジェクトをクローズしていない問題を修正する
feature/92-issue ブランチを作成します。
src/test/java/ksbysample/common/test/rule/db の下の DbUnitUtils.java を リンク先の内容 に変更します。
src/test/java/ksbysample/common/test/rule/db の下の TestDataLoader.java を リンク先の内容 に変更します。
src/test/java/ksbysample/common/test/rule/db の下の TestSqlExecutor.java を リンク先の内容 に変更します。
src/test/java/ksbysample/common/test/rule/db の下の TableDataAssert.java を リンク先の内容 に変更します。
src/test/java/ksbysample/common/test/rule/db の下の TestDataResource.java を リンク先のその1の内容 に変更します。
動作確認します。Gradle projects View から clean タスクの実行→「Rebuild Project」メニューの実行→build タスクの実行を行い、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。
Project View のルートでコンテキストメニューを表示して「Run 'All Tests' with Coverage」を選択し、テストが全て成功することを確認します。
commit、GitHub へ Push、feature/92-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/92-issue ブランチを削除、をします。
@TestData アノテーションを複数付加できるようにする
feature/90-issue ブランチを作成します。
src/test/java/ksbysample/common/test/rule/db の下に TestDataList.java を作成します。作成後、リンク先の内容 に変更します。
src/test/java/ksbysample/common/test/rule/db の下の TestData.java を リンク先の内容 に変更します。
src/test/java/ksbysample/common/test/rule/db の下の TestDataResource.java を リンク先のその2の内容 に変更します。
src/test/resources/ksbysample/webapp/lending/web/confirmresult/testdata/001 の下の lending_book.csv を リンク先の内容 に変更します。
動作確認します。src/test/java/ksbysample/webapp/lending の下の TestDataResourceTest.java に以下のテストクラスを追記します。
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class テストクラス_TestData_Annotation { @Rule @Autowired public TestDataResource testDataResource; @Autowired private DataSource dataSource; @Test @TestData("src/test/resources/ksbysample/webapp/lending/web/lendingapp/testdata/001") public void テストメソッド_lendingapp() throws Exception { IDataSet dataSet = new CsvDataSet( new File("src/test/resources/ksbysample/webapp/lending/web/lendingapp/testdata/001")); TableDataAssert tableDataAssert = new TableDataAssert(dataSet, dataSource); tableDataAssert.assertEquals("lending_app", new String[]{}, AssertOptions.EXCLUDE_COLUM); tableDataAssert.assertEquals("lending_book", new String[]{}, AssertOptions.EXCLUDE_COLUM); } @Test @TestData("src/test/resources/ksbysample/webapp/lending/web/confirmresult/testdata/001") public void テストメソッド_confirmresult() throws Exception { IDataSet dataSet = new CsvDataSet( new File("src/test/resources/ksbysample/webapp/lending/web/confirmresult/testdata/001")); TableDataAssert tableDataAssert = new TableDataAssert(dataSet, dataSource); tableDataAssert.assertEquals("lending_app", new String[]{}, AssertOptions.EXCLUDE_COLUM); tableDataAssert.assertEquals("lending_book", new String[]{}, AssertOptions.EXCLUDE_COLUM); } @Test @TestData(order = 1, value = "src/test/resources/ksbysample/webapp/lending/web/lendingapp/testdata/001") @TestData(order = 2, value = "src/test/resources/ksbysample/webapp/lending/web/confirmresult/testdata/001") public void テストメソッド_lendingapp_confirmresult() throws Exception { IDataSet dataSet = new CsvDataSet( new File("src/test/resources/ksbysample/webapp/lending/web/confirmresult/testdata/001")); TableDataAssert tableDataAssert = new TableDataAssert(dataSet, dataSource); tableDataAssert.assertEquals("lending_app", new String[]{}, AssertOptions.EXCLUDE_COLUM); tableDataAssert.assertEquals("lending_book", new String[]{}, AssertOptions.EXCLUDE_COLUM); } @Test @TestData(order = 2, value = "src/test/resources/ksbysample/webapp/lending/web/lendingapp/testdata/001") @TestData(order = 1, value = "src/test/resources/ksbysample/webapp/lending/web/confirmresult/testdata/001") public void テストメソッド_confirmresult_lendingapp() throws Exception { IDataSet dataSet = new CsvDataSet( new File("src/test/resources/ksbysample/webapp/lending/web/lendingapp/testdata/001")); TableDataAssert tableDataAssert = new TableDataAssert(dataSet, dataSource); tableDataAssert.assertEquals("lending_app", new String[]{}, AssertOptions.EXCLUDE_COLUM); tableDataAssert.assertEquals("lending_book", new String[]{}, AssertOptions.EXCLUDE_COLUM); } }
テストクラス_TestData_Annotation の左側の矢印アイコンをクリックしてコンテキストメニューを表示し、「Run TestDataResourceTest$テストクラス_Te...
」を選択してテストを実行します。
テストが成功することが確認できます。
commit、GitHub へ Push、feature/90-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/90-issue ブランチを削除、をします。
TestDataResource クラス内の定数にルートパスを設定することで @BaseTestData, @TestData アノテーションではルートパスを除く部分のみ指定できるようにする
feature/91-issue ブランチを作成します。
src/test/java/ksbysample/common/test/rule/db の下の TestDataResource.java を リンク先のその3の内容 に変更します。
Ctrl+Shift+R を押して「Replace in Path」ダイアログを表示し、「Text to find」に
@TestData("src/test/resources/ksbysample/webapp/lending/
を、「Replace with」に@TestData("
を入力してから「Find」ボタンをクリックしてプロジェクト内のファイルの文字列を置換します。動作確認します。Gradle projects View から clean タスクの実行→「Rebuild Project」メニューの実行→build タスクの実行を行い、"BUILD SUCCESSFUL" のメッセージが出力されることを確認します。
Project View のルートでコンテキストメニューを表示して「Run 'All Tests' with Coverage」を選択し、テストが全て成功することを確認します。
commit、GitHub へ Push、feature/91-issue -> 1.0.x へ Pull Request、1.0.x でマージ、feature/91-issue ブランチを削除、をします。
次回は。。。
もう少しテスト用ライブラリの機能強化を行います。TestDataResource クラスはこれで終了で、次回は TableDataAssert クラスの機能追加を行います。
ソースコード
DbUnitUtils.java
package ksbysample.common.test.rule.db; import org.dbunit.DatabaseUnitException; import org.dbunit.database.DatabaseConfig; import org.dbunit.database.DatabaseConnection; import org.dbunit.database.IDatabaseConnection; import java.sql.Connection; import java.sql.SQLException; public class DbUnitUtils { public static final String NULL_STRING = "[null]"; public static IDatabaseConnection createDatabaseConnection(Connection connection) throws SQLException, DatabaseUnitException { IDatabaseConnection conn = new DatabaseConnection(connection); DatabaseConfig databaseConfig = conn.getConfig(); databaseConfig.setProperty(DatabaseConfig.FEATURE_ALLOW_EMPTY_FIELDS, true); return conn; } }
- createDatabaseConnection メソッドの以下の点を変更します。
- 引数を
DataSource dataSource
→Connection connection
へ変更します。 new DatabaseConnection(...)
の引数をdataSource.getConnection()
→connection
へ変更します。
- 引数を
TestDataLoader.java
package ksbysample.common.test.rule.db; import org.dbunit.database.IDatabaseConnection; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ReplacementDataSet; import org.dbunit.dataset.csv.CsvDataSet; import org.dbunit.operation.DatabaseOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.io.File; import java.sql.Connection; @Component public class TestDataLoader { @Autowired private DataSource dataSource; public void load(String csvDir) { IDatabaseConnection conn = null; try (Connection connection = dataSource.getConnection()) { conn = DbUnitUtils.createDatabaseConnection(connection); load(conn, csvDir); } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (conn != null) conn.close(); } catch (Exception ignored) { } } } public void load(IDatabaseConnection conn, String csvDir) { try { IDataSet dataSet = new CsvDataSet(new File(csvDir)); ReplacementDataSet replacementDataset = new ReplacementDataSet(dataSet); replacementDataset.addReplacementObject(DbUnitUtils.NULL_STRING, null); DatabaseOperation.CLEAN_INSERT.execute(conn, replacementDataset); } catch (Exception e) { throw new RuntimeException(e); } } }
public void load(IDatabaseConnection conn, String csvDir)
メソッドを追加します。public void load(String csvDir)
メソッドの以下の点を変更します。- try の後に
(Connection connection = dataSource.getConnection())
を追加します。 DbUnitUtils.createDatabaseConnection(...)
の引数をdataSource
→connection
に変更します。- その後の処理を
load(conn, csvDir);
に変更します。
- try の後に
TestSqlExecutor.java
public void execute(Connection connection, Description description) throws SQLException { try (Statement stmt = connection.createStatement()) { // テストクラスに付加されている @BaseTestSql, @TestSql アノテーションの SQL を実行する Class<?> testClass = description.getTestClass(); executeTestSqlListOrTestSql(stmt , testClass.getAnnotation(this.testSqlListClass) , testClass.getAnnotation(this.testSqlClass)); // TestDataResource クラスのフィールドに付加されている @BaseTestSql, @TestSql アノテーションの SQL を実行する Field[] fields = description.getTestClass().getDeclaredFields(); for (Field field : fields) { if (field.getType().equals(TestDataResource.class)) { executeTestSqlListOrTestSql(stmt , field.getAnnotation(this.testSqlListClass) , field.getAnnotation(this.testSqlClass)); } } // テストメソッドに付加されている @BaseTestSql, @TestSql アノテーションの SQL を実行する executeTestSqlListOrTestSql(stmt , description.getAnnotation(this.testSqlListClass) , description.getAnnotation(this.testSqlClass)); } } .......... private void executeTestSqlList(Statement stmt, L testSqlList) { if (testSqlList != null) { Arrays.asList(value(testSqlList)).stream() .sorted(comparing(testSql -> order(testSql))) .forEach(testSql -> executeTestSql(stmt, testSql)); } }
- execute メソッドの以下の点を変更します。
- メソッドの第1引数を
DataSource dataSource
→Connection connection
へ変更します。 - try の後の (...) の中の記述を
Statement stmt = dataSource.getConnection().createStatement()
→Statement stmt = connection.createStatement()
へ変更します。
- メソッドの第1引数を
- executeTestSqlList メソッドの中の Stream API の forEach の中の記述から {} を削除します。
TableDataAssert.java
private ITable actualTable(String tableName, String[] columnNames, AssertOptions options) throws DatabaseUnitException, SQLException { IDatabaseConnection conn = null; ITable table = null; try (Connection connection = this.dataSource.getConnection()) { conn = DbUnitUtils.createDatabaseConnection(connection); table = conn.createDataSet().getTable(tableName); if (columnNames != null) { table = columnFilter(table, columnNames, options); } } finally { try { if (conn != null) conn.close(); } catch (Exception ignored) { } } return table; }
- actualTable メソッドの以下の点を変更しました。
IDatabaseConnection conn = new DatabaseConnection(this.dataSource.getConnection());
と記述していて、かつ取得した IDatabaseConnection オブジェクトも close していなかったので、Connection オブジェクトは try-with-resources 構文内で取得して自動的にクローズするようにし、IDatabaseConnection オブジェクトの取得はnew DatabaseConnection(...)
→DbUnitUtils.createDatabaseConnection(...)
へ変更してクローズする処理を追加しました。
TestDataResource.java
■その1
@Override protected void starting(Description description) { // @NouseTestDataResource アノテーションがテストメソッドに付加されていない場合には処理を実行する if (!hasNoUseTestDataResourceAnnotation(description)) { IDatabaseConnection conn = null; try (Connection connection = dataSource.getConnection()) { conn = DbUnitUtils.createDatabaseConnection(connection); // バックアップ&ロード&リストア対象のテストデータのパスを取得する String testDataBaseDir = getBaseTestDir(description); // バックアップを取得する backupDb(conn, testDataBaseDir); // テストデータをロードする testDataLoader.load(conn, testDataBaseDir); // @BaseTestSql アノテーションで指定された SQL を実行する TestSqlExecutor<BaseTestSqlList, BaseTestSql> baseTestSqlExecutor = new TestSqlExecutor<>(BaseTestSqlList.class, BaseTestSql.class); baseTestSqlExecutor.execute(connection, description); // テストメソッドに @TestData アノテーションが付加されている場合には、 // アノテーションで指定されたテストデータをロードする loadTestData(conn, description); // @TestSql アノテーションで指定された SQL を実行する TestSqlExecutor<TestSqlList, TestSql> testSqlExecutor = new TestSqlExecutor<>(TestSqlList.class, TestSql.class); testSqlExecutor.execute(connection, description); } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (conn != null) conn.close(); } catch (Exception ignored) { } } } } .......... private void loadTestData(IDatabaseConnection conn, Description description) { description.getAnnotations().stream() .filter(annotation -> annotation instanceof TestData) .forEach(annotation -> { TestData testData = (TestData) annotation; testDataLoader.load(conn, testData.value()); }); }
- loadTestData メソッドの以下の点を変更します。
- 第1引数に
IDatabaseConnection conn
を追加します。 testDataLoader.load(...)
の第1引数にconn
を追加します。
- 第1引数に
- starting メソッドの以下の点を変更します。
- try の後に
(Connection connection = dataSource.getConnection())
を追加します。 if (!hasNoUseTestDataResourceAnnotation(description)) { ... }
の記述をtry (...)
の外側に移動します。@NoUseTestDataResource アノテーションが付加されている場合には Connection オブジェクトを取得しないようにします。DbUnitUtils.createDatabaseConnection(...)
をdataSource
→connection
へ変更します。testDataLoader.load(...)
の第1引数にconn
を追加します。baseTestSqlExecutor.execute(...)
の第1引数をdataSource
→connection
へ変更します。loadTestData(...)
の第1引数にconn
を追加します。testSqlExecutor.execute(...)
の第1引数をdataSource
→connection
へ変更します。
- try の後に
■その2
private void loadTestData(IDatabaseConnection conn, Description description) { description.getAnnotations().stream() .filter(annotation -> annotation instanceof TestDataList || annotation instanceof TestData) .forEach(annotation -> { if (annotation instanceof TestDataList) { TestDataList testDataList = (TestDataList) annotation; Arrays.asList(testDataList.value()).stream() .sorted(comparing(testData -> testData.order())) .forEach(testData -> testDataLoader.load(conn, testData.value())); } else { TestData testData = (TestData) annotation; testDataLoader.load(conn, testData.value()); } }); }
- loadTestData メソッドの以下の点を変更します。
■その3
package ksbysample.common.test.rule.db; import org.dbunit.DatabaseUnitException; import org.dbunit.database.IDatabaseConnection; import org.dbunit.database.QueryDataSet; import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ReplacementDataSet; import org.dbunit.dataset.xml.FlatXmlDataSet; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.dbunit.operation.DatabaseOperation; import org.junit.rules.TestWatcher; import org.junit.runner.Description; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.Paths; import java.sql.Connection; import java.sql.SQLException; import java.util.Arrays; import java.util.Collection; import java.util.List; import static java.util.Comparator.comparing; @Component public class TestDataResource extends TestWatcher { private static final String BASETESTDATA_ROOT_DIR = "src/test/resources/"; private static final String TESTDATA_ROOT_DIR = "src/test/resources/ksbysample/webapp/lending/"; private static final String BASETESTDATA_DIR = BASETESTDATA_ROOT_DIR + "testdata/base"; private static final String BACKUP_FILE_NAME = "ksbylending_backup"; @Autowired private DataSource dataSource; @Autowired private TestDataLoader testDataLoader; private File backupFile; @Override protected void starting(Description description) { // @NouseTestDataResource アノテーションがテストメソッドに付加されていない場合には処理を実行する if (!hasNoUseTestDataResourceAnnotation(description)) { IDatabaseConnection conn = null; try (Connection connection = dataSource.getConnection()) { conn = DbUnitUtils.createDatabaseConnection(connection); // バックアップ&ロード&リストア対象のテストデータのパスを取得する String testDataBaseDir = getBaseTestDir(description); // バックアップを取得する backupDb(conn, testDataBaseDir); // テストデータをロードする testDataLoader.load(conn, testDataBaseDir); // @BaseTestSql アノテーションで指定された SQL を実行する TestSqlExecutor<BaseTestSqlList, BaseTestSql> baseTestSqlExecutor = new TestSqlExecutor<>(BaseTestSqlList.class, BaseTestSql.class); baseTestSqlExecutor.execute(connection, description); // テストメソッドに @TestData アノテーションが付加されている場合には、 // アノテーションで指定されたテストデータをロードする loadTestData(conn, description); // @TestSql アノテーションで指定された SQL を実行する TestSqlExecutor<TestSqlList, TestSql> testSqlExecutor = new TestSqlExecutor<>(TestSqlList.class, TestSql.class); testSqlExecutor.execute(connection, description); } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (conn != null) conn.close(); } catch (Exception ignored) { } } } } @Override protected void finished(Description description) { IDatabaseConnection conn = null; try (Connection connection = dataSource.getConnection()) { // @NouseTestDataResource アノテーションがテストメソッドに付加されていない場合には処理を実行する if (!hasNoUseTestDataResourceAnnotation(description)) { conn = DbUnitUtils.createDatabaseConnection(connection); // バックアップからリストアする restoreDb(conn); } } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (conn != null) conn.close(); } catch (Exception ignored) { } if (backupFile != null) { try { Files.delete(backupFile.toPath()); } catch (Exception e) { throw new RuntimeException(e); } backupFile = null; } } } private boolean hasNoUseTestDataResourceAnnotation(Description description) { Collection<Annotation> annotationList = description.getAnnotations(); boolean result = annotationList.stream() .anyMatch(annotation -> annotation instanceof NoUseTestDataResource); return result; } private String getBaseTestDir(Description description) { // @BaseTestData アノテーションで指定されている場合にはそれを使用し、指定されていない場合には // BASETESTDATA_DIR 定数で指定されているものと使用する // テストメソッドに @BaseTestData アノテーションが付加されているかチェックする BaseTestData baseTestData = description.getAnnotation(BaseTestData.class); if (baseTestData != null) { return BASETESTDATA_ROOT_DIR + baseTestData.value(); } // TestDataResource クラスのフィールドに @BaseTestData アノテーションが付加されているかチェックする Field[] fields = description.getTestClass().getDeclaredFields(); for (Field field : fields) { if (field.getType().equals(TestDataResource.class)) { baseTestData = field.getAnnotation(BaseTestData.class); if (baseTestData != null) { return BASETESTDATA_ROOT_DIR + baseTestData.value(); } } } // テストクラスに @BaseTestData アノテーションが付加されているかチェックする Class<?> testClass = description.getTestClass(); baseTestData = testClass.getAnnotation(BaseTestData.class); if (baseTestData != null) { return BASETESTDATA_ROOT_DIR + baseTestData.value(); } return BASETESTDATA_DIR; } private void backupDb(IDatabaseConnection conn, String testDataBaseDir) throws DataSetException, IOException { QueryDataSet partialDataSet = new QueryDataSet(conn); // BASETESTDATA_DIR で指定されたディレクトリ内の table-ordering.txt に記述されたテーブル名一覧を取得し、 // バックアップテーブルとしてセットする List<String> backupTableList = Files.readAllLines(Paths.get(testDataBaseDir, "table-ordering.txt")); for (String backupTable : backupTableList) { partialDataSet.addTable(backupTable); } ReplacementDataSet replacementDatasetBackup = new ReplacementDataSet(partialDataSet); replacementDatasetBackup.addReplacementObject(null, DbUnitUtils.NULL_STRING); this.backupFile = File.createTempFile(BACKUP_FILE_NAME, "xml"); try (FileOutputStream fos = new FileOutputStream(this.backupFile)) { FlatXmlDataSet.write(replacementDatasetBackup, fos); } } private void restoreDb(IDatabaseConnection conn) throws MalformedURLException, DatabaseUnitException, SQLException { if (this.backupFile != null) { IDataSet dataSet = new FlatXmlDataSetBuilder().build(this.backupFile); ReplacementDataSet replacementDatasetRestore = new ReplacementDataSet(dataSet); replacementDatasetRestore.addReplacementObject(DbUnitUtils.NULL_STRING, null); DatabaseOperation.CLEAN_INSERT.execute(conn, replacementDatasetRestore); } } private void loadTestData(IDatabaseConnection conn, Description description) { description.getAnnotations().stream() .filter(annotation -> annotation instanceof TestDataList || annotation instanceof TestData) .forEach(annotation -> { if (annotation instanceof TestDataList) { TestDataList testDataList = (TestDataList) annotation; Arrays.asList(testDataList.value()).stream() .sorted(comparing(testData -> testData.order())) .forEach(testData -> testDataLoader.load(conn, TESTDATA_ROOT_DIR + testData.value())); } else { TestData testData = (TestData) annotation; testDataLoader.load(conn, TESTDATA_ROOT_DIR + testData.value()); } }); } }
- 定数 BASETESTDATA_ROOT_DIR, TESTDATA_ROOT_DIR を追加します。
TESTDATA_BASE_DIR
→BASETESTDATA_DIR
へ変更し、セットする値をBASETESTDATA_ROOT_DIR + "testdata/base"
へ変更します。- getBaseTestDir メソッドの以下の点を変更します。
- 途中3ヶ所の return 文で返す値を
baseTestData.value()
→BASETESTDATA_ROOT_DIR + baseTestData.value()
へ変更します。 - 最後の return 文で返す値を
TESTDATA_BASE_DIR
→BASETESTDATA_DIR
へ変更します。
- 途中3ヶ所の return 文で返す値を
- loadTestData メソッドの以下の点を変更します。
- 2ヶ所ある
testDataLoader.load(conn, testData.value());
→testDataLoader.load(conn, TESTDATA_ROOT_DIR + testData.value());
へ変更します。
- 2ヶ所ある
TestDataList.java
package ksbysample.common.test.rule.db; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Target({METHOD}) @Retention(RUNTIME) @Documented public @interface TestDataList { TestData[] value(); }
TestData.java
package ksbysample.common.test.rule.db; import java.lang.annotation.Documented; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Target({METHOD}) @Retention(RUNTIME) @Documented @Repeatable(TestDataList.class) public @interface TestData { long order() default 1; String value(); }
- @Target アノテーションの値の指定を {} で囲み、
ElementType.METHOD
を import static してMETHOD
に変更しました。 RetentionPolicy.RUNTIME
を static import してRUNTIME
に変更しました。@Documented
を追加しました。@Repeatable(TestDataList.class)
を追加しました。long order() default 1;
を追加しました。
web/confirmresult/testdata/001/lending_book.csv
lending_book_id,lending_app_id,isbn,book_name,lending_state,lending_app_flg,lending_app_reason,approval_result,approval_reason,version 521,105,978-4-7741-6366-6,GitHub実践入門,蔵書なし,[null],[null],[null],[null],1 522,105,978-4-7741-5377-3,JUnit実践入門,蔵書あり,1,開発で使用する為,2,購入済です,2 523,105,978-4-7973-8014-9,Java最強リファレンス,蔵書あり,,[null],[null],[null],1 524,105,978-4-7973-4778-4,アジャイルソフトウェア開発の奥義,蔵書あり,1,勉強の為,1,,2 525,105,978-4-87311-704-1,Javaによる関数型プログラミング,蔵書あり,1,勉強会の調査の為,1,,2
- lending_book_id の昇順に並び替えます。
履歴
2016/02/19
初版発行。