ソフトウェアテストのスムーズな導入
はじめに
第1回で解説したように、ソフトウェアテストによって開発を効率良く進めることはできますが、その取り入れ方も効果的なほうが良いでしょう。
そこで今回は、テスト自体による効果ではなく、テストの効果的な取り入れ方について解説します。
ソフトウェアテストの2つのアプローチ
ソフトウェアテストだけに限りませんが、何か活動を起こすときには「継続のしやすさ」が重要になります。現時点で皆さんが実施中の活動についてもそうですが、ソフトウェアテストに関する活動を起こし継続させていく際に障害が起きやすい始め方はできるだけ避けましょう。
筆者がこれまでの経験から見てきた障害で多かったものは、次の2つです。
- 興味がないものを無理やりやっておりモチベーションが上がらない
- マネジメントや決裁権を持っている人間から反対されて止められてしまう
これらは継続のしやすさを下げるものです。筆者はそれぞれに対するアプローチを組み合わせており、どのような強弱をつけるかは状況によって変化させています。
- 興味あるところからやる
- 最も効果が大きいところからやる
前者は導入するためのキッカケを低くでき、後者はマネジメント面で納得しやすい形にできます(図1)。
各アプローチの注意点
1. 興味のあるところからやる
どちらのアプローチでも、適用範囲には特に注意を払う必要があります。興味のあるところからやる場合には実践者のモチベーションを重要視しています。筆者の経験ではトレードオフとして周りの人、モノ、コトを変化させるのはまだまだ実験的な場合が多く、考慮不足も目立ちます。こういった状況を考慮して、新しい取り組みでうまくいかなくても、既存の枠組みでリカバリーできるような進め方にしましょう。
例えば、新しいパフォーマンステストツールを導入するときは、既存のツールや手法における前提条件、実行結果などの情報と同等(同程度の情報量)以上のものを残しておくことが重要です。
また、新しいツールを導入してある側面ではよい結果を得られても、別の側面でやりたいことが出来ない場合もあります。その場合には、準備しておいた情報によって既存手法など別の手段で解決していきます。うまくいかないときのリカバリーを考慮しておくことで、極端な失敗が減り再チャレンジするモチベーションを保ちやすくなりますし、周りからの理解も得やすくなります。
2. 最も効果が大きいところからやる
最も効果が大きいところからやる場合には、いわゆる「ROI」を重要視しています。筆者の経験ではトレードオフとして大きな権限が必要で、かつ影響範囲も大きい場合が多いです。こういった状況を考慮して、いろんな人と共通認識をつくる機会を増やして、手段にとらわれないような進め方にしましょう。
例えば、テストプロセスを変更するときは、関わる人それぞれで考えている効果の大きさの認識を合わせたり、できることではなくてやるべきことを議論したりしていきましょう。できることを基準にしてしまうと、新しい取り組みで躓いたときに出来ない理由を並べやすくなってしまいます。
課題とやるべきことを分析し計画していくことで、ゴールを見失わずに着実に効果を出していきやすくなります。
オススメは静的解析ツール/単体テストの自動化/CI
すでに何かやりたいことがある人は、小さいステップから試行錯誤して始めることになります。とは言え、「何をどうすれば良いか分からない」という状況もあるでしょう。ということで、筆者の「とりあえずこれをやってみよう」というオススメを紹介します。
「とりあえず、何かソフトウェアテストをやってみようかな」という人にとっては、普段使っているものと距離感が近いものから始めると学習コストを低く抑えられます。開発者の場合で距離感が近いのはプログラムに直接作用するものなので、おおむね次の3つでしょう。
静的解析ツールを使う
静的解析ツール(静的コードアナライザ)とは、「静的コード解析を実施するツール。ソースコードをチェックし、コーディング基準や品質メトリクスへの準拠度合、データフローの不整合などを検出する(ソフトウェアテスト標準用語集(日本語版)Version 2.3.J02)」ものです。
具体的にはプログラム中のネストしすぎた部分、絶対に実行されない部分、リソースリークする書き方をしている部分などを列挙してくれます。
Rubyでは「RuboCop」などがあるほか、Javaをはじめ複数の言語に対応する「SonarQube」などもあります。最近では、これらをサービス化した「SideCI」などにより環境構築の手間が減ってきています。
単体テストの自動化ツールを使う
テスト(実行)の自動化とは「テストの実行、実行結果と期待結果の比較、テスト条件の設定、その他のテストコントロールやレポート機能を(自動)制御すること(ソフトウェアテスト標準用語集(日本語版)Version 2.3.J02)」です。
言い換えると、テストの手順をプログラム化することです。これを支援するのが「テスティングフレームワーク」で、実行、結果比較、レポート機能などが備わっています。
Rubyでは「RSpec」Javaでは「JUnit」、JavaScriptでは「Mocha」や「Jest」があります。単体テスト(コンポーネントテスト)とは「個々のソフトウェアコンポーネントのテスト(ソフトウェアテスト標準用語集(日本語版)Version 2.3.J02)」のことです。具体的にはおおむね1つのファイルやクラスに対するテスト、もしくはいくつかのファイルやクラスをまたがったテストになります。
まずはテスティングフレームワークを使って自分達が開発したコードの一部のテストを自動化してみることで、意図したとおりに動作する範囲を何度も機械に判断してもらうことができます。
CIサーバを使う
CIサーバ(継続的インテグレーションサーバ)とは「プロダクトの各モジュールや設定などを統合(ビルド、デプロイ、テストなど)し、結果を通知することが主な役割のツール」です。
プログラムが更新される度、もしくは定期的にプログラムをコンパイル、静的解析、自動テスト実行、デプロイなどを行うことで、 動作するソフトウェアになっているか、問題がないかなどを常に確認しやすくなります。
「Jenkins」という汎用的なものから、サービスとして提供されている「CircleCI」や「Travis CI」などがあります。
最も効果的なところを見つけるためのオススメ
最も効果が大きいところからやるモチベーションがある人にとっては、課題の見つけ方や分析の方法が重要になってきます。手段よりも「どのような課題を解決するか」のほうが重要だからです。
そのための方法論として、既存プロセスのボトルネックを可視化する「Value Stream Mapping」があります。これから作るものをハッキリさせるという意味では要件定義の手法を使えますし、要件や活動自体の質の分類として「狩野モデル」を使えます。課題を識別した後には費用対効果、投資対効果を計算することで効率的に進めることができます。
その際には、それぞれの手法によって多角的に活動を計画できると良いでしょう。ただ、最初から計画通りに進めていけるだけの準備を整える必要があるかは、実践者のモチベーション次第だったり、進めるときの影響力次第だったりします。
場合によっては、いずれかの方法論だけを取り入れて大まかな方針を決めてから、徐々に他の視点を増やしていくという進め方もあります。
筆者はまず関係者と現状や課題に対する認識合わせから始めることが多く、そのためにValue Stream Mappingをよく使っています。Value Stream Mappingでは「マーケット(自分が価値を提供している相手)から要求がきて、それを解決するまでの流れ」で起きていること(ステップ)を見えるようにし、各ステップでのリードタイム(経過時間)と価値創造の時間(最終成果物をつくっている時間)を実績から割り当てます(図2)。
その結果、最もムダな時間を産んでいるステップがどこにあるかが見えるようになり、改善対象として更なる分析に繋げやすくなります。筆者はValue Stream Mappingを簡易的に使って、まずステークホルダーの認識合わせをしていくことから進めていくことが多いです。
「テストとして何をするか」を決めよう
現状を分析し、課題の構造やゴールを認識できたら、それらをテストによってどのように解決できるのかを考えてみます。テストではそのような大まかな方針を考えることを「テスト戦略」や「テスト計画」と呼んでいます。
テスト戦略とテスト計画について、書籍『ソフトウェアテスト293の鉄則』(日経BP社刊)では次のように定義されていますが、筆者としては「対象のテストのゴールとマネジメントについてまとめたもの」くらいの認識で使っています。
テスト計画は、テストの進め方(テストプロセス)の指針をまとめたものである。一方「テスト戦略」は、テスト設計の指針をまとめたものを指している。テスト戦略はテスト計画の一部であるとともに、テスト計画の良否を左右する。また、テストの目的と内容を結びつけるものでもある。(ソフトウェアテスト293の鉄則)
よく使われているテスト計画や戦略には、次のようなものがあります。
・Vモデル
「Vモデル」にはいくつかの定義があります。筆者としては次のようにプロセスの各ステップに対応したテストを設計、実装していくことで段階的に必要十分なテストをしていく手法という認識です。
- 「要件定義」から「システムテスト」
- 「基本設計」から「統合テスト」
- 「詳細設計」から「単体テスト」
V&V(Verification and Validation)やISO12207などを参考にすると、いくつか具体例を見ることができます。
・継続的デリバリー
「継続的デリバリー」はテスト実行に関するプロセスを自動化し、常に顧客へ安全なソフトウェアをリリースできるようにすることです。
あるまとまりでプログラムの修正を終える度にコンパイル、静的解析、自動単体テスト、デプロイ、自動統合テスト、QA環境へのデプロイ、手動テスト、パフォーマンステストを自動化しておき、最後はワンクリックで本番環境へデプロイできるようにするというのが王道です。
・フロントローディング
「フロントローディング」はソフトウェア開発プロセスのいわゆる上流工程と言われる要件定義や概要設計において積極的なレビューやテスト設計をしていくことで、バグやムダを減らしていこうとするやり方です。
・リスクベースドテスト
「リスクベースドテスト」はソフトウェアテストをリスク分析とともに計画、設計、実施、フィードバックしていく方法です。リスクベースドテストにおけるリスク分析は大きく次の2つに分類されます。
- プランニングリスクの分析
- 技術的ソフトウェアリスク、ビジネス的ソフトウェアリスクの分析
これらに基づいて、ソフトウェアテストの進め方自体と、どのようなソフトウェアテストをどの順番(規則)で進めていくかを決めていきます。
おわりに
テストをやってみるときにはいろいろな視点があります。興味のあるところから徐々に始めていくのも良いですし、全体最適化を考えて最も効果のあるところから始めるのも良いでしょう。それぞれにメリットと特徴があります。
今回は、それぞれのアプローチで有用な手法を筆者の経験をもとにいくつか紹介しました。技術やツールに興味があるならばプログラムに近い部分から始めると楽しいので、テスティングフレームワークや静的解析ツールから入ると良いでしょう。マネジメント的な視点に興味があるなら、現状分析とテスト戦略の手法が適しているでしょう。
重要なのは、より良いシステム開発をすることです。何かの導入手順に縛られることなく、楽しんでいろいろな技術に卓越していくように進めていきましょう。