Pictを導入してテスト観点を見直してみた

## はじめに
- 今回はPictを使うきっかけも交えて使い方を簡単にまとめます
- きっかけとかあんまり興味のない方は使い方まですっ飛ばしてください

## 前提
- 僕たちのチームではテストフェーズにおいて、単体・機能・結合・長期安定化の4種類のテストを実施していました
- それぞれで確認していたことは以下の通り

| テストフェーズ      | 確認内容           | 
|:----------------|:------------------|
|単体テスト| ラインカバレッジを通っていれば良し|
|機能テスト|正常系何パターンか＋異常系は想定しているエラーのパターンだけ|
|結合テスト|インターフェース間の疎通確認がメイン|
|長期安定テスト|運用直前に最後のバグ潰し的位置付け|

- 一応、テストピラミッドを意識はしていて、バランス的には間違ってないのかなという認識ではいました

## きっかけ
- とはいえ、単体や機能でバグを救いきれないケースもあり、リリース後に気づいたこともあった
- そこに対して問題意識はあって、どうにかしないといけないとは思っていた

## 最初の案
- そこで、最初に案として機能テストを頑張ってケース増やすという話になった

### メリット
- いろんなケースを試せる
- テスト自動化してるので、1回仕込んでおけば安心

### デメリット
- DBセットアップとかjsonとか用意することが多い場合にコストが嵩む
- CIでDBセットアップしまくるとCIが遅くなる
- テストピラミッドを意識した際に、下のレイヤーの方がコスト低いから、下で担保できることは下でやったほうがいい（=下の層で担保できることを上の層でやらない）

- となると、単体でなるべくパターン網羅したほうがコスパよくない？という結論に至る

## 次の案
- そこで、単体テストを頑張ろうという話になった

### メリット
- 機能テストであげたメリットは享受できる認識
- 機能テストより単体テストでやったほうがコストは安い

### デメリット
- あんまり思い浮かばなかったです
- ただ、単体で複数の引数を受け取っていて、かつそれぞれが0,1,2を考慮しなければいけないケースなどでは全件やるのは無理
- そこで、pictの登場！！

## pictの使い方
### インストールの方法(homebrewが入ってる場合)

```shell
## 下記コマンドを叩くだけ
$ brew install pict

## インストールできていればpictコマンドが効きます
$ pict

Pairwise Independent Combinatorial Testing

Usage: pict model [options]

Options:
 /o:N    - Order of combinations (default: 2)
 /d:C    - Separator for values  (default: ,)
 /a:C    - Separator for aliases (default: |)
 /n:C    - Negative value prefix (default: ~)
 /e:file - File with seeding rows
 /r[:N]  - Randomize generation, N - seed
 /c      - Case-sensitive model evaluation
 /s      - Show model statistics
```
- 1回目にbrewした時になんかコケたのですが、もう1回実行したら普通にダウンロードされてきたので試してみてください

### インストールの方法(homebrewが入ってない場合)

```shell
## リポジトリをクローンしてくる
$ git clone https://github.com/Microsoft/pict.git
$ cd pict/

$ make

## 成功したらpictコマンドのパスを通す
$ sudo install -m 0755 pict /usr/local/bin/pict

## あとは同じ
$ pict

Pairwise Independent Combinatorial Testing

Usage: pict model [options]

Options:
 /o:N    - Order of combinations (default: 2)
 /d:C    - Separator for values  (default: ,)
 /a:C    - Separator for aliases (default: |)
 /n:C    - Negative value prefix (default: ~)
 /e:file - File with seeding rows
 /r[:N]  - Randomize generation, N - seed
 /c      - Case-sensitive model evaluation
 /s      - Show model statistics
```

### 簡単に使ってみる

- 試しに食事内容の組み合わせを決めてみたいと思います
- 適当なファイルに、下記の感じで4つのパラメータを用意してみました 

```sample.txt
meal: rice, bread, noodle
main: chicken, beef, pork, fish
salad: green, potato
withSoup: true, false
```
- pictのオプションは下記の感じになってるみたいです
- デフォルトではパラメータ名:value, value, valueという書き方をしてれば認識してくれそう

```README.md
Usage: pict model [options]

Options:
  /o:N    - Order of combinations (default: 2)
  /d:C    - Separator for values  (default: ,)
  /a:C    - Separator for aliases (default: |)
  /n:C    - Negative value prefix (default: ~)
  /e:file - File with seeding rows
  /r[:N]  - Randomize generation, N - seed
  /c      - Case-sensitive model evaluation
  /s      - Show model statistics
```

- このファイルを単純に組み合わせを考えると48通り出てくるはずですよね
- Pictを使うと、12通りのパターンを洗いだしてくれます（デフォルトで2パラメータ感の組み合わせをみてくれます）

```shell

$ pict sample.txt

meal	main	salad	withSoup
rice	beef	potato	true
bread	pork	potato	false
bread	fish	green	true
bread	chicken	green	false
rice	fish	potato	false
noodle	pork	green	true
rice	chicken	green	true
noodle	fish	potato	false
noodle	beef	green	false
noodle	chicken	potato	false
bread	beef	potato	false
rice	pork	green	false
```

- これを例えば3パラメータ間での組み合わせをみるとしたら

```shell
$ pict sample.txt /o:3

meal	main	salad	withSoup
rice	beef	green	true
rice	fish	green	false
bread	chicken	green	false
rice	pork	green	false
bread	fish	green	true
noodle	beef	green	false
noodle	beef	potato	true
rice	chicken	potato	true
rice	pork	potato	true
noodle	pork	green	true
noodle	fish	potato	true
bread	pork	green	true
rice	chicken	potato	false
bread	fish	potato	false
rice	chicken	green	true
bread	beef	potato	true
bread	beef	green	false
noodle	chicken	green	true
noodle	pork	potato	false
bread	pork	potato	false
bread	chicken	potato	true
rice	beef	potato	false
noodle	fish	green	false
noodle	chicken	potato	false
rice	fish	potato	true

```
- さすがに見づらいので、件数だけ取得してみます

```shell
$ pict sample.txt /o:3 /s

Combinations:   76
Generated tests:25
Generation time:0:00:00
```

## まとめ
- 基本的な使い方だけまとめさせてもらいました
- いくつものパラメータに渡って組み合わせを考えるのって結構面倒だと思うので使用できるケースは結構ありそうです
- pictのもっと詳しい内容が知りたい場合は[この記事](https://qiita.com/greymd/items/ad18aa44d4159067a627)をみていただけると良いかと
- あと、マイクロソフトさんが出してるだけあってREADMEがかなり充実してる印象なので時間がある時に一読してるといいかもです

## 参考記事
- [テストの数を減らそう！プリキュアで学ぶPICT](https://qiita.com/greymd/items/ad18aa44d4159067a627)
- [pictのgithub](https://github.com/Microsoft/pict/blob/master/doc/pict.md)