blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2025.03.27 技術記事

DeSCデータベースの品質を支える2つのテスト - 機能テストとデータテストの実践

by Kaito Tawara

#data-engineering #dbt #データ品質 #test

はじめに

こんにちは、DeSCヘルスケア製品開発統括部データプラットフォーム開発部の俵です。

以前『Redshift Serverless + dbtでデータ品質テストを100倍高速化した話』について紹介しました。

今回はより包括的なデータの品質管理の取り組みを紹介します。

DeSCデータベースの品質を支える2つのテスト

DeSCヘルスケアではDeSCデータベースの作成および提供を行っています。 DeSCデータベースは、匿名化されたレセプトデータなどで構成される大規模なリアルワールドデータベースです。 私が所属するデータプラットフォーム開発部はDeSCデータベースの作成を担っており、 その品質を管理することも重要な使命の1つです。

DeSCデータベースは毎月の計画に沿って作成されており、データ量の合計は25年3月時点で10TBを超えます。 また、DeSCデータベースを作成する基盤システムをデータプラットフォームとよび、データプラットフォームは複数のサブシステムから構成されます。 そのため、複数のサブシステムにまたがる大量のデータの品質をいかに正確かつ効率的に管理するかが我々の重要な課題です。

DeSCデータベースの品質を管理する上で重要な取り組みとして、機能テストデータテストを紹介します。

機能テスト

機能テストは、DeSCデータベースを作成するプログラム(データ変換プログラム)が仕様通りに動作することを確認するブラックボックステストです1。 機能テストは以下の流れで実施します。

  1. テスト用の入力データとそれに対応する期待出力データを用意します。
  2. 用意した入力データに対して開発環境でデータ変換プログラムを実行し、実際の出力データを取得します。
  3. 実際の出力データと期待出力データが一致することを確認します。

機能テストの概要

機能テストの概要

プログラムの動作を確認するテストとしては、他にユニットテスト(単体テスト)があります。 機能テストはユニットテストと比較して、入力データから出力データまでの一連の処理をエンドツーエンドで検証するため、 プログラム全体の整合性を確認できるというメリットがあります。 また、機能テストはプログラムの変更による影響を検証するリグレッションテスト(回帰テスト)としても機能し、 既存の動作が意図せず変更されていないことを確認する役割も果たします。

設計と実装

機能テストの設計と実装は、テスト対象となるデータ変換プログラムの仕様に大きく左右されます。 そのため、統一的な手法を適用するのが難しい場合もありますが、基本的には以下の流れで進めます。

  1. テスト観点の洗い出し
    • データ変換プログラムの入出力およびデータ変換仕様は、外部仕様書として定義しているため、それに基づいてテスト観点を洗い出します。
    • テスト観点は、データ変換プログラムの処理の複雑さに応じて多岐にわたります。そのため、まずは基本的で重要な観点を洗い出し、その後必要に応じて拡充していくと効率的です。
  2. テストデータの設計
    • テスト観点に対応するテストデータを設計し、スプレッドシートなどのドキュメントにまとめます。ドキュメント化することで、機能テストが失敗した際の原因の特定がスムーズになり、また関係者間でテストに対する共通認識を持つことができます。
  3. 機能テストの実装
    • 実際の出力データと期待出力データの比較方法は、出力形式によって異なります。出力形式がCSVなどのファイルであれば diff コマンド、データベースのテーブルであればSQLの EXCEPT などを使用することが考えられます。また、データ変換プログラムがdbtで実装されている場合は、 Unit tests の使用も検討できます。
  4. 機能テストの実行
    • 機能テストは、Dockerコンテナ上で実行することで、ローカル環境での実行やCI2への組み込みが容易になります。これにより、機能テスト自体やデータ変換プログラムの開発効率が向上します。

機能テストでは、適切な品質を確保しながら効率的に運用することが重要です。 とくに、テストデータの作成には多くの手作業が伴うため、工数や精度に課題があります。 こちらについては現在、プロセスの解釈性を確保しつつ、AIを活用した効率化を進めています。

データテスト

データテストは、データ変換プログラムの入出力データが仕様通りであることを確認するテストです。 データ品質テストともよびます。 我々が扱うデータは、先行する業務やシステムの影響で、想定した仕様とは異なるデータが発生する場合があります。 こうしたデータの異常を検知し、適切に対処するために、データテストは非常に重要です。 データテストの概要や実装例については 前回の記事 をご覧ください。

dbtの活用

我々は基本的にデータテストを dbt Data tests で実装しています。 とくに Generic data tests やそれを自作する Custom generic data tests を使用することでデータテストの実装量を大幅に削減できます。

また、dbtは elementary dbt-osmosis といった周辺ツールが非常に充実していることも特徴の1つです。

elementaryはデータテストの結果をダッシュボード形式で可視化・レポーティングするツールです。 レポートを確認することでデータテストの結果が一目で分かり、失敗した場合はその原因となるテストやデータを容易に特定できます。 他にもdbt単体では検知が難しいデータの異常検知や、レポートをSlackやAWS S3に送信する機能などがあります。 elementaryの詳細については こちらの記事 をご覧ください。

dbt-osmosisはdbtのモデルのメタデータ(YAML)管理を効率化するツールです。 dbtはデータテストの設定情報をYAMLファイルに記述します。 DeSCデータベースを構成するテーブルにはカラム数が数百になるものも存在するため、YAMLファイルの記述は膨大になります。 dbt-osmosisはこのYAMLファイルの作成を自動化・効率化するため、データテストの作成を効率化できます。

