nimbus (1.2.4) | 2018-01-25 20:02 |
nimbus-sample (1.2.4) | 2018-01-26 17:06 |
アプリケーション開発において、テストの生産性と品質は重要です。Nimbusでは、テストの自動化を支援するテストフレームワークを提供します。
通常、テスト工程と言えば、単体テスト、連結テスト、総合テスト、ユーザ受け入れテストなど、モジュールの連結度、環境、観点などから、複数の工程に分けて、積み上げテストを行います。
単体テストでは、いわゆる最小単位のモジュールレベルで、周りのモジュールをモック化して入力と出力のテストを行います。
単体テストの利点は、最小単位で行うため、1つ1つのテスト対象が小さく、周りのモジュールはモックであるため、全ての外部的な条件が整えやすく、ホワイトボックス(全網羅)テストが行えることです。また、周りのモジュールをモック化するため、周りのモジュールの開発状況の影響を受けずに、テストすることができます。
欠点は、見ている範囲が狭いため、システム全体としてありえる状態の考慮ができないため、そのモジュールとしてあり得る条件を全て網羅することになり、無駄に多くのテストを実施することになってしまいます。また、そのモジュール単体での要件仕様をテストするため、要件仕様自体の問題や間違いに気づく事が困難です。
連結テストでは、何らかの単位でモジュールを連結させて(連結させない部分は、結局モック化する)、入力と出力のテストを行います。
連結テストの利点は、モジュールが連結され、あり得る入出力の条件がより明確になるため、無駄なテストが減る事と、単体モジュール毎の要件仕様に間違いがなかったのかの確認が行えることです。
欠点は、連結対象のモジュールの開発状況を足並み揃える必要があることと、あり得る入出力の条件が絞られることで、各モジュールのホワイトボックステストを行うことが困難になり、ブラックボックステストになるため、テストの網羅性を外部観点のみで保証する必要があり、テストケース立ての難易度があがることです。また、テストをした結果、出力がNGな場合に、どこのモジュールに問題があるのかを切り分ける作業が必要になることです。
これ以降のテストは、基本的にモックが排除され、運用を意識したテストや、基盤を意識したテストが追加されたり、環境やテスト実施者が変わるなどしますが、基本的に実運用にそった形でシステムを稼働させ、手作業での確認作業を行うことになります。
従って、テストの自動化を行うのであれば、単体テスト及び連結テストまでが対象となります。
しかし、昨今のEOD(Ease of Developement)や、アジャイル開発などの流れから、システム開発は簡略化され、スケジュールも圧縮されてきています。それにより、モジュールの細分化が極力抑えられた設計が行われ、分割されたとしても、一連のモジュールは、同一の開発者が担当する事が多く、単体テストのメリットが減り、連結テストのデメリットも減ってきました。また、単体テストと連結テストのある意味、冗長なコストを掛けたテスト工程の積み上げを行う、スケジュールやコストが取れないという現実的な問題もあります。
そこで、Nimbusテストフレームワークでは、単体テストではなく、サーバ単位レベルでのサーバ内のモジュール連結以降の連結テストを対象とします。
テストにおいて、あるテストケースを実施するために、他のテストケースの実施が前提になる場合があります。そのように連続した複数のテストケースをひとまとまりにしてテストする場合、そのかたまりをシナリオと呼びます。
それをふまえて、Nimbusテストフレームワークでは、テストケースの概念を3階層で定義します。最下層がテストケース、テストケースを1連の流れとしてまとめるシナリオ、シナリオを意味的にまとめるシナリオグループです。
シナリオグループ1 | ||
シナリオ1 | ||
テストケース1 | ||
テストケース2 | ||
シナリオ2 | ||
テストケース1 | ||
テストケース2 | ||
シナリオグループ2 | ||
シナリオ1 | ||
テストケース1 | ||
テストケース2 | ||
シナリオ2 | ||
テストケース1 | ||
テストケース2 |
ここで、一般的なテストフレームワークがどうなっているかを考えてみましょう。
一般的なテストフレームワークでは、テストの入力データをプログラム的に生成し、テスト対象のモジュールを呼び出し、その出力データをプログラムで検証します。また、テスト対象自体が呼び出すモジュールをプログラム的なモックで実装することで、モックへの入力データを検証し、出力データを返します。
これは、テスト対象が、基本的に単体テストであり、モジュールの開発者=テスト開発者(少なくともプログラマ)であることが前提になっています。また、さらに言えば、テストコード自体がプログラムであることから、テストレビューア=プログラマ(=もしかしたらモジュールの開発者)であることが、暗に要求されています。また、テストレビューアがプログラマであれ、プログラムで書かれた検証ロジックの妥当性を評価するのは、骨の折れる作業です。
しかし、エンタープライズな開発においては、モジュールの開発者=テスト開発者までは許容できても、テストレビューア=プログラマは、場合によっては困難かもしれませんし、テストレビューア=モジュールの開発者はあり得ません。つまり、求められているのは、モジュールの開発者=テスト開発者(でなくてもよい)かつ、テストレビューア=設計者(少なくともプログラマではない)です。
テストフレームワークで、このような関係性にするためには、テスト対象に対する入力(モックの出力も含む)をプログラムではなく、データとして表現できることが必要になります。また、テスト対象の出力(モックに対する入力も含む)をデータとして検証できることも必要となります。
それにより、テストレビューア=設計者(プログラマではない)を可能にします。
そこで、Nimbusテストフレームワークでは、テストの事前準備、テストの実行、テストの結果検証などを部品化し、部品に対する入力をデータファイルで渡し、出力もデータファイルで取得し、出力されたデータファイルを人間が目で検証する事で正当性を保証し、2度目以降のテストでは、検証したファイルをエビデンスとすることで、Diffを取り自動検証する方式を採用しました。
従って、Nimbusのテストフレームワークを使ったテストケース開発では、以下のような作業の流れになります。
Nimbusのテストフレームワークを機能分解すると、以下のようになります。
関連するパッケージは、以下です。
テストを実行するユーザインタフェースを提供する機能が、TestRunnerです。
TestRunnerは、ユーザのテスト実行要求に対して、TestControllerとやり取りを行い、テストを実行します。
TestRunnerクラスの一覧は以下のとおりです。
クラス | 概要 |
jp.ossc.nimbus.service.test.TestRunner | テスト実行定義ファイルを読み込み、コマンドラインでテストを自動実行するクラスです。 |
jp.ossc.nimbus.service.test.swing.TestSwingRunner | SwingのGUI画面をユーザが操作することでテストを実行するクラスです。 |
テスト全体を制御する機能を抽象化したのがTestControllerインタフェースです。
テストコントローラは、テストの開始を要求されると、テストリソース管理から、シナリオグループ/シナリオ/テストケースのテストリソースを取得します。
また、テストリソースに、スタブ向けのリソースが含まれている場合は、スタブリソース管理を経由して、テストスタブにリソースを配布し、テストスタブにテストの開始を通知します。
テストリソースに定義されているテストアクションやテスト検証アクションを実行することで、テストの事前準備や、テストの実施、テスト結果の検証を行います。
TestControllerインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.TestControllerService | デフォルト実装サービスです。 |
jp.ossc.nimbus.service.test.HttpTestControllerClientService | テスト用のサーバに配置したHttpTestControllerServerServiceとHTTP通信を行い、サーバ上のTestControllerServiceを制御する実装サービスです。 |
テストを実行するために必要なシナリオグループ/シナリオ/テストケースのリソース定義を提供する機能を抽象化したのが、TestResourceManagerインタフェースです。
TestResourceManagerインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.resource.LocalTestResourceManagerService | ローカルのディスク上からリソース定義を提供する実装サービスです。 |
jp.ossc.nimbus.service.test.resource.CVSTestResourceManagerService | CVSサーバ上からリソース定義を提供する実装サービスです。 |
jp.ossc.nimbus.service.test.resource.GitTestResourceManagerService | Gitサーバ上からリソース定義を提供する実装サービスです。 |
jp.ossc.nimbus.service.test.resource.SVNTestResourceManagerService | SVNサーバ上からリソース定義を提供する実装サービスです。 |
テストに必要な処理を行う機能を抽象化したのがTestActionインタフェースです。
TestActionインタフェースの実装サービスの一覧は、以下のとおりです。
テストに必要な検証処理を行う機能を抽象化したのがEvaluateTestActionインタフェースです。
EvaluateTestActionインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.evaluate.TextEvaluateActionService | テキストファイルを検証するテスト検証アクションです。 |
jp.ossc.nimbus.service.test.evaluate.TextCompareEvaluateActionService | 2つのテキストファイルを比較検証するテスト検証アクションです。 |
jp.ossc.nimbus.service.test.evaluate.CSVCompareEvaluateActionService | 2つのCSVファイルを比較検証するテスト検証アクションです。 |
jp.ossc.nimbus.service.test.evaluate.BinaryCompareEvaluateActionService | 2つのバイナリファイルを比較検証するテスト検証アクションです。 |
jp.ossc.nimbus.service.test.evaluate.ServiceLoadActionService | Nimbusのサービス定義をロードして、正しくロードできたかを検証するテスト検証アクションです。 |
jp.ossc.nimbus.service.test.evaluate.ScheduleWaitActionService | ScheduleManagerを使って、スケジュールが想定通り終了したかを検証するテスト検証アクションです。 |
テストアクションを連鎖させることで、複数のテストアクションを論理的にひとかたまりに扱う機能を抽象化したのがChainTestActionインタフェースです。
ChainTestActionインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.ChainTestActionService | デフォルト実装のテスト検証アクションです。 |
テストアクションを連鎖させ、最後にテスト検証アクションで検証することで、連鎖テストアクションの機能性とテスト検証アクションの機能性を兼ね備えるような機能を抽象化したのがChainEvaluateTestActionインタフェースです。
ChainEvaluateTestActionインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.ChainEvaluateTestActionService | デフォルト実装の連鎖テスト検証アクションです。 |
テストアクションやテスト検証アクションを連鎖させ、最後にテスト検証アクションで検証し、途中の検証または最後の検証がNGの場合はリトライできる機能を抽象化したのがRetryEvaluateTestActionインタフェースです。
RetryEvaluateTestActionインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.RetryEvaluateTestActionService | デフォルト実装のリトライ連鎖テスト検証アクションです。 |
テストコントローラからスタブとして制御可能になるような機能を抽象化したのがTestStubインタフェースです。
テストスタブは、テストコントローラから、テストの開始イベントを受け取ると、スタブリソース管理を経由して、スタブとして応答すべき出力データを受け取ります。その後、テスト対象からの要求を受け取ると、要求内容を入力データとして記録し、出力データを応答します。次に、テストの終了イベントを受け取ると、テスト対象からの要求内容たる入力データを、スタブリソース管理を経由して、テストコントローラに渡します。
TestStubインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.stub.http.HttpTestStubService | HTTPサーバのスタブ実装です。 |
jp.ossc.nimbus.service.test.stub.tcp.TCPTextTestStubService | TCPプロトコルでテキストベースのデータプロトコルを持つサーバ(SMTPなど)のスタブ実装です。 |
テストコントローラとテストスタブ間のデータのやり取りを中継する機能を抽象化したのがStubResourceManagerインタフェースです。
StubResourceManagerインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.resource.LocalStubResourceManagerService | ローカルのディスクを経由してリソースを中継する実装です。 |
テンプレート言語で書かれたテンプレートファイルと、データファイルをテンプレートエンジンでマージしてファイルを出力する機能を抽象化したのがTemplateEngineインタフェースです。
テンプレート言語と、データファイルのフォーマットは、実装クラスに依存します。
TemplateEngineインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.resource.VelocityTemplateEngineService | Apache Velocityを使った実装です。 |
テストに関するレポートを出力する機能を抽象化したのがTestReporterインタフェースです。
TestReporterインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.report.ConsoleTestEstimateReporterService | テストの見積もりを標準出力に出力するテストレポーター実装です。 |
jp.ossc.nimbus.service.test.report.CSVTestEstimateReporterService | テストの見積もりをCSVファイルに出力するテストレポーター実装です。 |
jp.ossc.nimbus.service.test.report.HtmlTestCaseProgressReporterService | テストの進捗をHTMLファイルに出力するテストレポーター実装です。 |
jp.ossc.nimbus.service.test.report.MSProjectTestReporterService | テストの進捗をMicrosoft Projectで読み込めるXMLファイルに出力するテストレポーター実装です。 |
jp.ossc.nimbus.service.test.report.ConsoleTestReporterService | テスト実行結果を標準出力に出力するテストレポーター実装です。 |
jp.ossc.nimbus.service.test.report.CSVTestReporterService | テスト実行結果をCSVファイルに出力するテストレポーター実装です。 |
jp.ossc.nimbus.service.test.report.HtmlTestReporterService | テスト実行結果をHTMLファイルに出力するテストレポーター実装です。 |
ネットワーク通信をプロキシして、通信エラーを疑似する機能を抽象化したのがNetProxyインタフェースです。
NetProxyインタフェースの実装サービスの一覧は、以下のとおりです。
実装サービス | 実装概要 |
jp.ossc.nimbus.service.test.proxy.netcrusher.TcpNetProxyService | TCP通信をプロキシする実装です。 |
サンプルは、以下。