桜技録

🐈🐈🐈🐈🐘

dbsetup-csv: DbSetupでCSVデータを投入する

Javaユニットテストにて自動でテストデータをデータベースへ投入する為のツールとしてはDbSetupDBUnitをしばしば使っている。

ここ数年はコードの中でそのテストケースの確認に必要なデータを明示的に記述できるDbSetupの方を推しているのだが、カラム数の多いテーブルにデータをセットする場合は可読性が頗る悪くなってしまいテストデータをCSVExcelに記載するDBUnitが懐かしくなる。

とはいえ2つのツールを1つのプロジェクトに詰めるのも気持ち悪く、CSVを読んでDbSetupのInsertオペレーションにマップするスニペットを書いて使いまわしていたのだが流石にコピペを繰り返すのが阿呆臭くなってきたのでリライトしてパッケージとして公開することにした。

github.com

インストール

Maven Centralで公開中。GradleとMavenの例。

dependencies {
  testImplementation 'com.ninja-squad:DbSetup:2.1.0' 
  testImplementation 'com.sciencesakura:dbsetup-csv:0.0.1'
}
<dependency>
  <groupId>com.ninja-squad</groupId>
  <artifactId>DbSetup</artifactId>
  <version>2.1.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>com.sciencesakura</groupId>
  <artifactId>dbsetup-csv</artifactId>
  <version>0.0.1</version>
  <scope>test</scope>
</dependency>

使い方

投入するデータファイルはクラスパス配下となる場所に置くこと。GradleやMavenを使っているのなら通常 src/test/resources より下に置く。

以下は m_user テーブルをtruncateして src/test/resources/data/m_user.csv を同テーブルにインポートする例。

import com.ninja_squad.dbsetup.DbSetup;
import com.ninja_squad.dbsetup.DbSetupTracker;
import com.ninja_squad.dbsetup.destination.Destination;
import com.ninja_squad.dbsetup.operation.Operation;
import org.junit.jupiter.api.BeforeEach;

import static com.ninja_squad.dbsetup.Operations.sequenceOf;
import static com.ninja_squad.dbsetup.Operations.truncate;
import static com.sciencesakura.dbsetup.csv.Import.csv;

class Sample {

    private static final DbSetupTracker dbSetupTracker = new DbSetupTracker();

    private Destination destination;

    @BeforeEach
    void setUp() {
        Operation operation = sequenceOf(
            truncate("m_user"),
            csv("data/m_user.csv").into("m_user").build()
        );
        DbSetup dbSetup = new DbSetup(destination, operation);
        dbSetupTracker.launchIfNecessary(dbSetup);
    }
}

特に何も指定しなければデータファイルはUTF-8でカンマ区切り、フィールドの囲み文字*1は二重引用符、最初の1行はヘッダと見做され、空文字はnullと評価される。

これらは以下のようにカスタマイズ可能。

csv("data/m_user.csv").into("m_user")
    // エンコーディングを指定
    .withCharset("ms932")
    // 区切り文字を指定
    .withDelimiter('\t')
    // 囲み文字を指定
    .withQuote('\'')
    // ヘッダを指定 (ファイルの1行目からデータとして扱う)
    .withHeader("id", "user_no", "user_name", "email_address", "tel_no")
    // nullと評価する文字列を指定
    .withNullAs("[null]")
    .build();

なるべく生のDbSetupで

とまあ自作のツールを紹介したけれども初めに書いた通りDbSetupを使う良さはテストコードとテストデータを近い位置に記述させることだと考えているので、それを壊し得るこのツールの使い所はなるべく絞っていきたい。

目安としては生の Operations#insertInto を使って1レコード分の values(String...) に折り返しが発生してしまうようならこのツールの出番だろうか。

【追記】Excel版も作った。

github.com

*1:区切り文字を含む値や空白のみの値を表す場合は必須、それ以外の場合はオプション