Windowsアプリの受け入れテストを自動化しよう:特集:受け入れ検査の自動化手法の考察(2/5 ページ)
単体テストの次は、エンド・ユーザーへの納品時の受け入れテストも自動化したい? それを実現する手法を紹介する。
受け入れテスト用のAPIを作成する
●インターフェイス設計
今回作成するAPIは、前述したようにアプリをGUIからではなく、プログラムから操作するためのユーティリティである。APIの目的は「操作」であり「テスト」ではない。逆にテスト・シナリオの目的は「テスト」であり「操作」ではない。少なくともこれがはっきり分離されるように設計しなければならない。また、アプリの内部実装を知らないテスト担当者でも、APIを使ってテスト・シナリオを実装できるようにすべきである。
ここで公開するインターフェイスの品質で、テスト・シナリオの可読性が決まる。逆説的ではあるが、良いテスト・シナリオが書けるなら、それは良いAPIだといえる。この辺は「ユニット・テストが作りやすいコードが、一般的に良いコードになる」という理論に近い。とはいえ、一度で決定できるような簡単なものではないので、プロダクト・コード同様、リファクタリングを繰り返しながら、インクリメンタルに質を高めていくべきである。
●インターフェイスの実装
本稿では、APIは.NETのDLLとして実装する。このようにしてCLS(共通言語仕様)に準拠していれば複数の.NET系言語から使用できるので、テスト・シナリオを記述するときに、テスト担当の得意な言語を選択できるというメリットがある。
実装方法は自由で、とにかく対象アプリをインターフェイスの要求どおりに操作できればよい。GUIコントロールを操作することで、要求に応えてもよいし、特殊なテスト用インターフェイスを対象アプリに仕込んでそれを呼び出してもよい。
次章以降ではサンプルを使って、この実装方法を説明する。
コラム:ATDD(受け入れテスト駆動開発)
アジャイル・コミュニティでも、簡易スクリプトなど、GUI以外から操作する手段を用意して、受け入れテストを自動化する方法を紹介している。
また、ATDD(Acceptance Test Driven Development: 受け入れテスト駆動開発)として、先にテスト・シナリオを書く手法もある。先に受け入れテストを書いた場合、テスト対象のロジックはスクリプトからも呼び出せる必要があり、必然的にGUIから分離されるという考え方である。
本稿で紹介している方法は簡易スクリプトではなくAPIを用いてテスト・プロセスからアプリを操作するというものだが、本質的には同じアプローチである。
この手法になじんできたら、ATDDにもチャレンジしてみてはいかがだろうか。
テスト対象とテスト・シナリオの準備
●社員管理アプリ
今回、サンプルとして作成するアプリのGUIは次のような画面にする。これはWindowsフォーム・アプリとして作成している。
社員管理アプリのGUI
各コントロールは以下のとおり。
・[名前]欄: テキストボックス。名前は「textBoxName」
・[年齢]欄: テキストボックス。名前は「textBoxAge」
・[役職]欄: テキストボックス。名前は「textBoxPosition」
・[登録]欄: ボタン。名前は「buttonAdd」
・[検索]欄: ボタン。名前は「buttonFind」
この社員管理アプリがテスト対象となる。GUIの動作仕様は以下のとおり。
- [名前]/[年齢]/[役職]を入力して[登録]ボタンを押すと、そのデータが登録される
- 登録が成功すると、テキストボックスがクリアされる
- 登録時に、年齢が数値でない場合は失敗する
- 登録時に、すでに登録されている名前を指定すると失敗する
- [名前]を入力して[検索]ボタンを押すと、登録されている名前なら[年齢][役職]が表示される
- 検索に失敗するとテキストボックスがクリアされる
そのコードは、次のとおり。メイン・ウィンドウとして表示されるWindowsフォームはMainFormクラスに実装する。ビジネス・ロジックはManagementSystemクラスに実装する。今回は、ManagementSystemクラスを結合状態で受け入れテストすることを目標とする。なお、この内容であれば、本来、ユニット・テストで十分なのだが、そこはサンプルということでご容赦願いたい。
using System;
using System.Windows.Forms;
using System.Collections.Generic;
namespace EmployeeManagement
{
// GUI。
public partial class MainForm : Form
{
ManagementSystem system = new ManagementSystem(); // ビジネス・ロジック用のクラス
public MainForm()
{
InitializeComponent();
}
// 追加ボタン押下。
private void buttonAdd_Click(object sender, EventArgs e)
{
if (system.Add(textBoxName.Text, textBoxAge.Text, textBoxPosition.Text))
{
//成功した場合はテキストボックスを空にする。
textBoxName.Text = textBoxAge.Text = textBoxPosition.Text = string.Empty;
}
}
// 検索ボタン押下。
private void buttonFind_Click(object sender, EventArgs e)
{
EmployeeData hit = system.Find(textBoxName.Text);
// GUIに表示。
if (hit != null)
{
//ヒットした場合はデータを表示。
textBoxName.Text = hit.Name;
textBoxAge.Text = hit.Age.ToString();
textBoxPosition.Text = hit.Post;
}
else
{
//失敗したらテキストボックスを空にする。
textBoxName.Text = textBoxAge.Text = textBoxPosition.Text = string.Empty;
}
}
}
// 社員データ。
[Serializable]
public class EmployeeData
{
public string Name { get; set; }
public int Age { get; set; }
public string Post { get; set; }
public EmployeeData(string name, int age, string post)
{
Name = name;
Age = age;
Post = post;
}
}
// ビジネス・ロジック。
public class ManagementSystem
{
List<EmployeeData> allData = new List<EmployeeData>();
// 追加。
public bool Add(string name, string ageString, string post)
{
// 数値化できない場合はNG。
int age;
if (!int.TryParse(ageString, out age))
{
return false;
}
// 名前の重複は許容しない。
if (Find(name) != null)
{
return false;
}
allData.Add(new EmployeeData(name, age, post));
return true;
}
// 検索。
public EmployeeData Find(string name)
{
foreach (EmployeeData element in allData)
{
// 名前で検索。
if (element.Name == name)
{
return element;
}
}
return null;
}
}
}
●テスト・シナリオ
テスト・シナリオは最初に例示した「リスト1 シンプルなテスト・シナリオ」を使う。
実行環境はVisual Stuido 2010のテスト・プロジェクトを使用する。
●API
今回はテスト・プロセスで動作するクラスとして「EmployeeManagementApp」を作成する。このクラスは、社員管理アプリの起動/終了/操作を目的とする。その実装方法は下記のようにいくつか考えられる(※最後の「Codeer.Friendly」についての詳細は後述するが、今回のケースのような受け入れテストを簡単に実装できるようにするために筆者の会社が開発して無料で公開しているライブラリである)。
- WCFを使ってAPIを実装する
- UIオートメーションを使ってAPIを実装する
- Codeer.Friendlyを使ってAPIを実装する
そこで、次章以降でそれぞれの実装サンプルを例示する。
Copyright© Digital Advantage Corp. All Rights Reserved.