はじめに
こんにちは!
株式会社LegalOn TechnologiesのSET(Software Engineer in Test)のhikimochiです。普段は自動テストの推進やQA横断の施策を実施しています。
LegalOn Technologiesでは昨年、企業における法務業務を包括的にサポートするAI法務プラットフォーム「LegalOn Cloud」をリリースしました。
リリース後、様々な機能追加が行われる中、弊社の他製品で契約書の内容を自動レビューするAIレビューサービスの「LegalForce」、AI契約管理システムの「LegalForceキャビネ」からのデータ移行を行うための機能開発が行われました。
本投稿では、データ移行機能のテストアプローチとしてデータベーステストを行った件と、リリース後の運用に関連するテスト事例をご紹介します。
背景
データ移行機能は「LegalForce」、「LegalForceキャビネ」からデータを「LegalOn Cloud」に移動し、そのデータを用いてアプリケーションを利用できるようにするものです。
しかし、「LegalOn Cloud」の仕様を踏まえると、ただ単純にデータを移行するだけでは問題があり、以下を考慮する必要がありました。
- 移行元のアプリケーション「LegalForce」、「LegalForceキャビネ」のデータベースの型、制約
- 移行先のアプリケーション「LegalOn Cloud」のデータベースの型、制約
- 移行元のアプリケーションにおける業務上の制約
- 移行先のアプリケーションにおける業務上の制約
特に移行先のアプリケーション側の制約が強い場合、単純にデータを移行することはできないので注意する必要があります。
例えば、仮にある値が移行前のデータベースにおいてVARCHAR(100)で管理されており、移行後のカラムではVARCHAR(90)で管理する必要があった場合、そのまま移行を行うことはできず90文字に丸めを行うか、制約を変更するなどの対応を取る必要が出てきます。
業務上の制約については、例えば仮に移行前のアプリケーションで管理できるユーザー数が100で、移行先のアプリケーションで管理できるユーザー数が90だった場合に全てのユーザーは移行できないことになります。これもアプリケーションの仕様変更をするか、データ移行仕様側でどのように移行するかを考える必要が出てきます。
また、データ移行してもサーバー側で利用されるのみで、UI上には現れないデータもあるため、そのようなものも含め包括的に確認する方法としてデータベーステストを実施しようと考えました。

データ項目移行表の作成
本データベーステストにおいてテストベースとなるものは何になるでしょうか?
どのデータがどのような移行仕様でどこにデータ移行されるのかが分かる資料が必要になります。
当初は、開発者が作成したデータ移行の仕様書しか存在せず、QAやプロダクトマネージャーにとって、データベースの制約、業務上の制約を満たしているか、そのデータ移行仕様で問題ないかの判断が難しい状態でした。
そのため、どのデータがどのような移行仕様でどこにデータ移行されるかがテーブル、カラム単位で把握できるデータ項目移行表の作成と、それを用いた仕様確認を行う必要がありました。
作成したデータ項目移行表のイメージと例です。
データベースのテーブル、カラムの対応付けを行い、データベースの制約、業務上の制約により、移行仕様を決めるという形を取りました。
移行仕様はQA、開発者、プロダクトマネージャーで行った仕様確認会により決定しました。仕様確認会では以下の点を確認しました。
- その移行仕様で問題ないか、抜け漏れはないか
- プロダクト側の仕様変更を行う必要があるか
- (移行仕様が許容できない場合、)制約の変更が必要か
データ項目移行表が完成したことで、職種問わず移行仕様を確認できるようになりました。
データベーステスト
データ項目移行表により移行仕様は決まったので、次はこの仕様を元にテストを設計していきます。
データベーステストのテスト対象は以下の図の赤色の部分になります。
見ての通りアプリケーションはテスト対象に含まず、純粋にデータベースとデータ移行ツールがテスト対象になります。
実際は、より複雑なものですが簡略化して表現しています。

テストプロセスごとに詳しく説明していきます。
テスト分析
データ移行仕様を確認すると項目ごとにいくつかのパターンに分けられることが見えてきたため、各パターンに応じてテスト設計方針を決めました。
テスト設計
各項目ごとにどのパターンになるかを確認し、用意すべきテストデータを考えていきます。
変換が行われる項目は境界値分析を行い、条件分岐が発生する項目についてはディシジョンテーブルを作成し各パターンを網羅するような値を利用します。
成果物の例としては以下のようなものになります。

