『システム運用アンチパターン』輪読会 5章「最後の味付けとしての品質」

## 5章 最後の味付けとしての品質

---

料理を引き立てるために最後に加えられるスパイス類。だがそこに「高品質」という名のスパイスは存在しない。存在しないのだが多くの組織で「高品質という名のスパイスで料理を満たしてくれ！」という注文がなされる。
これが今回のアンチパターン。

---

高品質なプロダクトを安定して提供するためには全て個別のコンポーネントや構成要素で品質を作り込み、最終的にプロダクトに完全に統合される前にその品質を個別に検証しなければならない。
この章では開発サイクルにおける品質を左右するテストプロセスとそれがDevOpsにどのように適用されるかが説明されている。

---

### 5.1節 テストピラミッド

---

テストピラミッドは

- エンドツーエンドテスト
- 統合テスト
- ユニットテスト

という、3つの層からなる。

---

ユニットテストが一番下、真ん中が統合テスト、一番上がエンドツーエンドテストである。下に行くほど数が多く高速、上に行くほどテストの速度が低下し、影響を与える外部要因の数が増えていく。

---

DevOpsの本にテストに焦点を当てた章がある理由
- 自動テストがDevOpsのアプローチにおいて重要な役割を果たしているから
- 運用担当者(開発者ほどテストプロセスに精通していない)に向けてテストプロセスを理解してもらうため

---

＜私見・感想＞
かなりの頻度でテストピラミッドの上の方からのアプローチを「単体テスト」として実行している場面に出くわす。歴史的経緯でテスティングフレームワークが未導入だったり色々理由はあるのだが。
Webフォーム表示プログラムのテストがE2Eになるのはある程度しょうがない気もする（情報の登録なんかはAPI側のユニットテストで担保されているんだけれども）

---

### 5.2節 テストの構造

---

テストピラミッドで挙げた3つのテストについてそれぞれの構造を説明している節である。

下の階層ほど外部から分離されたテストとなっており逆に上に行くほど外部への依存が発生する。故に上に行くほど不安定なテストであるといえる。
継続的インテグレーションサーバーによって自動テストが実行されるのは一番下のユニットテストである。
統合テストはDBやAPIとのやりとり、他へのレスポンス処理をテストする
E2Eテストはエンドユーザーの視点によるシステムテストである

---

＜私見・感想＞
一つのフォームに１０００を超えるE2Eのテストケースを作ったことがある身としては耳が痛い話。リグレッションテストとしてはE2Eはアリなんだけど、環境依存で結果が変わるようなテストケースは含めないようにしないとテスターに迷惑がかかる。本当ごめんなさい :bow:

---

### 5.3節 テストスイートの信頼性

テストが失敗した時にエンジニアが原因も探らずテストを再実行する場合、エンジニアのテストスイートへの信頼性は低い。言い換えると自分が行った変更がテストスイートに影響したと確信していない。ビルド環境とかデータを疑っている。

---

#### 信頼性を取り戻す

- テストスイートは失敗が発生したらすぐに失敗するべき(ピラミッドの下層で失敗しているのに上層のスイートを実行する意味はない)
- 不安定なテストを許容しない
  - テストスイートを分離
  - E2Eテストの数を制限する
  - E2Eテストは機能テストのみに限定する（パフォーマンスはテストしない)
  - E2Eテストは可能な限り分離する(独立した環境で実施する)

テストカバレッジに代表される「虚栄のメトリクス」は回避する。数字だけでなく品質に目を向けよう

---

＜私見・感想＞
さっきも書きましたがE2Eテストの数の話は耳が痛い。ユニットテストが実施できないレガシィなシステムだと統合テスト以降に頼らざるを得ないのが辛い。

---

### 5.4節 継続的デプロイと継続的デリバリ

---

継続的デプロイ
- メインラインブランチへの全てのコミットが本番環境へのデプロイプロセスをトリガするという考え方

継続的デリバリ
- アプリケーションを常にデプロイ可能な状態にしておくことを目的とする。どれだけ頻繁にリリースするかに関わらずリリースサイクル中は常にメインブランチが壊れていない

デプロイパイプライン
- ユニットテストやアプリケーションコードのパッケージ化などコードの変更を検証する一連の構造化され自動化されたステップのこと

ビルドアーティファクト
- アプリケーションまたはアプリケーションのコンポーネントのデプロイ可能なバージョン。ビルドプロセスの最終的な出力となる

---

＜私見・感想＞
継続的デプロイと継続的デリバリを区別しているところが面白い。メインブランチへのコミットがメインブランチを壊さないことが保証されていれば二つは同一視できそうだが、確かに自動テストもない状態でそれを担保するのは不可能に近い。

