dbtで使用できる主なテスト


# dbtで使用できる主なテスト
dbtで使用できる主なテストは5つあります
1. シングルテスト（Singular Test）
2. ジェネリックテスト（Generic Test）
3. 単体テスト（Unit Test）
4. dbt-utilsを使用したテスト
5. dbt-expectationsを使用したテスト

:::note warn
筆者の知見内の記述になっています。他に行えるテストがあればコメントで教えていただけると幸いです
:::

---

## 1. Singular Test

### 概要
シングルテストは、個別のSQLクエリを使用して特定の条件を検証する**カスタムテスト**です。
`tests`ディレクトリ内に`.sql`ファイルとしてテストクエリを配置し、`dbt test`コマンドで実行できます。

https://docs.getdbt.com/docs/build/data-tests#singular-data-tests

### 使用例
```sql
-- tests/not_null_test.sql
SELECT *
FROM {{ ref('my_model') }}
WHERE column_name IS NULL
```

このテストクエリは、`my_model`の`column_name`にNULL値が存在しないことを確認しています。



---

## 2. ジェネリックテスト（Generic Test）

### 概要
ジェネリックテストは、`schema.yml`ファイル内でモデルやカラムに対する**一般的なテスト**を指します

https://docs.getdbt.com/docs/build/data-tests#generic-data-tests

dbtは以下の標準的なテストを提供しています

- **not_null**: 値がNULLでないことを確認
- **unique**: 値が一意であることを確認
- **accepted_values**: 指定した値のセットに収まることを確認
- **relationships**: 外部キーが存在することを確認

### 使用例

#### not_null
```yaml
columns:
  - name: column_name
    data_tests:
      - not_null
```

#### unique
```yaml
columns:
  - name: id
    data_tests:
      - unique
```

#### accepted_values
```yaml
columns:
  - name: status
    data_tests:
      - accepted_values:
          values: ['active', 'inactive']
```

#### relationships
```yaml
columns:
  - name: user_id
    data_tests:
      - relationships:
          to: ref('users')
          field: id
```

一つのカラムに複数のテストを適応させることもできます。
下記はsample_modelテーブルのuser_idカラムに`unique`, `not_null`, `accepted_values`, `relationships`のテストを適応させた例です。

```yaml
version: 2

models:
  - name: sample_model
    description: サンプルモデル
    columns:
      - name: user_id
        data_tests:
          - unique
          - not_null
          - accepted_values:
              values: ['1', '2', '3']
          - relationships:
              to: ref('users')
              field: id
```


---

## 3. 単体テスト（Unit Test）

### 概要
単体テストはdbt-core v1.8で導入されました。単体テストを使用することで、モデルの各部分が期待通りに動作していることを確認できます。

### 使用例
```yaml
models:
  - name: my_model
    unit_tests:
      - name: test_logic
        model: my_model
        given:
          - input: ref('users')
            rows:
              - {id: 1, user_email: 'example@example.com'}
        expect:
          rows:
            - {id: 1, domain: 'example.com'}
```

このテストは、user_emailカラムのメールアドレスがdomainカラムに意図した変換で入っているかを確認しています。

---

## 4. dbt-utilsを使用したテスト

### 概要
`dbt-utils`は、テストやモデル開発を支援する便利なマクロや関数を提供するパッケージです。これを活用することで、カスタムマクロを作成する手間を省き、複雑な条件を簡潔に記述できます。
2で記述したジェネリックテストはdbt-utilsでも実装できます。

https://hub.getdbt.com/dbt-labs/dbt_utils/latest/

### 使用例と説明
#### 1. **equal_rowcount**
- **説明**: 2つのテーブル間で行数が一致することを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.equal_rowcount:
      compare_model: ref('other_model')
```

---

#### 2. **fewer_rows_than**
- **説明**: あるテーブルの行数が、別のテーブルの行数より少ないことを検証します。
- **例**:
```yaml
tests:
  - dbt_utils.fewer_rows_than:
      compare_model: ref('other_model')
