システムテスト 自 動 化 プログラムにおける 操 作 技 術 と シナリオ の 分 割 発 表 者 石 川 達 也 ( 株 式 会 社 Codeer) e-mail:ishikawa-tatsuya@codeer.co.jp 共 同 執 筆 者 堅 田 成 洋 ( 株 式 会 社 ベリサーブ) e-mail:naruhiro.katada@veriserve.co.jp
2 自 己 紹 介 石 川 達 也 株 式 会 社 Codeer 代 表 取 締 役 Microsoft MVP (2014~) Windowsアプリテスト 自 動 化 歴 10 年 テスト 自 動 化 ライブラリFriendly 作 者 堅 田 成 洋 株 式 会 社 ベリサーブ 組 み 込 みソフト 第 三 者 検 証 暦 10 年 テストのスペシャリストとして 数 々のプロジェクトを 成 功 に 導 く 本 稿 で 紹 介 する 手 法 をテストチームのリーダーとして 経 験 ( 約 2 年 )
3 アジェンダ 1. 資 料 背 景 2. 問 題 3. 分 割 4. 改 善 実 例
4 1. 資 料 背 景 1. 資 料 背 景
5 1. 資 料 背 景 株 式 会 社 Codeerは 様 々な 企 業 プロジェクトで Windowsアプリのシステムテスト 自 動 化 支 援 を 実 施 している 今 回 の 発 表 はそこでの 実 績 に 基 づいている 今 回 示 す 改 善 は 手 動 テスト 自 動 テストではなく 成 果 の 出 ていない 自 動 テスト 成 果 の 出 る 自 動 テスト Power up! テスト 対 象 と 自 動 化 のために 使 った 環 境 は 以 下 のもの テスト 対 象 Windowsアプリ 自 動 化 プログラム 開 発 環 境 Visual Studio 自 動 化 プログラム 言 語 C# 操 作 用 ライブラリ Friendly
6 2. 問 題 点 2. 問 題 点
7 2. 問 題 点 システムテスト 自 動 化 は 困 難 なプラクティスである 改 善 前 のお 客 様 から 聞 く 話 は タイミング 依 存 でテストが 失 敗 する 実 行 時 間 が 長 いので 頻 繁 には 実 行 できない 保 障 されている 範 囲 が 少 ない また 不 明 確 担 当 者 不 足
8 2. 問 題 点 改 善 前 のテストプログラム 例 [TestMethod] public void Test() { //プロセス 起 動 var process = Process.Start("EmployeeManagement.exe"); //プロセスを 操 作 できるようになるまで 待 つ Thread.Sleep(1000); //フォーム 取 得 var mainform = AutomationElement.FromHandle(process.MainWindowHandle); //ボタンを 取 得 var buttonadd = mainform.findfirst(treescope.element TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "_buttonadd")); タイミングを 時 間 で 調 整 対 象 アプリの 初 期 化 についての 知 識 が 欠 落 安 易 なSleepは 時 間 の 無 駄 も 招 く 仮 に1ケース5 秒 ロスすると5000ケースだと 約 7 時 間 無 駄 になる 内 部 仕 様 ( 変 数 名 )が テストシナリオに 出 てきている //ボタンクリック 実 行 var addinvoker = (InvokePattern)buttonAdd.GetCurrentPattern( InvokePattern.Pattern); addinvoker.invoke(); タイミングを 時 間 で 調 整 ウィンドウの 表 示 までに 関 する 知 識 が 欠 落 // 次 の 画 面 を 待 つ Thread.Sleep(1000); var addformhandle = GetWindow(process.MainWindowHandle, (uint)getwindow_cmd.gw_hwndprev); var addform = AutomationElement.FromHandle(process.MainWindowHandle); // 次 の 画 面 要 素 取 得 var textname = addform.findfirst(treescope.element TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "_textboxname")); // 次 の 画 面 の 操 作 (コード 量 多 い) 全 体 的 に 複 雑 すぎて テスト 内 容 が 分 からない
9 2. 問 題 点 テスト 自 動 化 には ソフトウェアテストのスキル ソフトウェア 開 発 のスキル の 両 方 が 必 要 これを 理 解 して 設 計 管 理 する 必 要 がある 多 くの 場 合 自 動 操 作 プログラム 作 成 がボトルネックになっている C# テスト 自 動 操 作 プログラムの 開 発 ボトルネック
10 3. 分 割 3. 分 割
11 3. 分 割 テストと 操 作 に 必 要 な 技 術 は 全 く 別 もの 分 割 することにより それぞれのスペシャリストで 作 業 を 分 担 できる シナリオ 設 計 作 成 に 必 要 な 知 識 境 界 値 分 析 法 同 値 分 割 法 状 態 遷 移 テスト 全 ペアテスト 原 因 結 果 グラフ デシジョンテーブル エラー 推 測 統 計 的 テスト etc 信 頼 性 高 く 品 質 を 保 証 するには 専 門 的 なテスト 技 術 が 必 要 操 作 に 必 要 な 知 識 Win32API.Netの 知 識 メッセージループ 画 面 遷 移 スレッド プロセス 画 面 要 素 のツリー 構 造 対 象 アプリの 内 部 設 計 etc 安 定 高 速 な 操 作 を 実 現 するには 高 度 な 開 発 技 術 が 必 要
12 3. 分 割 AppDriver アプリケーションドライバーのレイヤを 作 った テストシナリオ 強 力 に 操 作 内 部 仕 様 技 術 的 なことを 隠 蔽 アプリケーションに 特 化 した シンプルなインターフェイスを 提 供
13 3. 分 割 AppDriver 担 当 とボリュームイメージ 小 アプリケーションドライバ 技 術 的 な 部 分 は 難 易 度 は 高 いが ボリュームは 小 さい 開 発 チームが 担 当 大 シナリオ 技 術 的 な 難 易 度 は 低 いが 品 質 を 保 証 するためにある 程 度 の ボリュームが 必 要 になってくる テスト 設 計 も 含 めてテストチームが 担 当
14 3. 分 割 AppDriver - Interface アプリケーションドライバのインターフェイスは 外 部 仕 様 を 知 っていれば 操 作 可 能 な 設 計 にした ( 内 部 仕 様 はインターフェイスには 現 れない) [TestMethod] public void 追 加 テスト() { var mainform = App. 社 員 管 理 ; // 追 加 ボタンを 押 したらモーダルダイアログが 出 る var addform = mainform.button_ 追 加.EmulateClick(); // 追 加 画 面 の 操 作 addform.textbox_ 名 前.EmulateChangeText(" 山 田 "); addform.textbox_ 住 所.EmulateChangeText(" 大 阪 "); addform.radiobutton_ 男.EmulateCheck(); addform.button_ 登 録.EmulateClick(); } // 元 の 画 面 でデータチェック Assert.AreEqual(" 山 田 ( 男 ) 大 阪 ", mainform.listbox_ 社 員.GetItemText(0));
15 3. 分 割 AppDriver - Interface VisualStudioのインテリセンスを 最 大 限 に 活 用 できる 設 計 にした [TestMethod] public void 追 加 テスト() { var mainform = App. 社 員 管 理 ; // 追 加 ボタンを 押 したらモーダルダイアログが 出 る var addform = mainform.button_ 追 加.EmulateClick(); // 追 加 画 面 の 操 作 addform..(ドット)を 打 つことにより 次 に 選 択 するべきコードが 候 補 表 示 される 日 本 語 を 交 えることにより 作 業 効 率 が 上 がることが 経 験 的 に 確 認 されている
3. 分 割 AppDriver - Interface インターフェイスも 用 途 に 合 わせて 複 数 作 った //GUIを 意 識 させるインターフェイスで 作 成 [TestMethod] public void 追 加 テスト() { var mainform = App. 社 員 管 理 ; var addform = mainform.button_ 追 加.EmulateClick(); addform.textbox_ 名 前.EmulateChangeText(" 山 田 "); addform.textbox_ 住 所.EmulateChangeText(" 大 阪 "); addform.radiobutton_ 男.EmulateCheck(); addform.button_ 登 録.EmulateClick(); Assert.AreEqual(" 山 田 ( 男 ) 大 阪 ", mainform.listbox_ 社 員.GetItemText(0)); } GUIレベルで 細 かく 確 認 する 場 合 GUI 仕 様 が 変 わると シナリオもメンテの 必 要 がある // 機 能 を 意 識 させるインターフェイスで 作 成 [TestMethod] public void 追 加 () { App. 機 能. 追 加 (new EmployeeData() { Name = "", Address = "", IsMan = true}); } 機 能 が 動 くことを 確 認 する 場 合 テスト 対 象 外 の 操 作 の 場 合 ( 前 提 条 件 を 満 たすための 操 作 ) 上 記 の 操 作 が 隠 蔽 されているので GUI 仕 様 が 変 わっても 変 更 の 必 要 はない 16
17 3. 分 割 AppDriver - Interface これらの 工 夫 により テストチームのメンバ ( 本 職 のプログラマではない)でも 安 定 高 速 動 作 し メンテナンス 性 の 高 い テストシナリオを 作 成 できることを 確 認 している シナリオは 大 量 に 作 るが 可 読 性 メンテナンス 性 の 高 い 状 態 を 維 持 担 当 者 も 増 員 可 能 な 状 態
3. 分 割 AppDriver - Implement アプリケーションドライバの 実 装 は 開 発 者 で 実 施 する 対 象 プロセスの 内 部 設 計 実 装 を 熟 知 しているので 安 定 した 操 作 を 提 供 できる テストを 安 定 動 作 させる 責 務 はこちらにある 操 作 を 提 供 する 層 であり テスト 内 容 は 入 り 込 まない public class 社 員 管 理 _Driver { public FormsListBox ListBox_ 社 員 { get; set; } public IClickable< 追 加 _Driver> Button_ 追 加 { get; set; } public IClickable< 検 索 _Driver> Button_ 検 索 { get; set; } public 社 員 管 理 _Driver(WindowControl window) { ListBox_ 社 員 = new FormsListBox(window.Dynamic()._listBoxEmployee); 内 部 仕 様 を 知 っているので 安 定 して 要 素 を 特 定 } } Button_ 追 加 = new FormsButton(window.Dynamic()._buttonAdd). MakeModal((w, a) => new 追 加 _Driver(w, a)); 画 面 遷 移 の 詳 細 を 把 握 している ので 安 定 した 方 法 で Button_ 検 索 = new FormsButton(window.Dynamic()._buttonAdd). 次 の 画 面 を 取 得 MakeModal((w, a) => new 検 索 _Driver(w, a)); 18
19 3. 分 割 AppDriver - Implement アプリケーションドライバの 実 装 にはFriendlyをお 勧 めしています 別 プロセスから 内 部 APIを 呼 び 出 し 可 能 アプリケーション 開 発 に 必 要 な 技 術 力 が 必 要 その 技 術 力 をテスト 時 に 操 作 に 活 かしきることができる http://www.codeer.co.jp/autotest
20 4. 改 善 実 例 4. 改 善 実 例
21 4. 改 善 実 例 某 社 の 業 務 システム 不 安 定 な 作 りであったので 実 施 時 に 人 手 のコストが 発 生 していた 待 ち 合 わせのSleepが 大 量 に 入 っていた (ネットワークの 待 ち 合 わせもあるため 長 い) 量 は 少 ないがトータル2 時 間 かかっていた テストの 成 功 がリリースの 条 件 になっていたので リリース 時 の 負 荷 が 大 きかった
22 4. 改 善 実 例 作 成 メンテナンス 性 の 向 上 正 しく 分 割 することにより 自 然 とコードの 共 通 化 が 進 んだ 行 数 としては 半 分 程 度 に 安 定 化 と 高 速 化 安 定 動 作 するインターフェイスを 提 供 することに よって テストケース 内 のSleepは 全 て 削 除 改 善 前 は2 時 間 かかっていたテストが 改 善 後 で は15 分 で 完 了 するようになった また 実 行 するたびに 人 手 のコストが 発 生 して いた 問 題 も 解 消 リリースもスムーズに 行 えるようになった
23 4. 改 善 実 例 某 社 パッケージソフト 複 雑 なテスト 用 操 作 高 い 技 術 力 で 安 定 動 作 はさせていた テストチームの 入 り 込 む 余 地 なし 網 羅 性 などテストとしての 品 質 に 不 安 あり メンテナンス 引 き 継 ぎ 困 難
24 4. 改 善 実 例 作 業 の 最 適 な 分 業 1 機 能 のテストケース 作 成 工 数 (h) ( 任 意 で 抽 出 したケースの 平 均 ) 正 しく 分 割 した 設 計 にすることにより テストシナリオの 作 成 難 易 度 が 下 がり テストチームと 分 業 することが 可 能 になった
25 4. 改 善 実 例 テスト 品 質 の 向 上 と 無 駄 の 削 除 テストチームがシナリオを 作 成 管 理 するため 必 要 な 観 点 要 素 や 確 認 する 項 目 が 盛 り 込 まれたテスト 内 容 になった また 以 前 は 開 発 側 作 成 の 自 動 テストと 検 証 側 作 成 の 手 動 テストで 重 複 する テストが 存 在 していたが 解 消 され 手 動 テスト 工 数 が 削 減 された 特 に 複 数 回 テスト 実 施 を 行 うプロジェクトにおいて 検 証 チームが 自 動 化 を 管 理 している 項 目 では トータルコストの 大 幅 な 削 減 を 実 現 している 観 点 あたりの 工 数 平 均 手 動 : 実 施 時 0.75H N 回 自 動 : 作 成 2H 1 回 改 善 後 は 一 回 目 に 工 数 が 発 生 したが その 後 は 検 証 工 数 が 発 生 していない
26 4. 改 善 実 例 開 発 チームとの 密 な 連 携 設 計 改 善 テスト 観 点 抽 出 の 時 点 で 自 動 化 について 開 発 側 と 検 証 側 の 間 で 議 論 をする ため テストの 品 質 はもちろん 開 発 側 の 設 計 にもフィードバックがなされ 後 の 仕 様 / 設 計 / 実 装 の 手 戻 りを 減 らすことができた 双 方 がテスト 内 容 を 確 認 する 事 で お 互 いに 気 付 きを 発 信 しやすい 環 境 にな っている トラブル 対 応 回 帰 テストでのトラブル 発 生 時 でも 開 発 チーム/ 検 証 チーム 双 方 が 調 査 を 行 うため 各 々の 得 意 分 野 で 分 担 して 効 率 の 良 い 運 用 が 可 能 となった
27 まとめ テスト 自 動 化 プログラムは 操 作 技 術 とテストケースを 表 す シナリオ に 分 けられる 分 けることで 適 切 な 担 当 者 をアサインすることが 可 能 それぞれで より 高 度 な 技 術 を 使 うことが 可 能 テストチームと 開 発 チームが 協 力 することによって より 質 の 高 いテスト 自 動 化 作 成 が 可 能 となる