WCF(Windows Communication Foundation)は、マイクロソフトが.NETでサポートする通信手段の1つで、これを使えば簡単にインターフェイスを公開できる。WCFの詳細に関しては「Windows Communication Foundation概説」などを参照願いたい。
WCFを使う手法では、テスト対象アプリのコードも変更が必要である。変更の目的は、ビジネス・ロジックであるManagementSystemクラスを(WCFサービス経由で)外部から操作できるようにすることである。これは以下の実装で可能となる。
using System.ServiceModel;
……省略……
// WCFサービス公開用インターフェイスの定義。
[ServiceContract]
public interface IManagementSystem
{
[OperationContract]
bool Add(string name, string ageString, string post);
[OperationContract]
EmployeeData Find(string name);
}
// ManagementSystemクラスの定義を次のように変更する。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class ManagementSystem : IManagementSystem
{
……実装は変更なし……
}
// 外部からの要求でインターフェイスを公開。※説明しやすいように、ここに記述しているが、MainFormクラスはファイルの先頭に記述しないと、Windowsフォーム・デザイナでエラーが出るので注意してほしい。
public partial class MainForm : Form
{
……もともとの処理はそのまま……
// 以下が追加コード。
ServiceHost wcfHost = null;
public const int WM_OPEN_SERVER = 0x8000;
public const string WcfAddresses =
"net.pipe://localhost/EmployeeManagement.ManagementSystem";
// メッセージを受けると公開。
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_OPEN_SERVER)
{
wcfHost = new ServiceHost(system);
wcfHost.AddServiceEndpoint(typeof(IManagementSystem),
new NetNamedPipeBinding(), WcfAddresses);
wcfHost.Open();
m.Result = new IntPtr(1);
}
base.WndProc(ref m);
}
// 画面を閉じるときにはWCFサービスも閉じる。
protected override void OnClosed(EventArgs e)
{
if (wcfHost != null)
{
wcfHost.Close();
wcfHost = null;
}
base.OnClosed(e);
}
}
次に、先ほどWCFサービス経由で公開したインターフェイスを使ってManagementSystemクラスを操作するためのAPI(=EmployeeManagementAppクラス)を、クラス・ライブラリのプロジェクト内に実装する(ここでは、ソリューション内に「EmployeeManagementAPI」という名前のクラス・ライブラリ・プロジェクトを追加した)。
具体的には次のコードのように、Windowsフォームの社員管理アプリ(=EmployeeManagement.exeファイル)のWCFサービスに要求を出してインターフェイスを公開させ、それを取得して使うという手順になる。
using System;
using EmployeeManagement;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.Threading;
namespace EmployeeManagementAPI
{
public class EmployeeManagementApp : IDisposable
{
// 開始。
public static EmployeeManagementApp Start()
{
#if DEBUG
string path = Path.GetFullPath("../../bin/Debug/EmployeeManagement.exe");
#else
string path = Path.GetFullPath("../../bin/Release/EmployeeManagement.exe");
#endif
return new EmployeeManagementApp(Process.Start(path));
}
IManagementSystem managementSystem;
int processId;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
// コンストラクタ。
public EmployeeManagementApp(Process process)
{
processId = process.Id;
// メインウィンドウが完成するまで待つ。
while (process.MainWindowHandle == IntPtr.Zero)
{
process = Process.GetProcessById(process.Id);
Thread.Sleep(10);
}
// インターフェイス公開要求。
SendMessage(process.MainWindowHandle, MainForm.WM_OPEN_SERVER, IntPtr.Zero, IntPtr.Zero);
// インターフェイス取得。
managementSystem = new ChannelFactory<IManagementSystem>
(new NetNamedPipeBinding(), MainForm.WcfAddresses).CreateChannel();
}
// 終了。
public void Dispose()
{
Process.GetProcessById(processId).CloseMainWindow();
}
// 登録。
public bool Add(string name, string age, string post)
{
return managementSystem.Add(name, age, post);
}
// 検索。
public EmployeeData Find(string name)
{
return (EmployeeData)managementSystem.Find(name);
}
}
}
あとは、ソリューションに単体テスト・プロジェクト(ここでは「TestProject」とする)を新規追加して、そこに「リスト1 シンプルな受け入れテストのテスト・シナリオ(AcceptanceTest.cs)」で示したファイルを作成すれば完成だ(※このプロジェクトには、EmployeeManagementプロジェクト/EmployeeManagementAPIプロジェクトへの参照を追加する必要がある)。Visual Studioの[テスト エクスプローラー]などを使ってテストを実行すると、受け入れテストが実施される。
次にUIオートメーションを使う方法を説明しよう。
Copyright© Digital Advantage Corp. All Rights Reserved.