PICTを使った効率的な網羅テストについて
※この記事は Wantedly から移行したものです。
初めに
皆さんこんにちは。バックエンドエンジニアとしてLinc’wellで働いている山本和久です。カズさんって呼んでくださいね。
さて、今回は私が好きなテスト用ツール「PICT」についてご紹介したいと思います。皆さんテスト用ツールと聞いてどのようなものを思い浮かべますか?RSpecのようなテストフレームワークもありますし、CircleCIのような継続的インテグレーションツールを思い浮かべる方も多いと思います。
「PICT」はペアワイズ法による効率の良いテストパターンの作成を支援するツールと言えます。
網羅的なテストとは
御存知の通り現在の開発現場ではテストをコードで記述して、アプリケーションの改修に伴う退行を防止したり、複雑なビジネスロジックの安全性を担保しています。
そういったシーンで欠かせないのがテストの網羅性です。
プログラムのバグが発生した場合、多くの原因はテストの漏れにあります。テストの漏れはどうして発生するのでしょうか。まずテストの網羅性を語る上で重要な4つの要素について考えてみましょう。
- 因子
- 項目名
- 水準
- 項目の値
- 組み合わせ
- 項目ごとの組み合わせ
- 期待値
- 期待する結果
例えば、クリニック受診前のオンラインアンケートを例に取ると次のような因子と水準が考えられます。(注意:実際のサービスで利用されているアンケートとは異なります)
因子 | 水準 |
---|---|
性別 | 男/女 |
咳 | ある/なし |
喉の痛み | ある/なし |
吐き気 | ある/なし |
味覚障害 | ある/なし |
妊娠 | 妊娠中/なし |
この因子と水準を満たす全てのテストパターンを考えると、水準が2の因子が6つあるので、2^6 = 64通りにもなってしまいます。
さて、テストパターンがなぜ漏れてしまうかの話に戻るのですが、因子と水準が正しく洗い出せていない、もしくは洗い出せていたとしても量が多いため有効な組み合わせで十分テストができていないという点があると考えられます。
前置きが長くなりましたが、PICTを使えば有効な組み合わせで網羅テストを行うことが可能となります。
PICTのインストールと実行
PICTとはMicrosoftが開発したペアワイズ法によるテスト組み合わせを自動的に作成してくれるツールです。
まずはインストールしてみましょう。
Mac OS
$ brew install pict
Linux
$ git clone https://github.com/microsoft/pict.git
$ cd pict
$ make
$ cp ./pict /path/to #パスの通ったディレクトリにコピーする
次にパターンファイルを作成します。テキストエディタを利用して次のルールで記載しましょう。
因子: 水準1,水準2,水準3...
受診前のアンケートをパターンファイルにすると次のようになります。
question.txt
性別: 男, 女
咳: ある, なし
喉の痛み: ある, なし
吐き気: ある, なし
味覚障害: ある, なし
妊娠: 妊娠中, なし
さて、次のコマンドを入力してテストパターンを出力してみましょう。
$ pict question.txt /o:6
性別 咳 喉の痛み 吐き気 味覚障害 妊娠
男 なし ある ある ある 妊娠中
女 ある なし なし なし なし
男 ある ある なし なし 妊娠中
男 ある なし ある なし なし
女 ある ある ある ある 妊娠中
女 ある なし なし ある なし
女 ある ある なし なし 妊娠中
女 ある なし なし なし 妊娠中
女 なし ある なし ある なし
男 ある ある ある なし なし
・
・
・
オプションで指定している /o:6はテストの組み合わせ数です。内容は後ほど説明します。
出力結果の列がずれて見にくい場合は、Excel等にコピペすると見やすくなります。
先に書いたとおり64パターン出力されていますね。
テストコードでこのパターンを実装したとしても64パターンのテストとその期待値を記載するのは大変です。しかし、なんの根拠もなくテストパターンを減らしてしまうと、バグの原因となります。ここではペアワイズ法を使ってテストパターンを減らしてみましょう。
次のようにオプション無しで実行してみてください。
$ pict question.txt
性別 咳 喉の痛み 吐き気 味覚障害 妊娠
女 ある ある ある なし なし
女 なし なし なし ある 妊娠中
男 ある なし なし ある なし
男 なし なし ある なし なし
男 ある ある なし なし 妊娠中
男 なし ある ある ある 妊娠中
極端にテストパターンが少なくなりましたね。これだとテストがずっとラクになります。でも、こんなにパターンを減らして本当に大丈夫なのでしょうか?
ペアワイズ法とは
ペアワイズ法とは「ほとんどの不具合が2つの要因の相互作用によるもの」と言う経験則から導かれています。
- NASAにおけるデータベースの欠陥329個を分析したところ、全体の93%がシングルモードまたはダブルモードの設定の組合せで欠陥が発生。
- Webブラウザではトリプルモードで95%の欠陥を検出(ダブルモードでは76%)
これは2つの要素の組み合わせさえカバーしておけば多くの不具合が防げる事を意味します。
初めに実行したコマンドは6つの要素、つまり全てのパターンをカバーしたテストになります。
$ pict question.txt /o:6
2回目に実行したコマンドはオプションを省略しました。この場合、組み合わせ数は2となります。
$ pict question.txt
$ pict question.txt /o:2 # 上と同じ
それでは先ほど作成したテストパターンを改めて確認してみましょう。
性別 | 咳 | 喉の痛み | 吐き気 | 味覚障害 | 妊娠 |
---|---|---|---|---|---|
女 | ある | ある | ある | なし | なし |
女 | なし | なし | なし | ある | 妊娠中 |
男 | ある | なし | なし | ある | なし |
男 | なし | なし | ある | なし | なし |
男 | ある | ある | なし | なし | 妊娠中 |
男 | なし | ある | ある | ある | 妊娠中 |
たとえば、性別と咳に着目してみます。
- 女、ある
- 女、なし
- 男、ある
- 男、なし
の2つの組み合わせが全てカバーされていますね。
次は、喉の痛みと味覚障害はどうでしょうか?
- ある、ある
- ある、なし
- なし、ある
- なし、なし
こちらも2つの組み合わせが全てカバーされています。
今回の例のように水準が2つしかない場合は、手動でもパターンを作成することができるかもしれません。しかし、水準が多い場合はPICTによるテストパターンの自動生成が役立ちます。
制約条件
先程作成したテストパターンをもう一度確認してみましょう。
性別 | 咳 | 喉の痛み | 吐き気 | 味覚障害 | 妊娠 |
---|---|---|---|---|---|
女 | ある | ある | ある | なし | なし |
女 | なし | なし | なし | ある | 妊娠中 |
男 | ある | なし | なし | ある | なし |
男 | なし | なし | ある | なし | なし |
男 | ある | ある | なし | なし | 妊娠中 |
男 | なし | ある | ある | ある | 妊娠中 |
性別が「男」かつ「妊娠中」が存在します。通常このような場合はアプリケーション側で「妊娠中」の因子を選択不可とする制御を行います。PICTはこのように条件に制約を設けることができます。
question.txt
性別: 男, 女
咳: ある, なし
喉の痛み: ある, なし
吐き気: ある, なし
味覚障害: ある, なし
妊娠: 妊娠中, なし
if [性別] = "男" then [妊娠] = "なし";
このように任意の因子と水準を指定して条件を設定することができます。もちろん ifは複数行記載することもできますし、 条件に AND, OR, LIKE 等を指定してより複雑な条件を組み立てることも可能です。
重要な組み合わせ
効率的なテストパターンが自動生成されるのはとても良いことですが、必ずこの組み合わせをテストしたい場合もあります。
このような場合は原型ファイルを利用して重要な組み合わせを指定することができます。
ここでは咳、喉の痛み、味覚障害がすべて「ある」の人にメッセージを表示するテストを考えてみましょう。
性別 | 咳 | 喉の痛み | 吐き気 | 味覚障害 | 妊娠 |
---|---|---|---|---|---|
女 | ある | ある | ある | なし | なし |
女 | なし | なし | なし | ある | 妊娠中 |
男 | ある | なし | なし | ある | なし |
男 | なし | なし | ある | なし | なし |
男 | ある | ある | なし | なし | 妊娠中 |
男 | なし | ある | ある | ある | 妊娠中 |
今までのテストパターンを確認すると、この3つの因子についてすべて「ある」というパターンが存在しません。
そこで次のような原型ファイルを作成します。
base.txt
性別 咳 喉の痛み 吐き気 味覚障害 妊娠
女 ある ある なし ある なし
原型ファイルはPICTが出力したフォーマットで作成する必要があります。
それではこの原型ファイルを指定してテストを実施してみましょう。
% pict question.txt /e:base.txt
性別 | 咳 | 喉の痛み | 吐き気 | 味覚障害 | 妊娠 |
---|---|---|---|---|---|
女 | ある | ある | なし | ある | なし |
女 | なし | ある | ある | なし | 妊娠中 |
男 | なし | なし | なし | なし | なし |
女 | ある | なし | ある | ある | 妊娠中 |
男 | ある | ある | ある | なし | なし |
女 | なし | なし | なし | ある | 妊娠中 |
原型ファイルを元に特定パターンのテストを追加することができました。
まとめ
簡単ではありますがPICTを使ったテストパターンの作り方を説明しました。
PICTを使うことによりテストパターンが爆発的に増えるのを効率的に抑えることができます。しかし、本文中にも書きましたが、因子の2つの組み合わせだけではテストとして不十分である事も考えられます。
また、当然のことながら期待値はテスト設計者が考えて慎重に設定する必要があります。
プロダクトの特性を考え、ビジネス的に絶対に落としてはいけない箇所を重点的かつ効率的にテストしていきましょう。
Discussion
大変勉強になりました。ありがとうございます!
TypeScript環境で利用できる類似のツールを開発中ですので、参考にさせていただきます。