2
1

More than 1 year has passed since last update.

KarateのテストでDBUnitを使ってDBにテストデータを入れる

Posted at

はじめに

Javaのテストフレームワークの中にKarateというものがあります。
E2Eのテスト自動化ツールで、レポートなども生成してくれて、非常に便利なのですが、テストデータの作成が中々にめんどくさい。
Javaのコードをテスト内で実行できるので、それでORMみたいなものを作ってデータの作成もできるんですが、クラスを作ったらいちいちそっちも作ったり、修正したらメンテしたりとめんどくさいです。

そこで便利なのが、DBUnitです。
XML形式でデータを定義し、あとは流すだけでデータを作ってくれます。
また、XMLの内部で識別用の文字列をセットしておいて、後で任意の値に置換することで変数の入れ込みも行えます。

コード

以下が該当のテストコードです。

Feature: テスト
  Background:
    * def dbunit = Java.type('integration.util.DBUnitController')
    * def uuid = Java.type('java.util.UUID')
    * text originalData =
    """
      <?xml version="1.0" encoding="UTF-8"?>
      <dataset>
        <TEST ID="<id>" NAME="テスト" />
      </dataset>
    """
  Scenario: テスト1

    * copy data = originalData
    * def id = uuid.randomUUID().toString()
    * replace data
      | token        | value                                   |
      | id           | id                                      |
    * print data
    * dbunit.refresh(data)

    Given url 'http://localhost:9080/api/test?id=' + id
    And header Accept = 'application/json'
    When method get
    Then status 200
    And match response.test.id = id

また、dbunitのコードはDBUnitController.java に書かれています。
以下が該当のコードです。

public class DBUnitController {
  private static final String schema = "xxx";
  private static final String username = "xxx";
  private static final String password = "xxx";
  private static final String url = "xxx";
  private static final String driverClassName = "xxx";
  private static IDatabaseConnection conn;

  static {
    try {
      conn =
          new JdbcDatabaseTester(driverClassName, url, username, password, schema).getConnection();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static void refresh(String content) throws Exception {
    try {
      String filename = saveFile(content);
      DatabaseOperation.REFRESH.execute(conn, getDataSet(filename));
    } catch (Exception e) {
      e.printStackTrace();
      throw e;
    }
  }

  private static IDataSet getDataSet(String filename) throws Exception {
    FlatXmlDataSet dataSet = new FlatXmlDataSetBuilder().build(new File(filename));

    ReplacementDataSet replacementDataSet = new ReplacementDataSet(dataSet);
    replacementDataSet.addReplacementObject("[null]", null);
    replacementDataSet.addReplacementObject("[uuid]", UUID.randomUUID().toString());
    replacementDataSet.addReplacementObject(
        "[current_timestamp]",
        LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.000")));
    return replacementDataSet;
  }

  private static String saveFile(String content) throws Exception {
    Path path = Files.createTempFile("dbunit-", ".xml");
    File file = path.toFile();
    Files.write(path, content.getBytes(StandardCharsets.UTF_8));
    file.deleteOnExit();
    return file.getAbsolutePath();
  }
}

コード自体はかなり単純で、テーブルのスキーマにデータを定義して、それをDBUnitに渡して保存してもらっているだけです。

karateでは、xmlに <id> のような形でデータの部分に定義しておけば、replaceという宣言で、token に合致するものを value の値に置換してくれます。
上で示したテストコードのように、変数を入れ込むことができるので非常に便利です。

また、私のプロジェクトでは、DBUnitController.javagetDataSet メソッドの中で、文字列を予約しています。
このように予約しておけば、わざわざxmlで書かなくても、[uuid] などと書くだけで、uuidに変換してくれます。
こういった拡張は好きなだけできると思います。

是非試してみてください。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1