専門性を求められるテスト
はじめに
本連載では「開発を加速・効率化させるテスト」をテーマとしていますが、今回は少し視点を変えて「専門性を求められるテスト」について解説します。
専門性を求められるテストと聞くと、「開発者の自分には関係ない」という人もいますが、開発者にとっても知っておくことは非常に有益です。
「専門性を求められるテスト」ってどんなテスト?
ひとことでソフトウェアテストと言ってもさまざまな種類があります。本連載でも多様な側面からテストについて述べてきましたが、ここでは「テストタイプ」と呼ばれる側面から専門性を求められるテストを整理します。
まず、改めてテストタイプとは何かを確認してみましょう。
「コンポーネント又はシステムをテストするためのテスト活動をまとめたものであり、例えば機能テスト、使用性テスト、回帰テストなどのように特定のテスト目的に焦点を当てている。」(ソフトウェアテスト標準用語集(日本語版)Version 2.3.J02)」
テストタイプと似た言葉に「テストレベル」がありますが、テストタイプとは異なります。テストレベルでは、開発において段階的に詳細化したもの(例えば、要求、仕様、設計、コードと詳細化していきます)に対応してテストを段階的に統合していきます。具体的にはコンポーネントテスト(単体テスト、ユニットテストとも呼ばれます)、統合テスト(結合テスト、インテグレーションテストとも呼ばれます)、システムテスト、受入テストなどがテストレベルです。詳細化した開発側の粒度ごとにテストを積み上げていき、その対応関係をレベルとして整理したものです。
テストタイプは、さまざまなテストレベルの中で、特定のテスト目的によってまとめられたテストです。例えば、次のようなテストがテストタイプの具体例です。
- セキュリティテスト
- 使用性テスト
- 性能テスト
- 相互運用性テスト
- 信頼性テスト
上記で挙げたものに限りませんが、本稿では特にこれら「非機能テスト」について解説します。
非機能テストは、機能ではなく非機能の特性に注目してテストします。非機能テストは総じて機能テストよりも込み入っています。また、テストにより最終的な非機能の特性を確認するためには、一定以上にシステムが完成している必要もあります。昔ながらのシーケンシャルな開発プロセスではライフサイクルの終盤に行われることが多く、専門のテストチームがその役割を担うことも多いため、システムや製品をリリースする前の最終関門をイメージする人も多いのではないでしょうか。
セキュリティテストの例
セキュリティテストは、対象のシステムや製品がセキュアかをテストします。このセキュリティテストを例に、非機能テストの中身を見ていきましょう。
例えば、セキュリティテストのひとつに「ペネトレーションテスト」があります。これは、システムに対して客観的な立場から脆弱性の有無を調べるテストです。ペネトレーションテストを実施する人は、実際のシステムを攻撃する立場でシステムの外部からペネトレーション(侵入)できるか試みます。
このようなテストでは、実施者に高いセキュリティのリテラシーが必要になります。具体的には、システムに対してどのようものがセキュリティホールとなり得るかの知見を持ち、さまざまなツールを駆使しながら実際のシステムにセキュリティホールが存在するか確認しなければなりません。ペネトレーションテストで行うことはクラッカーと同じことなので、それを業務で実施する上での倫理感も重要です。また、セキュリティも非常に情報の変化が激しい世界なので、常に最新動向を把握しておかなければなりません。やっかいなのは、ある時点でペネトレーションテストを行って安全だったと判断しても、その後に発見された新しい脆弱性にも対処する必要があることです。
特に脆弱性の話になると、テスト対象は開発者が作っているアプリケーションだけではなくなります。利用しているライブラリやフレームワーク、アプリケーションが動作するOS、連携するデータベースなどのミドルウェア、さらにはネットワークプロトコルやネットワークデバイスなどの脆弱性も含まれます。このように、非機能テストは専門性を求められるものが少なくありません。特にペネトレーションテストは外部の専門会社に依頼して実施することも多いのが実情です。
ただ、ペネトレーションテストはシステムにおけるセキュリティ対応状況を知るための一側面でしかありません。開発者がペネトレーションテストを行うことはないとしても、セキュリティを高めるための役割を持たないわけではありませよね。「品質は上流で作り込む」とよく言われますが、開発の最初期段階からしっかりとセキュリティ要件を考慮しなければなりません。そしてセキュリティ要件を満たすような設計を考え、セキュアコーディングを実践するなどしっかりと意図を持って上流工程で品質を作り込んでいく必要があります。それは開発者の責務です。
最近では、静的解析ツールがセキュリティツールと呼ばれるように、コードレベルで数多く脆弱性を検出できます。また、ファジング(ファズテストとも呼びます。想定外の入力を与えてエラーや例外を監視することでソフトウェアの欠陥を発見する手法です。想定外の入力データを生成するためのデータ生成機をファザーと呼びます)により、信頼境界の外側にあるインターフェースに対して適切な入力値のバリデーションが行われているかを確認することも容易になってきています。
このように、開発者自身が非機能テストを実施することはなくても、開発者が明確な意図をもって作り込んだ結果を非機能テストで確認します。つまり非機能テストの内容を深く知ることは、裏返せば「開発者としてどのようなことに留意しておくべきか」を知ることともいえます。
非機能テストの情報を開発に活用する
従来のウォーターフォールに代表されるシーケンシャルな開発モデルは、いわばソフトウェア開発を製造業的なパラダイムで捉えたものといえます。つまり、製品をリリースすることが1つのゴールとなり、それ以降は保守工程と捉えるのです。
このような開発ではソフトウェアライフサイクルの各工程内で完結する組織形態を採用することが多く、各工程に専門性をもったチームが配置されます。特にシステムテストのテストレベルでは、専門性をもつテストチームがさまざまな非機能テストを担います。
しかし、一定以上システムが完成してから非機能テストを実施して欠陥が見つかっても、修正には非常に大きな手戻りが発生します。また、困ったことにこれら非機能に関する問題はソフトウェアやシステムの根幹に関わることも少なくありません。開発からテストまでの距離が遠いと、テストで得られた情報を活かすことが難しくなり、技術的な負債を溜め込みやすくなってしまいます。そのためにも、開発の初期段階から非機能の側面をしっかりと考えておくことが重要です。
また、ウォーターフォール的な開発ではリリースが1つのゴールなので、リリース前とリリース後には大きな壁があります。リリース後の保守段階で機能追加などを行うこともありますが、それはあくまで保守のためのものです。そこには積極性や迅速さよりも製品のライフサイクルが終わるまでの生命維持や延命的な色合いが濃くなります。
近年ではリリース後こそがより重要な位置を占めるシステムや製品が多くなってきています。リリース後に実際にユーザに使ってもらい、ユーザのニーズを積極的にシステムや製品にフィードバックし、サービスを継続的に育てていきます。
このような場合、もはや保守といった概念ではなく、常にシステムをアップグレードしていくため積極的に開発を繰り返していく必要があります。リリース前、リリース後といった区切りはなくなり、常にリリースし続けている状況です。つまり、仮にシーケンシャルな開発で各リリースまで一定の期間がかかるとしても、本質的には反復開発を行っていることにほかなりません。
そう捉えると、ともすれば開発工程の最終関門とも見られがちな非機能テストを現在の開発や次のリリースに向けて積極的に活用していくモチベーションが生まれます。また、開発により有益な情報をフィードバックするために、本番環境でさまざまな非機能テストを実行することも増えています。
その他の非機能テストの例
例えば、使用性テストでは開発の初期段階にプロトタイプを作り、実際に何人ものユーザを集めてその行動を観察します。また、特定のシナリオを実施したりする際にかかった時間や手順数などで使いやすさを測っています。
しかし、今日ではABテストのように実運用環境でテストを実施し、AとBそれぞれの環境における具体的なユーザ操作の結果から画面のデザインを選定することも珍しくありません。従来の使用性テストよりも、もっと迅速かつ直接的にフィードバックを得て、その情報を積極的に活用している例といえるでしょう。
相互運用性テストでは、よく多端末や多OS、多ブラウザといった環境上でテストを実施します。以前は多種多様な環境を用意すること自体がひと仕事でしたし、それぞれの環境でテストを実行するにも人力でカバーしていました。しかし、仮想化技術の発展とシステムテストにおける自動テストの普及により、さまざまな環境でE2Eテストを実施しやすくなりました。また、従来よりも高頻度で素早いフィードバックを得ることができます。さらに、インフラの準備とテスト実行を人力に依存しなくなるため、テストの分散並列化しやすいことも特徴的です。
性能テストでは、特定の環境における性能限界や限界状況における挙動などを確認します。その状況をシミュレートし、その際の情報を収集して分析することで性能要件を満たしているか確認します。多くの場合、環境を変更することは容易ではないので、本番環境で性能に関わる問題を発生させないためにも非常に注意深く行います。しかし、もし環境がクラウドならば緻密な性能テストよりもサーバを状況によって動的にスケールアウトすることで対処できるため、いかにスケールアウトしやすくするかに関心が移っています。
信頼性テストでは、Netflixのカオスエンジニアリングのようにプロダクション環境で意図的に障害や負荷を発生させ、自動復旧システムが動作するかをテストし続けているものすらあります。特にプロダクション環境で自ら積極的に破壊的な活動をし続けてサービス提供を止めないというビジネス上の価値を常に示し続けるといったことは、以前ではなかなか考え難いものでした。実際に高可用性が求められるシステムで冗長化や多重化構成を取っていても、いざ障害が起きた際にうまく動作せずにシステムダウンしてしまうといった事例は決して少なくありません。
まとめ
旧来のウォーターフォール的開発パラダイムでは、工程毎に組織と役割を細かく分けて専門性を持たせた弊害として、テストや品質という言葉がテストチームや品質保証部のようなあたかも他の誰かが気にしてくれているものに映りがちでした。しかし、昔からテストや品質は誰かの専権事項ではなく、ソフトウェアライフサイクルのステークホルダー全員で考えるべきものです。
特にWebシステムの領域では顕著ですが、DevOpsという言葉が示すように開発者が担う役割は非常に広くなっていますし、役割にも明確な境界はなくなってきています。そして、DevOpsがさらにBizDevOpsと呼ばれるように、よりビジネスも含めた繋がりと広がりが強調されるようになってきました。
継続性や迅速さを強く求められる時代においては、よりビジネスと開発と運用の連携が求められており、その中における開発の役割も従来のものから非常に広がっています。ソフトウェアこそが価値を決定づける時代において、このような変化はある意味当然の帰着ともいえるでしょう。
自分達が提供するサービスにおいて、何がビジネス上の価値なのかをより明確にし、その価値をシステムが常に提供し続けられるように作り、それが継続的に提供できていることを確認するためにテストを活用していくことがより重要な時代なのです。
おわりに
今回は、「専門性を求められるテスト」をキーワードに解説しました。
以前は開発から遠かったリリース近くに行われるような、ともすれば自分には関係ないと思っていたテストを、ビジネスに価値を提供するためにもっとテストを活用して開発を加速させるきっかけとしていただければ幸いです。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- 開発手法を徹底比較!アジャイル vs.ウォーターフォール
- さまざまな開発手法
- CNDT2021、大規模ウォーターフォール開発をクラウドネイティブにするためのヒントをNTTデータのエバンジェリストが解説
- 非ウォーターフォール・モデル
- エンタープライズモバイルに必要なアプリの品質とは?―Think IT Mobile Developer Seminar 2016レポート
- いろいろなプロセス ~V字モデルとスクラム~
- 開発プロセスモデル
- アジャイル開発とは?プロジェクト推進からチームビルディング、見積もりのコツまでを完全解説
- インフラの中核を担う「サーバ」を知ろう
- コンテナ開発へのDevSecOpsの適用