【クラウド勤怠】爆発する組み合わせテストと真摯に向き合う

この記事について

こんにちは。「マネーフォワード クラウド勤怠」のエンジニアをしています katuo です。直近、自分が担当する新機能開発プロジェクトで影響範囲が広範囲でかつ複雑な条件が混ざり合うテスト設計が求められる場面がありました。その過程で苦しみながら得たテストケース作成の知見などを一部抜粋して本記事にて共有できればと思っております。

なお、業務の関係上、具体的なテスト対象の公開が難しいため、一部表記を控えさせていただいています。

combinatorial testing

テスト対象となる機能の1つにユーザーからの入力を受けて保存処理を行う機能のテストを実施する場面があり、combinatorial testing(組み合わせテスト)を用いてのテストケース作成を試みました。この機能をテストするにあたっての因子と水準を考えると、初期状態や操作などを合わせて、7つの因子で構成されており

exhuastive testing(全網羅テスト)をする場合、テストケース数が各水準の種類を掛け合わせた12960件になってしまうようなテストでした。広範囲でかつ複雑な条件が混ざり合うテスト設計が求められている状況において、限られたリソースで効果的で十分なテストを設計するかということを考慮した結果、必要性が低いと判断されるテストケースを削減する方針でテストケースを作成していくことにしました。

combinatorial testingの辛い箇所

全組み合わせの中からテストケースを削除するにあたって、100件くらいまでなら大きな負荷は掛からないのですが、これ以上の件数になってくると、どのテストケースを残して、どのテストケースを捨てるのかの判断が曖昧になり、難しくなってきます。数万件のテストケースに対して、事前に不要な組み合わせを捨てるといったことを実施したとしても、大抵の場合は組み合わせ数が爆発したままになってしまうことが殆どでしょう。

テスト工程に掛けられる人的リソースがある場合、exhuastive testingによる全組み合わせを実施するのが潜む全てのバグを発見するという観点では最も優れた選択肢であることは否定しようがない事実です。ですがこのような場合において、現実的なラインを考慮するとバグ1件を発見するまでに必要なテストケース数を少なくするということが取れる手段の1つになってきます。

pairwise testing

テストケース数が爆発してしまう場面などで、より効果的なテストケースを生成するためにブラックボックステスト設計技法の1つであるpairwise testingを用いることにしました。

概要だけ書くと、最低限2つの因子間での組み合わせに限っては全て網羅するようにテストの組み合わせを作るテスト技法です。(アルゴリズムの具体的な説明は今回の記事では省略します。厳密な定義は Pairwise Testing in Real World の「1. Background」記載されているので興味があればお読みください)

exhaustive testing と pairwise testing のテストケース数の推移

以下の図は「Pairwise Testing in Real World」に書かれている内容で、縦軸をテストケース数、横軸をテストの因子数として、ある条件下におけるExhaustive(全網羅)とPairwiseのそれぞれをプロットした図です。

出典: Pairwise Testing in Real World

Exhaustiveの場合、因子数が9, 10件を超えた辺りから縦軸のテストケース数が指数関数的に増えていることがわかります。一方、Pairwiseの場合は1次関数的に増加していることがわかります。このようにexhaustive testingを行った場合に発生してしまいがちなテストケース爆発をpairwise testingを使うことで抑制することができます。

PICT の活用

pairwise testingを作成するにあたってIBM社の Intelligent Test Case Handler (replaces CTS), Jenkins社の Jenny など数多くのツールがあります。今回はMicrosoft社によって公開されているオープンソースである PICT を利用しました。PICTをローカルで利用できるようにするためには公式リポジトリをcloneしてmakeするか、brew install pictなどを実行すればPICTのCLIが使えるようになります。

PICTの使い方は非常にシンプルで、以下のように各行に対して因子: 水準の種類を記述した任意の名前の.txtファイルを用意して

// ファイル名: combination.txt

初期状態_勤怠区分: 平日, 所定休日, 法定休日
初期状態_打刻: 手動打刻有, みなし打刻有, 打刻無
初期状態_勤務パターン: <省略>
初期状態_数値集計項目: <省略>

操作_打刻: 追加, 削除, 無操作
操作_勤務パターン: <省略>
操作_数値集計項目: <省略>

PICT CLIを実行すると、組み合わせ結果が標準出力で出力されるのでこれを任意の結果出力用の.txtファイルなどに書き出してあげれば良いです。

$ pict combination.txt > result.txt

素晴らしいことにPICTはユースケース的にありえない組み合わせを事前に除外するための条件付き制約が用意されています。例えば 初期状態_打刻みなし打刻有 または 打刻無 の場合に 操作_打刻削除を選択できないようにする禁則を設けたい場合は以下のようにifを使って記述することができます。

初期状態_勤怠区分: 平日, 所定休日, 法定休日
初期状態_打刻: 手動打刻有, みなし打刻有, 打刻無
初期状態_勤務パターン: <省略>
初期状態_数値集計項目: <省略>

操作_打刻: 追加, 削除, 無操作
操作_勤務パターン: <省略>
操作_数値集計項目: <省略>