```

---

#### 3. **equality**
- **説明**: 2つのモデル間でデータが完全に一致することを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.equality:
      compare_model: ref('other_model')
```

---

#### 4. **expression_is_true**
- **説明**: SQL式がすべての行で`TRUE`になることを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.expression_is_true:
      expression: "col_a > col_b"
```

---

#### 5. **recency**
- **説明**: 日付列の最も新しい値が、現在時刻から一定時間以内であることを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.recency:
      datepart: day
      interval: 7
      field: updated_at
```

---

#### 6. **at_least_one**
- **説明**: テーブルに少なくとも1行のデータが存在することを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.at_least_one
```

---

#### 7. **not_constant**
- **説明**: 列の値が一定ではないことを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.not_constant:
      field: column_name
```

---

#### 8. **not_empty_string**
- **説明**: 列の値が空文字列ではないことを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.not_empty_string:
      field: column_name
```

---

#### 9. **cardinality_equality**
- **説明**: 2つの列の一意な値の数が一致することを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.cardinality_equality:
      field: column_a
      other_field: column_b
```

---

#### 10. **not_null_proportion**
- **説明**: NULL値の割合が指定した閾値以下であることを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.not_null_proportion:
      field: column_name
      threshold: 0.9
```

---

#### 11. **not_accepted_values**
- **説明**: 列の値が指定した値のいずれにも一致しないことを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.not_accepted_values:
      field: column_name
      values: ['invalid', 'unknown']
```

---

#### 12. **relationships_where**
- **説明**: 条件付きのリレーションシップをテストします。
- **例**:
```yaml
tests:
  - dbt_utils.relationships_where:
      to: ref('users')
      field: user_id
      where: "is_active = TRUE"
```

---

#### 13. **mutually_exclusive_ranges**
- **説明**: 2つの列の範囲が重複しないことを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.mutually_exclusive_ranges:
      field: start_date
      other_field: end_date
```

---

#### 14. **sequential_values**
- **説明**: 列の値が連続していることを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.sequential_values:
      field: id
```

---

#### 15. **unique_combination_of_columns**
- **説明**: 複数列の組み合わせが一意であることを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.unique_combination_of_columns:
      combination_of_columns: ['email', 'signup_date']
```

---

#### 16. **accepted_range**
- **説明**: 数値列が指定した範囲内であることを確認します。
- **例**:
```yaml
tests:
  - dbt_utils.accepted_range:
      field: age
      min_value: 0
      max_value: 120
```

---

## 5. dbt-expectationsを使用したテスト

### 概要
`dbt-expectations`は、データ検証ツールのGreat Expectationsの概念を取り入れたデータ品質テスト用ライブラリです。これを利用することで、より高度なデータ品質チェックを簡単に実装できます。

https://hub.getdbt.com/calogica/dbt_expectations/latest/

https://greatexpectations.io/

### 使用例と説明

#### 列の一意性を確認
```yaml
columns:
  - name: order_id
    data_tests:
      - expect_column_values_to_be_unique
```

#### NULL値が含まれていないことを確認
```yaml
columns:
  - name: customer_id
    data_tests:
      - expect_column_values_to_not_be_null
```

#### 値が特定セットに属していることを確認
```yaml
columns:
  - name: payment_status
    data_tests:
      - expect_column_values_to_be_in_set:
          value_set: ['paid', 'unpaid', 'pending']
```

#### 分布や統計量の確認
```yaml
columns:
  - name: order_total
    data_tests:
      - expect_column_mean_to_be_between:
          min_value: 50
          max_value: 500
```

---

## まとめ

dbtのテストは、プロジェクトの規模や要件に応じて使い分けることが重要です。

- **ジェネリックテスト**で基本的な品質を確保。
- **シングルテスト**や**dbt-utils**、**dbt-expectations**を活用して詳細な検証を実行。

---