6. 品質について考え直す
本章について、最初に、お詫びがあります。
アジャイル開発における品質確保の手法について、常識らしいものがあるのかについて、著者には全く知識がありません。
本書全体が著者個人の意見を中心に記載していますが、特に本章の内容は将来見直される可能性があります。
6.1 ウォーターフォール開発では形式的な合意形成の事例がある
【現実6】
品質に100%は存在しません。
ソフトウェアにバグが無いことは証明も確認もできません。テストはいくらでも継続することも可能です。さらに、そもそも要求仕様が真の要求を100%満足するものになっていることさえも保証できていないかもしれません。
【現実6-a】
品質とは、費用対効果のバランスを考えて割り切るものです。【品質トレードオフ原理】
品質100%の世界が無いとすると、どんな試験をどこまで実施し、どこで止めるか、が重要なポイントになります。 QCD(品質・コスト・納期)のバランスをとった判断が必要で大切 になります。
■ ウォーターフォール開発の良さは、試験の進め方および試験終了に関する合意形成の形式的な見本が多数あることです。
ウォーターフォール開発では、たとえば試験の進め方は以下のようになります。
- 各工程のドキュメント作成とレビューによる合意を行い品質の高いドキュメントを積み上げる。必要ならレビュー時間・コメント密度などの指標も活用しドキュメント品質を上げていく。
- 試験工程は「V字モデル」で示されるとおり、各工程で生産したドキュメントに対応する試験観点・試験項目を用意する。
- ソースコードはクロスレビューをする。
- 単体試験はC0(命令網羅率), C1(分岐網羅率), C2(条件網羅率)などの網羅率の目標値を決める。
- 試験観点については網羅性をレビュー合意する。
- 目標の試験密度を決め、試験項目で正常系試験数と準正常・異常系試験数の比率を決め、試験観点から試験項目を展開する。
- 長安(長期安定化試験)、過負荷長安について試験時間の目標を決める。
そして、試験を実施した結果について、たとえば以下のような分析と対策を実施して、試験終了判定を実施します。
- 各目標値を満足しているか、基準範囲内に含まれているか、乖離があれば乖離理由は何かを分析します。
- バグ検出数・傾向の分析をします。高密度なら品質低ではないか、低密度なら試験不足ではないか、バグ出現は特定の機能や観点部分に偏りないか、摘出した工程は適切だったか、などの分析を行います。
- 長安実施中のリソース傾向、過負荷時の状態、過負荷終了後に定常状態に戻った後のサービス回復/リソース回復状況などを分析します。
- バグや異常動作については、原因分析(なぜなぜ分析)を行って弱点やミス発生理由を検出します。偏り(特定の機能か、特定の使われ方か、特定の作成者かなど)のある弱点がないか分析します。そのバグが作り込まれた本当の理由はなにか、そのバグはどの工程で検出すべきだったのか、それを防ぐために本来各工程で何をすべきだったかなど、を分析します。
- 各弱点や原因に応じて本質的な品質向上対策を類似部分についても水平展開を実施します。
- 品質不足、試験密度不足、観点漏れがあれば、追加で強化試験を実施します。
- 強化試験結果の再分析とバグ原因への対策完了で試験終了を判定します。
- バグ収束曲線の傾向分析を行い収束傾向から試験終了を判定します。
ウォーターフォール開発では、試験前に合意した各種目標値を満たすことで試験終了と判断することができます。その基準を満足することが、決して、サービス開始後に重要な問題を起こさないということを保証するものではないことも多くの人は理解しています。実際、ウォーターフォール開発で実施したシステムでも不具合・故障は発生しています。それでも、ほぼ形式的に試験終了判断を可能にする合意形成メカニズムは有効です。他者と同等レベルの形式に従って試験を実施したので、問題が発生しても、それは仕方なかったという横並び論理が使える枠組みとして割り切るのでしょう。(実際に、商用サービスで大きな問題が発生してしまうと、そんな理由は何の気休めにもならないのが実態かと思いますが・・・。)
■ ウォーターフォール開発では、受注側に完成責任(瑕疵担保責任)があるので発注側に安心感はありますが、実は期待するほど強力な仕組みではありません。
ウォーターフォール開発では、受注する側に欠陥の無いものを納品する義務が発生しています。その枠組みがあるから、困ったら無償で直してもらえばよいと考えれば良いのでしょうか。ある意味では正しい考え方ですが、一方で注意しなければいけない点はあります。
- 受注側の責任による欠陥であることを客観的に示せるでしょうか。仕様として誤解なく明記されているでしょうか。伝え方が悪かったなどグレーゾーンであることがあります。伝えた記録はきちんと残っているでしょうか。
- 要件FIX、仕様FIX後に仕様変更を押し込むなどの強引な行為は無かったでしょうか。途中から言い方を変えて受注者を混乱させていなかったでしょうか。変更に伴って期間・費用を適切に見直した契約変更を実施しているでしょうか。
- 経験豊富な開発会社であれば、都度、発注者にレビューを依頼し確認を積み上げてきます。発注者側でレビューは完全にできているでしょうか。最終品質も、「ここまでこういう試験をしている」と発注者に報告した記録と、発注者側の受入試験に合格した証跡があるはずです。受入確認は十分だったのでしょうか。
これらに発注者側が完璧に対応していれば、瑕疵担保責任によって無償改修してもらえるでしょう。しかし、発注者側にも仕様記載漏れ、レビュー確認漏れ等が発生すると、訴訟に発展していきます。痛み分けとなった場合には、双方に弁護士費用と不毛な時間が発生します。「伝家の宝刀」だと思って抜いたら自らをも大きく傷つける「両刃の剣」かもしれません。
■ アジャイル開発における品質確保・試験終了への考え方は、ウォーターフォール開発に比べて形式化されていません。
アジャイル開発ではウォーターフォール開発と同じ試験終了ストーリーは使えません。そして、試験終了の基準もなく、すべてがPOに任されているというのが現状でしょう。では、アジャイル開発における試験の進め方、試験の終了判断はどうすれば良いでしょうか?
6.2 アジャイル開発での品質確保・試験終了の考え方
3章を読んだ方は、すでに理解されていると思いますが、アジャイル開発では以下の原則があります。
■ アジャイル開発では品質確保責任も、発注者側(PO)にあります。
品質確保も完成責任の一部です。よって、品質についてもPOのコントロール配下にあります。
ウォーターフォール開発では形式として、「目標試験密度をクリアすること」、「バグ収束曲線が収束すること」、「バグ発生原因を分析し、対策が完了済みであること」、などと形式的に品質条件を指定することが可能でした。アジャイル開発であってもPOがウォーターフォール開発と同様の基準を達成する進め方は可能です。それも一つの方法でしょう。
しかし、ウォーターフォール開発と同じ進め方は本当に正しいのでしょうか。アジャイル開発のPOは早期のサービスリリース圧力と、品質確保のバランスの中で、もっと良い方法と試験の終了時期を考えていくべきでしょう。
■ アジャイル開発では、一定レベルの品質の確保の後は、小さく利用してもらいながら品質を上げ、利用対象を拡大するアプローチをとります。
アジャイル開発では、初期にまず小さい範囲のユーザに利用を開始してもらい、徐々に利用者の範囲を広げていくという考え方を素直に適用します。ウォーターフォール開発とは異なり、試験を一旦終了しリリースした後であっても、追加で品質向上のための試験を実施することができますし、初期のユーザ試用によって発見された重大な弱点は早期に対応していくことが可能なのです。アジャイル開発では以下の2つの考え方が大切になってきます。
【方針1】 重要な部分から品質を確保する考え方
【方針2】 継続的に品質を改善していくという考え方
それぞれについて更に考えていきましょう。
6.3 【方針1】 重要な部分から、品質を確保する
■ テストの前に、まずは動作させることを優先しましょう。テストは、動作するものが固まってから実施するものです。早すぎるテストは悪です。
テストは動作するものが固まってから実施するものです。アジャイル開発では設計や仕様をダイナミックに変更させていくケースがあります。そういったアーキテクチャの試行錯誤の工程でテストを優先してはいけません。アーキテクチャを固めることは、テストをすることよりも明らかに優先されます。「コードを書いたら、まずはテストする」という考え方や、「UT 100%」という考え方の優先度を高く設定してはいけません。コードを書いた瞬間こそ、テストコードを書きやすいというケースもあるでしょう。その場合はソースコード中に「TODO」として、テストに関するメモを残すことに留めましょう。
■ テストは、早めに大きなリスクを抽出するように順序を計画しましょう。
テストは大きなリスクを早めにつぶすべき、それが考え方の軸となります。
- システム設計上の核となる部分。設計が難しい部分。
- システムのメインルート。ユーザ影響が大きい部分。
- 課金等に関わるもののうち根幹となる部分。
- 仕様が難しい部分。
- バグが発見されると改修するのに時間がかかり、代替手段(運用対処など)がない部分
■ 1つのテストの中に、重要な部分と重要ではない部分が混在する場合には、テストも分割して各優先度に応じたタイミングで実施しましょう。
大切な機能だから最初にテストすべきと選ばれた機能であっても、本当にその機能を全てテストするのか、を考え、重要な部分とそうでない部分が混在しているのであれば、重要でない部分の実施優先度を考え直しましょう。「ついでにやりたいから」という理由に対する優先度は低いと思いましょう。一緒にやることで時間効率が高いのであればバランスを考えて判断しましょう。
■ 機能ごとに、試験工程の実施時期を変えることは普通です。
重要部分やシステムとして早期に動かすべき部分の結合試験と、周辺部分の結合試験のタイミングは当然異なって構いません。機能の重要性が高いものの結合試験工程と、機能の重要性が低いものの製造工程が各々同時に進んでいることは平常状態です。
■ 外部APIのテストは重要です。
システム連携など、外部システムとのAPIを持つシステムであれば、そのAPIに関するテストは重要です。
他システムに悪影響を与えないために、さらに、今後のリリースにおいてもAPIを確実な互換性を維持するために、早期にテストセットを整備し、確実に試験すべきです。
■ 画面系のテストは、ずっと後です。利用者の意見を聞きながら変化・反映させる部分に対して、最初にテストしても無駄になります。
外部との連携部分として、ユーザ画面もあるでしょう。しかし、画面系について最初から試験密度を上げるテストを行ってはいけません。できるだけ、UI部分とバックエンドをREST(HTTP)等で分離し、優先度を変えて試験を実施していきましょう。
■ 真にエンドの利用者に使ってもらうフェーズのリリースになってきたら、ユーザに失望されないレベルの品質が大切です。
真のエンドユーザに失望されて、今後の開発や利用で協力を得られないレベルに陥るのでは問題があります。エンドユーザはアジャイル開発にも、不完全なシステムの利用にも慣れていないかもしれません。あらかじめ目的と品質レベルを通知し納得してもらって使ってもらいましょう。
■ エンドの利用者に使ってもらった後のリリースでは、デグレード(先祖がえり)を避けましょう。
一旦、利用してもらった後に、改善版を再度リリースして使ってもらう際には、デグレードしないように注意し試験を実施しましょう。リグレッション・テストの整備を実施し始めるタイミングになっています。あわせて構成管理(各サブシステムのバージョン管理等)も確実に実施していきましょう。
■ その後のリリースでは、テスト不足を取り繕うことで忙殺されることのない品質レベルを目指しましょう。
品質が悪いものを大規模ユーザに対してリリースすると、多数の課題が出てくるかもしれません。品質強化の作業で開発メンバを酷使してはいけません。アジャイル開発では開発メンバのモチベーションの維持が重要なポイントでした。大規模ユーザへのリリースの前には、十分な総合試験と自動リグレッション・テストの整備を行いましょう。リリース後の品質対応の苦労を知る優秀な開発メンバを含む開発チームは、きっと品質を上げてからリリースした方が楽だと思っているハズです。
6.4 【方針2】 継続的に品質を改善する (自動リグレッション・テストの整備)
アジャイル開発で作られるシステムは常に成長し続けるシステムです。永遠のβ版かもしれません。
そこで、重要になるのが自動リグレッション・テスト(回帰試験)の整備と実施です。
■ リグレッション・テストの整備とその自動化率の向上は計画に入れておきましょう。
アジャイル開発のテストにおいてリグレッション・テストは必須です。それは、アジャイル開発の 属人化リスクを避けるための重要な手段 でした。リグレッション・テストの整備はついでの作業でできるレベルではありません。あらかじめ計画の中に組み込んで置く必要があります。リグレッション・テストの自動化環境の整備やCI環境の整備は、システム本体開発の遅延対策用のバッファ(たとえばCIは後にする、自動化は後にするなど)として活用することもできます。
なお、自動リグレッション・テストの整備についても100%主義を持ち込んではいけません。たとえば、異常状態からの復旧のテストを100%自動化するのは投資対効果の面から良い判断とは言えないケースもあります。また、リグレッション・テストの整備は、システム本体開発よりは優先度が下がることは意識しましょう。リグレッションコードの整備を優先しすぎてシステムの進化を止めすぎると、アジャイル開発で得るはずだった競争力が低下して、開発プロジェクト自体の停止に至ることもありえます。
■ リグレッション・テストの拡充によって、過去のリリースより品質が向上していることを積み上げて保証していきましょう。
リグレッション・テストの整備も段階的に実施していくことになります。自動化の度合いも徐々に向上させていくことになるでしょう。
リリースの都度リグレッション・テストを完了させていることによって、過去のリリース以上の品質であることを保証していきます。開発者もサービス提供者も安心して次の機能開発に進んでいくことができるようになります。
■ リグレッション・テストの整備のメリット/デメリット
メリットは以下となります。
- 属人性の削減ができる。維持管理費用の低減になる。
- OSSのセキュリティパッチ対応やバージョンアップの際にも、自信を持って対応できる。
一方、デメリッは以下になるでしょう。
- 機能作成時に、テストコード作成の手間が増える。
- 将来の機能変更の際に、テストコードのメンテの手間が増える。
■ テストコードは適切なフレームワークを利用し、シンプルにして維持管理しやすくしましょう。
上記のデメリットに対応するためには、テストコード自体の維持管理を考えなければいけません。適切なフレームワークを活用し、できるだけシンプルに作らなければいけません。テストコードが複雑すぎて修正もできない、テスト自体が正しいか判断できない、ということになっては本末転倒です。
■ CI環境の整備のタイミングは遅くても良いと思います。
自動リグレッション・テストが完成後、一度動作したシステムに対して継続的インテグレーション(CI)環境の実現と実施は非常に有効です。Build&Testを毎晩自動実行していれば、互換性の崩れを翌日に検出できます。けれどもリグレッション・テストの実行が自動化されていることがより重要であって、その日々実行の環境はそこまで優先度が高くありません。実施するタイミングは、一度、商用サービスリリースしてからでも良いと筆者は考えます。当初の開発計画にはCI環境の構築までを含めておき、品質問題が発生した際には強化試験に置き換えるバッファとして使うのがバランスの良い考え方だと思います。
■ TDDの価値は無いと思います。多くのTDDは、実は単体試験駆動開発(UTDD)だからです。
「テスト駆動開発(TDD)」、それは、非常に魅力的な視点を提供しています。筆者もウォーターフォール開発の際に、設計書はテスト項目で書こうと提案したこともありました。
しかし、現在の筆者の考えでは、アジャイル開発においてTDDは良くない考え方の側にいます。TDDと言った場合には、単体試験を前提に語られているように思います。要求仕様や基本設計等に対応するレベルのTDDであれば優先度を上げていくことは理解できますが、単体試験レベルを志向するTDDは良くないアプローチです。
■ TDDは全体のアーキテクチャの決定より個別プログラムコードの品質を優先している点において、早期サービスリリースを優先するスタイルとは合いません。
筆者の考えでは、単体試験の優先度はアーキテクチャの決定より圧倒的に低いと考えています。まずは全体のアーキテクチャ設計をユーザからのフィードバックを受けながら確かめ修正していくことが優先されます。将来捨てるかもしれないプログラムコードに対して、品質を求めていくことは優先順位が間違っています。アジャイル開発ではUT100%よりも、サブシステム間のインタフェースを試しながら確定する方が重要なのです。
■ 全体アーキテクチャが固定化された後の機能追加開発であれば、システムテスト駆動開発(STDD)は有効です。
単体試験レベルに対するTDDではなく、結合試験レベルに対するTDDが有効になることは間違いありません。その場合のTDDは外部インタフェース(API)の試験と、ユースケースシナリオ試験になります。ATDD(受入試験のTDD)もこれに近いかもしれません。
6.5 それでも、納期が厳しく品質も求められる場合の対応 (例)
それでも、納期が厳しく品質が求められる開発の場合もあるでしょう。その場合にはどのように進めるべきでしょうか?
残念ながら科学的な手法はありません。ウォーターフォール開発スタイルでの開発だった場合とアジャイル開発での比較をしながら考えていくのも一つの方法だと思います。
従来のウォーターフォール開発で開発する場合のV字モデルを参照しつつ、KKD法によって、たとえば、一旦以下のような基準(仮)とします。
0/5の時期 ・・・ 仕様の提示、設計開始
1/5の時期 ・・・ 仕様のFIX
1/2の時期 ・・・ 製造の完了、試験工程開始
納期1ヶ月前 ・・・ 最低限の納品物が存在する
4/5の時期 ・・・ 商用環境試験開始
5/5の時期 ・・・ 納品
これを参考として、あなたのプロジェクトの計画や実績との比較分析をしてはどうでしょうか。たとえば、1/2の時期で製造工程は完了しているでしょうか。普通のアジャイル開発であれば、既に先行開発部分を利用者に使い始めてもらっていてもおかしくない時期でしょう。しかし、あなたのプロジェクトではまだ製造工程が完了していないとしたら、それは納期に対して大きな遅延かもしれません。開発機能の一部を落としてでも試験に入っていかなければ品質確保は難しいのかもしれません。逆に先行する部分に対する試験が十分進んでいれば、±0であって遅延はないのかもしれません。この分析によって、今後、アジャイル開発で受け付けられる仕様変更の量を見極めるのも一つの方法でしょう。
この例は、あくまでも、他に頼るべき基準が無くて困っている場合ですが・・・。
2022.9.25 改版に向けて