# 制約
if [初期状態_打刻] in {"みなし打刻有","打刻無"} then [操作_打刻] <> "削除";

他にも詳しい使い方が公式リポジトリに記載されているので、実際に使用する場合はこちらをご覧ください。

Google Spread Sheet の活用

PICTによって生成されたテストケースの組み合わせ表をスプレッドシートを使って半自動的に表示する方法の一例を簡単に紹介します。

生成される組み合わせ表は次のシートのようになります。

上のシートは以下のPICTの出力貼り付け用シートの値を元に生成される仕組みになっています。

具体的には組み合わせ表の◯が入る可能性がある領域に対して、PICTの出力貼り付け用シートと水準を比較した時に合致していれば◯を自動入力するというスプレッドシートの関数が挿入されており、PICTで生成された結果を出力貼り付け用シートにペーストすると、◯が自動で入力される仕組みになっています。1点困った箇所がありまして、PICTによって生成されるテストケースのアウトプットは各行に対して出力されるので、自分の書いた各列に対してテストケースの組み合わせを表示するフォーマットに合わなかったのですが、シート内で「右クリック→特殊貼り付け→転置して貼り付け」で転置してからペーストすることで解決しました。

このようにしてPICTによって生成される水準の組み合わせを可視化することで、ユースケース的にテストしたいと思っていた水準の組み合わせがpairwiseによって網羅されているのかなどを把握しやすくなります。最後にこの組み合わせ表を使って、以下のような実際の値が入ったテストケースを作成します。(以下の画像は実際に使用したテストケースの一部です)

pairwise testing を活用してみた感想

良かったこと

1つ目: exhuastive testingでは12960件だったテストケース数を、条件付き制約などを加えたpairwise testingで33件にテストケース数を削減することができ、これによりテスト実施工程の工数を大幅に削減することができました。

2つ目: 従来のexhuastive testingから手動でテストケースを削除するやり方と比べて大幅にテスト作成コストを削減することができました。これは因子/水準が多くテストケース数が爆発してしまう時にどのテストケースを捨てて、どのテストケースを残すのかを人間が判断する部分を機械的に決定できるようになったことが大きいと思っています。

3つ目: テストケースを作成するときの精神的な負荷を軽減できました。組み合わせが爆発する因子/水準におけるテストケースを削る工程において、バグが潜んでいることを否定できないテストケースを大量に削除するのはかなり精神的な負担がかかります。またテストケース数が爆発しているテストのテストケースを削除する工程はそもそも工数が非常にかかるので、この辛い時間を減らせたのも大きかった印象です。

4つ目: テスト全体を通してpariwise testingで生成したテストケースよって、仕様の考慮漏れやバグをテストで発見することができました。仕様の考慮漏れは非人為的に水準の組み合わせがPICTによって生成されたことにより見つかった印象が強いです。

イマイチだったこと

1つ目: pairwise testingだけでは機能のユースケース的な観点から重要だと思われる水準の組み合わせを必ず網羅してくれるとは限らなかったです。pairwise testingによって生成されたテストを組み合わせ表のテストから見た時に、ある水準同士の組み合わせのテストケースは用意したいと思う場面が多々あり、この場合はpairwise testingとは別に手動でテストケースを追加することで対応しました。一般的に言われる「テストケース数を減らせる魔法の手法ではない」といわれるものを体感しました。

2つ目: 仕様変更や各因子の水準同士の組み合わせで存在しないパターンなどが見つかった場合、PICTで生成したpairwise testingのテストケースをもう一度作り直さないといけなかったことです。これはPICTのインプットを変更するとpariwise testingによって生成されるテストケースがガラリと変わってしまう仕様に起因します。この場合は、上で紹介したスプレッドシートの組み合わせ表を元に具体的な値が入ったテストケースを作成する前に、ありえないケースが存在しないかを事前に確認することでなるべく手戻りがなくなるように工夫したりしました。

最後に

今回、自分が担当した新機能開発において、全ての画面や機能に対して合計何百件テストケース作成しました。正直な所、普段アプリケーションエンジニアとして活動する自分にとって今回のような大規模なテストケース作成にあたって精神的にかなり苦しみましたが、1つ1つのテストに対して真摯に向き合い、今回のようにpariwise testingであったり新しいテスト技法の知見も獲得できました。テスト作成に掛けられる工数やテスト対象によって実施するべきテストの形は大きく変化するので、これからもしっかりとテストと向き合っていこうと思います。

宣伝ですが「Scrum Fest Niigata 2022 Day 2」にスピーカーとして登壇するので良かったら、良かったらご覧ください!

参考文献


マネーフォワードでは、エンジニアを募集しています。
ご応募お待ちしています。

【会社情報】
Wantedly
株式会社マネーフォワード
福岡開発拠点
関西開発拠点(大阪/京都)

【SNS】
マネーフォワード公式note
Twitter – 【公式】マネーフォワード
Twitter – Money Forward Developers
connpass – マネーフォワード
YouTube – Money Forward Developers

Pocket