---

### 5.5節 機能フラグ

---

フラグやセマフォを使ってコードパスに対して条件分岐を追加するための手法。コードのデプロイのタイミングと新しいコードパスを有効化するタイミングを分けることができる。

例えばレコメンドのアルゴリズムを機能フラグを使って新旧を出し分けるような仕組みのこと。
グレースフルリカバリーのために機能フラグを保持し続けることもある。

---

＜私見・感想＞
ABテストにも使えそう。DBのフラグテーブルによる出しわけだとユーザーごとに変えたりは難しそうだけど。C言語系のコンパイラディレクティブなんかも機能フラグとして使えるのかな？ でも別ビルドになるからちょっと意味合いが変わるか。

---

### 5.6節 パイプラインの実行

---

筆者曰く、継続的インテグレーションは誤用されているので「パイプラインエグゼキュータ」という言葉を用いている。それはワークフロー内のさまざまなステップを条件付きで実行できるツールのことである。
製品による大きな違いはないので、組織に導入しやすいツールを選択しよう（ツールの選定に多くの時間を割くべきではない)

---

＜私見・感想＞
「CIのアプローチでは少なくとも1日に1回自分の変更をメインラインにマージすることを求められる」
うぉ、まじか。PR出してからマージまでが１日かからない生産性の高いエンジニアになりたい。

---

### 5.7節 テストインフラの管理

---

管理すべき重要なコンポーネント

- CIサーバ
- アーティファクトのストレージ
- テストサーバ
- テスト対象のソースコード
- 実行されるテストスイート
- テストスイートが必要とする全てのライブラリと依存関係

---

筆者曰く、テスト環境は運用チームが所有するべきである、と。理由は以下の通り。
- テストサーバーは本番環境を模倣する必要があり、本番環境に詳しいのは運用グループである
- テストインフラ、特にCIサーバは大きなセキュリティ上の懸念があるため、運用チームがCIサーバを所有し他のセキュリティ制限やプロセスに準拠することは理にかなっている

ただし、運用部門と開発チームの間には高度な協力と調整が必要。

---

＜私見・感想＞
CIサーバもSaaSに任せる時代がやってきております。IaaS上のJenkinsで運用してたこともありますが。
べんりなじだいになったものじゃのう
（なお、当社ではSaaSがセキュリティ基準を満たすかどうかをセキュリティ部門が精査して基準を満たすサービスだけを利用しています）

---

### 5.8節 DevSecOps

---

DevOpsの考え方を拡張し、セキュリティを主要な関心事の一つとして加える新しいパラダイム。
最後の味付けとしての品質というアンチパターンではプロジェクトの最後にセキュリティチェックを行うが、セキュリティチームをDevOpsのライフサイクルに組み込むことで、セキュリティチームはプロセスの早い段階で設計の決定に関与する機会が得られる。

---

DevSecOpsのアプローチでは、テストの運用方法と同様にセキュリティスキャンやセキュリティテストをパイプラインの一部として組み込む必要がある。
まずはセキュリティチームに相談して、どうすればより緊密に連携し、彼らのプロセスをビルド・テスト・デプロイのプロセスに統合できるかを聞いてみよう。
今後のプロジェクトにおいてセキュリティチームにどのように参加してもらうかのステップを明確にした上で、ハイレベルでのチェックを自動的に行いそれをテストパイプラインに組み込むことを目標としよう

---

＜私見・感想＞
セキュリティテストがE2Eテストに近い感じで長時間かかるイメージがあるのだが、それも最後の味付けとしての品質パターンにはまっている証拠かもしれないと思った。静的解析ツールで不用意なセキュリティ的に弱いコードを避けるなどが対策として当てはまるのだろうか。

---

### 5.9節 本章のまとめ

- テストピラミッドを参考にして、テストを論理的にグループ化しましょう。
- 信頼性と開発者への迅速なフィードバックを重視することで、テストに対する自信を回復しましょう。
- 継続的デリバリにより、アプリケーションを常にリリース可能な状態にしましょう。
- パイプラインエグゼキュータツールは、組織からの抵抗が最も少ないものを選びましょう。

---

＜本章に対しての私見・感想＞
「高品質」を求める場合、早い段階から高い品質を意識的に組み込む仕組みを作る必要があるとわかった。
それはテストを自動化すればいいとかテストカバレッジを100%にすればいいというものではなく、信頼性の高いテストスイートの作成やインフラの管理なども含めて品質を保てるように意識しておく必要があるのだなぁ。

以上