モダンなテストレベル設計(ユニットテスト~システムテスト等をどう設計するか)の原則
#QA #テスト設計 #テストケース
@goyoki: TLでテストレベル設計の話が出ていたので、ここ数年のテストアーキテクト業で考えていたものを、勢いで文章化してみた/モダンなテストレベル設計(ユニットテスト~システムテスト等をどう設計するか)の原則 - 千里霧中 https://t.co/a3FBiZStuY
現代のテストについて網羅的に解説されており、とても丁寧で良い記事だったkoushisa.icon
プロジェクト全体のテストを組み立てる際に重要な課題になるのが、テストレベル設計です。テストレベル設計は、ユニットテスト、結合テスト、システムテストといったテストレベルを、どのような責務・段取りで行うか分析・設計する活動です。
このテストレベル設計ですが、ここ10年程度の間に望ましいアプローチが変わってきたと感じています。今回はこの変化と、変化後のモダンなテストレベル設計の原則について、考えていることを記述したいと思います。
いくつか引用
---
旧来のテストレベル設計のアプローチ
旧来、このテストレベル設計では、Vモデルをベースしたアプローチや、自工程完結・品質積み上げをベースとしたアプローチがよく見られました。
一つ目のVモデルをベースとしたアプローチは、要求定義から設計までの上流工程への対応を観点に、テストレベルを設計するものです。
#要求分析 #要件定義
#トップダウン
二つ目の自工程完結・品質積み上げをベースとしたアプローチは、「自分たちチームの成果物の品質は自分たちが責任をもって確保・保証する」「構成要素ごとに品質を確保・保証する」という考え方でテストレベルを設計するものです。
~
チームが実装工程を担当するならば、ユニットテスト工程を確保し、実装仕様の実現性保証や、実装に起因するバグの取りきりをチーム内で行います。
#ボトムアップ
「構成要素ごとに品質を確保・保証する」 = コンポーネントチームっぽい感じかな
---
開発技術やプロセスの発展とテストレベル設計
上記のアプローチは現在でも陳腐化したわけではありません。ただ開発技術やプロセスの発展で、より柔軟なアプローチを加えることが可能になっていると感じています。
その発展の一つが、自動テスト手段の充実です。
~
結果、Vモデルや自工程完結のアプローチだけでテストレベルを設計するだけでなく、費用対効果の高いテストレベルの責務を増やし、費用対効果の低いテストレベルの責務を減らす設計アプローチが、開発の生産性を高めるのに有効になりました。
発展の二つ目は、継続的デリバリやDevOps、またはDORA Four Keysを追及するような、開発のリードタイムを重視する開発プロセスの普及です。
~
この開発プロセスにとっては、旧来の大規模な手動テストは、遅すぎ・コストがかかりすぎで、リードタイムを大きく悪化させ、プロダクトの価値を棄損します。
そこで、リードタイムの短いテストレベルでなるべくテストを済ませ、遅いテストレベルはできるだけ排除するアプローチが採用されやすくなりました。
最後の発展は、CI/CDによるデプロイメントパイプラインの充実です。
~
これにより、テストレベルの本来の能力に基づいて、テストの責務を移動させるアプローチを柔軟に取れるようになりました。
---
モダンなテストレベル設計の原則
もっとも効果的なテストレベルの責務を最大化する
それぞれのテストレベルの強みを最大化し、弱みを最小化・補完する
テストレベル間のテストの重複は、全体が良くなる方向で削除する
BDD っぽいkoushisa.icon
~
このようなデメリットを加味して、注力するテストレベルを選択すべきといえます。テストピラミッドでなく、APIテスト等結合テストを主体としたテストトロフィーを志向したほうが良い開発も少なくありません。
テスティングトロフィー
---
テストレベル間でのテストの責務の移動を支える基礎
契約による設計(またはそれと同等の責務設計)を推進する
#契約による設計 #レイヤードアーキテクチャ
システムテストの責務を結合テストに移動させる場合に重要になるのが、システムの機能や処理を、コンポーネントのどこが責務として担っているのか明確にすることです。
例えば以下の事例を考えます。
~
しかし入力バリデーションの責務が曖昧だったり、レイヤ横断的に実装されている場合は、システムテストから結合テストへの移動は、リスクができず実施できなくなります。
ですので、 契約による設計、またはそれと同等のアーキテクチャレベルの責務設計は、テスト責務を柔軟に移動させるアプローチにとって不可欠になります。
責務が肥大化した機能やレイヤ横断実装はテストが難しいし、責務の移動が難しくなるのはほんと同意
境界づけられたコンテキストを能動的に見出して、その入出力の型とテストに各々で責任を持つって感じかなkoushisa.icon
サービス指向アーキテクチャだとAPIテストやったりするし
テスト設計とアーキテクチャが開発組織を作るといっても過言ではないという話を思い出した
コンウェイの法則の力学も少なからず発生する
ここはボトムアップな設計手法を取ろうとすると難しい
関連
フロー効率とリソース効率から考えるチーム
アーキテクチャは課金体系が決める
テストを意識した方法論はTDD, BDDなどの文化がチームに浸透している必要性があると感じる
デプロイメントパイプラインの信頼性を挙げる
CI/CD
CI/CDのデプロイメントパイプラインの信頼性を挙げて、安全にテストレベル間でテストの責務を移動できるようにするのも重要です。
例えば各テストレベルで、各テストレベルのテスト条件(例えば対象のブランチ、バージョン、インテグレーション状態)を一致させるようにパイプラインを組むのは有効です。またテストレベルを移行する間のバグ混入を最小化するのも有効です。
アーキテクチャレベルで凝集性を上げ、結合性を下げる
例えば「コンポーネント間の結合部の並行処理のリスクを下げることで、システムを結合しないと再現できないバグを減らす」「コンポーネントの凝集度を上げ責務を明確化することで、多数のコンポーネントを横断させないとテストできない機能を減らす」といった設計の工夫の積み重ねが、テスト責務の移動を安全にします。
koushisa.iconの感想
言語化が難しかった箇所が代弁されてすっきりした
テスト設計パターンは大まかに4種類に分類できることが分かった
語彙が増えたkoushisa.icon*2
解像度が高いと手段の多様性が生まれる
QAとアーキテクチャは不可分で、凝集度を高め結合度を低くするという原則はやはり大事
テストピラミッドでもなくトロフィーでもなく、砂時計みたいな型が理想かも?と通ずる部分があった
積み上げ思考的なメモ TODO: あとで切り離す
まとめた→2023/04/25 フロントエンドのテスト設計とアーキテクチャ
---
以下はTLからの引用
@tkhrstw: 開発全員で読むべし内容。
モダンな開発スタイルの課題の本質はテストレベル設計にあるのかも。
@miwa719: どういう仕組みでシステムが動いているのか知らないとテストなんかできないんだぜ? というメッセージを受け取りました。わたしもそう思ってるからそう読んでしまうのかもしれないけど、テスターは設計や実装を知らなくてもいい(むしろ知るとよくない)みたいな考え方はこの記事によって滅びてくれ!!
@freddiefujiwara: なるほどテスト効率を向上させて開発生産性を高め開発スピードが重要な時代。本題とは関係ないですがFlutterへのE2E自動化はあまり便利ではないと感じたことが多いです。独自レンダラでRanorexも対応していないし、Autifyも対応していないみたいです。https://t.co/T3nTJs8EE8
仕方なく独自対応
#E2Eテスト
@trickmrbiz: テストを考えるうえで、ソフトウェアそのもののアーキテクチャや設計への理解が不可欠になってきたと日々実感しています。もっと設計を学ばないと…と思います。
@hide_ramen_san: 勢いで書けるところがすごいですけど、以前から色々考えてらしたのかもしれません。
とても分からりやすく書かれてますし重要なご指摘だと思います。
@hide_ramen_san: たぶん似たような問題意識はあるなかで、goyokiさんは現状を丁寧に分析して原則を説明してくれてますが、私のツイートはかなり雑に技術の進歩によってこっちの方向に進めるべきじゃないかと提案する感じですね。
@hide_ramen_san: なるほどとは思うんですが、入力バリデーションをシステムテストから結合テストに移行するメリットはあまりよくわからない。
ハッピーパスはシステムテストでやってバリデーションチェックを結合テストでやると二重管理になるデメリットもあるし、実行頻度もハッピーパスの方が多くなるべきはず。
#ハッピーパス #バリデーション #結合テスト
→ValidationもAIが担う