dbtにはelementaryやdbt-osmosisを含めさまざまな周辺ツールが存在し、その充実度はますます増しています。 我々はこれらdbtのエコシステムを最大限活用し、データテストならびにデータプラットフォーム全体の最適化に取り組んでいます。

機能テストとデータテストの違いと補完関係

機能テストとデータテストは共にDeSCデータベースの品質を管理する上で欠かせない重要なテストです。

ここで両テストの違いを表にまとめました。

機能テスト データテスト
目的 データ変換プログラムの品質確認 データの品質確認
実行フェーズ 開発時 本番運用時
実行環境 開発環境 本番環境
使用するデータ テストデータ 本番データ
検知できる異常 プログラムの異常 データまたはプログラムの異常

機能テストとデータテストで実行するフェーズや環境、使用するデータなどの違いがありますが、 一言で表すとプログラムに焦点を当てたのが機能テストデータに焦点を当てたのがデータテストです。 機能テストだけでは本番運用時にデータの異常を検知できませんし、 データテストだけでは開発時にプログラムの異常を検知できません。 両テストを組み合わせることでプログラムとデータの両面から品質を管理できます。

続いて我々のデータプラットフォームにおける機能テストとデータテストの関係を図にしました。

データプラットフォームにおける機能テストとデータテストの関係

データプラットフォームにおける機能テストとデータテストの関係

データプラットフォームは複数のサブシステム(データ変換プログラムとデータテスト)から構成されており、 各データ変換プログラムに対して機能テストを実施しています。 このように多段階でテストを実施することでプログラムやデータの異常を早期に検知できます。 異常を早期に検知することで原因の特定が容易になり、手戻りが減少するため修正コストを低く抑えることができます。 これはソフトウェア開発におけるシフトレフトとよばれる考え方と同様です。

テストと開発効率の関係性

機能テストとデータテストに加えて、各サブシステムにおけるユニットテストや変更に対するコードレビューを徹底することで多層的に品質を管理しています。 このようにテストを拡充することは、DeSCデータベースの品質を向上するだけでなく、以下の点から開発効率を向上します。

1. バグの早期検知による修正コストの削減
プログラムの変更にバグはつきものです。 その変更が複雑かつ影響範囲が広い場合はなおさらです。 バグを出さないのが理想ですが、バグを早期に検知することで修正コストを低く抑えることができます。 ユニットテストや機能テストが拡充されていれば開発時の段階でバグを検知し修正できます。 また、もし開発時にバグを検知できなかったとしても、データテストが拡充されていれば本番運用時のより早い段階でバグを検知し修正することで手戻りを減らせます。 手戻りが減ることでエンジニアはより生産的な開発業務に取り組むことができます。

2. 属人性の排除
自身が熟知していないプログラムの変更は難しく不安なものです。 そのプログラムにドキュメントやテストコードがない場合はなおさらです。 たとえプログラムのコードを読んで処理を理解したとしても、変更に対する不安がつきまといます。 しかし、テストコードは一種のドキュメントとして機能するためプログラムの理解を助けます。 また、テストが通ることで安心感が得られ、積極的に機能変更やリファクタリングに取り組むことができます。 このように属人性を排除し、チーム開発を効率的に行えるという点でもテストの拡充が重要です。

上で述べたように、テストの拡充は開発効率を向上しますが、過度なテストには注意が必要です。 基本的にテストはメンテナンスし続ける必要があり、怠るとすぐに形骸化してしまいます。 そのため、過度で冗長なテストはメンテナンスコストを増加させ、開発速度を低下させる要因となります。 また、我々のように大規模なデータを扱う場合はデータテストにおける計算資源の消費も課題となります。 大規模なデータのテストにはそれに応じた計算資源が必要となるため、その速度や費用が課題となる場合があります。 したがって、期待する品質に対して過不足のないテストを設計することが重要です。 データテストにおける速度や費用改善の具体例については 前回の記事 をご覧ください。

まとめ

DeSCデータベースの品質を管理する上で重要な取り組みとして、機能テストとデータテストがあります。 機能テストはデータ変換プログラムの品質を確認するためのテストであり、 データテストはデータ変換プログラムの入出力データの品質を確認するためのテストです。 両テストを組み合わせることでプログラムとデータの両面から品質を管理できます。 また、テストを拡充することはバグの早期検知や属人性排除の点で開発効率の向上につながります。 ただし、過度で冗長なテストはメンテナンスコストの増加や処理性能の課題を引き起こす要因となるため、 期待する品質に対して適切なテストを設計することが重要です。

おわりに

本記事ではDeSCデータベースの品質を支える2つのテストとして、機能テストとデータテストを紹介しました。 今でこそ両テストはDeSCデータベースの品質管理において欠かすことのできない重要なテストですが、初めから整備されていたわけではありません。 テクニカルプロダクトマネージャー(TPM)を中心として部全体で品質管理に取り組み、地道に改善を重ねた結果だといえます。 引き続きテストの効率化・最適化に取り組み、DeSCデータベースの価値向上につなげていきます。


  1. 実際はデータテストに対する機能テストも存在しますが、本記事では割愛します ↩︎

  2. Continuous Integration:継続的インテグレーション ↩︎

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。