LoginSignup
7
2

Dataform の Unit test で UNION ALL を書くのが辛くて JavaScript の wrapper を書いた話

Last updated at Posted at 2023-10-13

はじめに

Dataform には unit test を記述出来ます。
ただし、テストに用いるデータは SQL で書く必要があり冗長なものになりがちです。
Dataform は JavaScript を記述、読込みできるので wrapper を書きました。

Dataform の Unit test について

Dataform の Unit test はこのように記述できます。
example_originals table からデータを参照する example.sqlx があったとします。

foo/example.sqlx
config {
  type: "view",
  name: "example_tables"
}

SELECT
  id,
  title
FROM
  ${ref("example_originals")}

この example.sqlx に対する Unit test を用意すると以下のようになります。

foo/test_example.sqlx
config {
  type: "test",
  dataset: "example_tables"
}

SELECT
  1 AS id,
  "title1" AS title
UNION ALL
SELECT
  2 AS id,
  "title2" AS title
UNION ALL
SELECT
  3 AS id,
  "title3" AS title

input "example_originals" {
  SELECT
    1 AS id,
    "title1" AS title
  UNION ALL
  SELECT
    2 AS id,
    "title2" AS title
  UNION ALL
  SELECT
    3 AS id,
    "title3" AS title
}

test データを用意したいだけですが、 UNION ALL を何度も記載する必要があります。
面倒ですし、可読性も悪い状態になってしまいます。

苦し紛れではありますが、JavaScript を用いて UNION ALL のラッパー関数を作成しました。

JavaScript の wrapper を書いた

Dataform は includes 以下の ディレクトリに JavaScript ファイルを置くことで、
SQLX 内から JavaScript に記載した処理を呼び出すことができます。

作成した JavaScript はこちらです。
渡されたデータを UNION ALLjoin するだけの簡単な処理です。

エスケープ処理等いくつか省略しています。

includes/sql.js
function build(data) {
  if (data.length === 0) {
    return "";
  }

  const keys = Object.keys(data[0]);
  return data.map((item) => {
    const values = keys.map((key) => {
      if (typeof item[key] !== "string") {
        return `${item[key]} AS ${key}`;
      }
      return `'${item[key]}' AS ${key}`;
    });

    return `SELECT ${values.join(", ")}`;
  }).join(" UNION ALL ");
}

module.exports = {
  build,
};

SQLX ファイルから処理を呼び出す場合は以下のように記載します。

foo/bar.sqlx
${
  sql.build([
    { id: 1, title: "title1" },
    { id: 2, title: "title2" }
  ])
}

すると以下のような SQL に変換します。

SELECT
  1 as id,
  "title1" as title
UNION ALL
SELECT
  2 as id,
  "title2" as title

最後に

今回記事を書くために記載したテストデータの件数は3件程でした。
Dataform で処理するデータ次第ですが、テストデータの件数はもっと多くなるはず。

ちょっとした JavaScript を書くだけで、すこしメンテナンスしやすなります。
いい塩梅が求められる部分なので、やり過ぎは禁物です。

References

7
2
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
7
2