Skip to content

Commit

Permalink
Merge pull request #138 from mziyut/create-pull-request/patch-pull-ar…
Browse files Browse the repository at this point in the history
…ticles

Pull articles
  • Loading branch information
mziyut authored Oct 14, 2023
2 parents e83162a + 7ef2d4d commit f1576c3
Showing 1 changed file with 154 additions and 0 deletions.
154 changes: 154 additions & 0 deletions qiita/public/ccf2c58ae44c49a34b04.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
---
title: Dataform の Unit test で UNION ALL を書くのが辛くて JavaScript の wrapper を書いた話
tags:
- JavaScript
- SQL
- テスト
- sqlx
- Dataform
private: false
updated_at: '2023-10-13T18:41:54+09:00'
id: ccf2c58ae44c49a34b04
organization_url_name: qiita-inc
slide: false
ignorePublish: false
---

## はじめに

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

## Dataform の Unit test について

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

```sqlx:foo/example.sqlx
config {
type: "view",
name: "example_tables"
}
SELECT
id,
title
FROM
${ref("example_originals")}
```

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

```sqlx: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 ALL``join` するだけの簡単な処理です。

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

```js: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 ファイルから処理を呼び出す場合は以下のように記載します。

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

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

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

## 最後に

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

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

## References

https://docs.dataform.co/guides/tests

https://cloud.google.com/blog/ja/topics/data-warehousing/learn-how-to-use-the-dataform-cli-tool-to-unit-test-udfs?hl=ja

https://cloud.google.com/blog/topics/data-warehousing/learn-how-to-use-the-dataform-cli-tool-to-unit-test-udfs/

0 comments on commit f1576c3

Please sign in to comment.