テストデータ作成
テスト設計した内容に基づき移行元のアプリケーションである「LegalForce」、「LegalForceキャビネ」にテストデータを作成していきます。
基本的にはUIから作成しますが、UI上からは再現できないテストデータについてはデータベースを直接操作して値を入れていきました。
テスト実施
移行処理を行った後に移行先のデータベース内の値が期待値と相違ないかを確認していきます。
テスト実施結果
結果として20件ほどのバグを検知することができました。全バグ数のうち**8割**が本データベーステストのものでした。
データ移行機能なので、データベースレベルで検知できる数は多くなるのは当たり前と言えば当たり前ではありますが、UIに現れず通常のアプリケーション操作では見つけられなかったであろうデータ整合性に関する問題など、影響が大きいバグも含めて見つけられたことは大きな成果でした。
運用について
テストも無事に終わり、データ移行ツールのリリースが完了したあとも、「LegalOn Cloud」では日々新しい機能が次々とリリースされています。
これにより、「LegalOn Cloud」のデータベーススキーマや業務上の制約条件が変わることがあります。この仕様変更に気づかずデータ移行を行ってしまうと障害につながるため、データ移行ツールは仕様変更に追従していく必要があります。
そこで仕様変更検知のための仕組みとして「**ガードレールテスト**」というテストを考えました。これは意図せずデータ移行が失敗することを防ぐ意味を込めた造語です。テスト環境にて定期的にこのテストを動かすことで、本番環境へのバグの流出を防ぐ狙いがあります。
ガードレールテスト
ガードレールテストは3つのテストから成り立ちます。
- データベーステスト
- データベースメタデータテスト
- APIテスト
それぞれ分けて説明します。
データベーステスト
データベーステストは本ブログ前半で紹介したデータベーステストと全く同じです。ただし、毎回手動で確認すると費用対効果が合わないため自動化を考えました。本テストではDatabase Riderというツールを利用することにしました。
Database Riderを選定した理由は以下の通りです。
期待値をYAMLで表現できる
テスト実装は基本的にQAが行うため、普段開発を行わないメンバーでも実装できるようにしておく必要があります。Database RiderではYAMLで期待値を設定することができ、実装が容易です。
users: # テーブル名 # テストケース No.1 Taroが移行される(コメントも入れられる) - id: 1 name: "Taro" email: "test@example.com" created_at: "2023-01-23 00:00:00.000000" updated_at: "2023-01-23 00:00:00.000000" xxx_enabled: true
テーブルにレコードが含まれることを確認できる
データ移行先データベースのテーブルには移行対象以外のレコードも存在していますが、本テストの対象範囲はテーブル内に存在する移行対象のレコードのみです。そのため、テーブル全体の完全一致ではなく、特定のレコードが存在することを検証できる必要があります。
Database Riderのデフォルトでは完全一致による検証ですが、オプションで部分一致に変更することができます。
期待値として正規表現が利用できる
Database Riderでは期待値として正規表現が利用できるため、データ移行が終わらない限り期待値がわからないカラムに対しても期待値を指定することができます。ただしこれは検証を曖昧にしているとも言えるため、可能な限り期待値は実際の値を利用すべきです。
users: # テーブル名 # テストケース No.1 Taroが移行される(コメントも入れられる) - id: 1 name: "Taro" email: "test@example.com" created_at: "regex:^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}$" # データ移行した時刻が入る updated_at: "regex:^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}$" xxx_enabled: true
これらの工夫により、現状ではQAメンバーがテスト実装を行えるようになっています。
ツールでは対応できないもの
テストツールとしてDatabase Riderを紹介しましたが、いくつか対応しきれないパターンがありました。
暗号化された値
実際のレコードでは値が暗号化されて管理されるものがあります。これらは復号しなければ期待値との比較ができませんが、Database Riderにはそこまでの機能がないため自作する必要があります。
一意にレコードを特定できない場合
上記のusersの例ではidからレコードを一意に特定することができますが、idが移行後に採番されるなど移行されるまで値が確定しない場合があります。この場合期待値をあらかじめ設定できないため、移行前のidと移行後のidの変換テーブルを参照するなどして移行後のidを引っ張ってくる必要がありました。
このような操作もYAML上では表現できないので自作する必要があります。
レコード数を確認したい場合
特定の値ではレコード自体が生成されない場合や、データ移行仕様により特定の数のレコードしか作成されないような場合があり、このようなケースではレコード数のチェックが有効です。この場合もYAMLで表現することができないので自作する必要があります。
データベースメタデータテスト
データベースメタデータテストは、データベースのメタデータ(型、サイズ、制約など)を期待値と比較するテストです。
これによりスキーマに変更が加わった場合にテストが失敗し、スキーマ変更を検知できる仕組みになっています。
こちらは丁度良いツールが存在しなかったため自作していますが、Database Riderと同様YAMLで期待値を表現することができます。
tables: - name: users columns: - name: id type: int nullable: false primaryKey: true - name: name type: varchar nullable: false length: 100 - name: email type: varchar nullable: false length: 300 - name: created_at type: timestamp nullable: false - name: updated_at type: timestamp nullable: false - name: xxx_enabled type: boolean nullable: false
APIテスト
こちらはそのままAPIのテストです。データ移行後に主要なAPIを叩き、振る舞いが変わらないことを確認するテストです。APIの変更や、エラーを検知するためのテストになります。
まとめると以下のような形になります。
| テスト種別 | 目的 |
|---|---|
| データベーステスト | 期待通りにデータが移行されることを確認する |
| データベースメタデータテスト | データベーススキーマの変更を検知する |
| APIテスト | APIの振る舞いの変更を検知する |
定期実行
ユニットテストやAPIテスト、自動UIテストなどはPull Request上、デプロイ後など適切なテスト実行のタイミングがあります。
一方、「LegalOn Cloud」は複数のマイクロサービスで成り立っている性質上、各テストが失敗する可能性には様々なものが考えられるため、何をトリガーにするかの判断が難しいです。すべてのタイミングで実行するのにもコストがかかります。
そのため、毎日定期的に実行するという判断をとりました。
KubernetesのCronJobを利用することで定期実行を実現しています。
まとめ
本ブログではデータ移行に対するテストのアプローチとして、データベーステストを紹介しました。
そして今後の運用も見据えたテストとしてガードレールテストというものを提案し紹介しました。
データ移行など、データベースを中心としたテストを考える際に本記事が参考になれば幸いです。
謝辞
これらのテストを一緒に推進して頂いた島根(@shimashima35)さん、Xiaoさん、本ブログのレビューをして頂いた岡登さん、時武さん、ありがとうございました。
仲間募集
LegalOn Technologiesでは共に働く仲間を募集しています!
ご興味がある方は、以下のサイトからぜひご応募ください。皆様のご応募をお待ちしております。
https://herp.careers/v1/legalforce/q1UxYv1m5lDdherp.careers
https://herp.careers/v1/legalforce/7wXZUA5pCvTKherp.careers