【sqip2014】システム操作インターフェイス最適化によるテスト自動化roi向上...

Post on 25-Jun-2015

4.845 Views

Category:

Documents

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

SQiP2014で発表したスライドです。 GUI以外のインターフェイスを使うことによって、削減できるコスト、得ることのできる利益について説明しています。GUI以外のインターフェイスを使う方法にはWindowsではFriendlyがあります。

TRANSCRIPT

システム操作インターフェイス最適化によるテスト自動化 ROI向上

株式会社 Codeer石川達也http://www.codeer.co.jp/

石川達也

株式会社 Codeer代表取締役

Microsoft MVP for C#

Windowsアプリテスト自動化歴 9年

Windowsアプリ操作用ライブラリ Friendlyの開発者

自己紹介

ご相談を受けた企業様の悩みで多いもの

システムテスト自動化やったことあるんだけど、効果が出なくて・・・

4

課題抽出

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

作業と ROI要素

エラー!

成功

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

テスト起因のエラー。解析工数は運用コスト。

エラー!

成功

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

テスト起因のエラー。解析工数は運用コスト。

ほぼ毎日、いずれかのテストがタイミング依存で失敗。ランニングコスト化。想定外の運用コストとなっている。

課題① 自動実行不安定

モチベーション低下自動化に対する不信感

0

2

4

6

8

10

12

Before

テスト不安定によるエラー発生数( A社)

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

作業と ROI要素 もう一つ

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

BugFix実行

指定のケースではデグレがないという情報を取得できた!

作成

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

BugFix実行

成功しても安心できないし、手動テストも、ほとんど減ってない。

課題② 自動化されたテストケースが少ない

指定のケースではデグレがないという情報を取得できた!でも・・・

パラメタライズ込でこの件数なので自動化としては少なめ。箇所としても、自動化容易性が優先されている。

Series10

500

1000

1500

2000

2500

3000

Before

A社自動化ケース数

この情報の価値が低い。成功?だから何?

作成

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

BugFix実行

不安定なテスト増やさないで・・・

成功しても安心できないし、手動テストも、ほとんど減ってない。→じゃあ、そんなに工数出せないよ。

工数足りない。作れないよ・・・

少ない工数で作ったスクリプトだからメンテがつらい。

悪循環ケース少ないと価値が低い。

12

課題①②の共通問題

・・・

13

課題①②の共通問題

*その前に注意書き

課題①②の共通問題

*その前に注意書き

実際には、これらの課題は

・テストケースの見直し・管理の改善・ CI環境の改善・単体テストへの移行

など、複合的に対応されました。しかし、ここでは主題「システム操作インターフェイス最適化」に沿った改善のみにフォーカスして説明します。

15

課題①②の共通問題

・・・

(-_-)

課題①②の共通問題

ココ

だから・・・

・タイミング依存でテストが失敗する・テスト作成工数が増える  →見積もり時点で自動化対象から省かれる。

テスト以前に対象アプリの操作が上手くいっていない。

課題①②の共通問題

ココ

Why?

マルチプロセスプログラミング

キー、マウスエミュレートは

不安定

そもそもGUIって人間

UIAutomation?

キャプチャリプレイ?

OSからユーザコードまでの

BlackBox

マルチプロセスプログラミング

キー、マウスエミュレートは

不安定

そもそもGUIって人間

UIAutomation?

キャプチャリプレイ?

OSからユーザコードまでの

BlackBox

課題①②の共通問題

ココ

GUIアプリを「外側から」「プログラムから」「安定して」操作するのは難しい!

ここまでのまとめ!

19

対応

アプリ操作インターフェイス最適化~内部 APIを使う~

20

内部 APIとは

【備考】

21

内部 APIとは?

本稿では、

普通にプログラムで使う(作る) APIを指す。つまり、普段書いているプログラムのクラス、メソッド、フィールド、プロパティーなど。

22

GUI 層 例えばグリッド操作

23

人間ならキー、マウス。

自動化なら、そのエミュレート

もしくは UIAutomation・・・

GUI 層 例えばグリッド操作

24

内側にはプログラム実装用の簡単で高機能な APIが公開されている

//WinFormsの DataGridViewの場合bool BeginEdit(bool selectAll);bool EndEdit();Control EditingControl { get; }DataGridViewRowCollection Rows { get; }・・・

これを使えば、プログラム作成時同様、自由に安定した操作が可能!

GUI 層 例えばグリッド操作

25

アプリ実装層 例えば右クリック以降の処理

26

一般的にはマウスエミュレートしか選択肢がない。座標計算して、タイミング合わせて・・・

アプリ実装層 例えば右クリック以降の処理

27

内部では、プログラム (API)として実装しているので・・・

// ボタンを押したイベントVoid OnMouseClick(object sender, MouseEventArgs e) { ・・・ MouseRightClickCore(row, col); }

//この APIは比較的プログラムから扱いやすいVoid MouseRightClickCore(int row, int col) { ・・・ FunctionA(); }

Void FunctionA() { ・・・ FunctionB(); }

最も操作しやすい APIを呼び出せる。どうしても操作できない場合は、コードの変更も可能。つまり、テスタビリティーを向上することが可能。

アプリ実装層 例えば右クリック以降の処理

28

単体テストとの違いは?

単体テストは、部品単位。システム(アプリ)は組みあがっていない。

内部 APIを使ったシステム操作はアクセス方法が違うだけで結合状態のシステムを操作している。あくまでシステムテスト。

注意点1使用する内部 APIによっては、人間の操作との差分が生じる。テスト対象外になった部分を手動テストにフィードバックする。GUI 層の APIで操作した場合は、手動とほぼ等価。

アプリ実装の層の APIを使う場合は、どれくらい削ったかを確実にフィードバック。

(あくまで、操作としての話)

内部 APIだが、テストから呼び出した時点でテスト用の公開 API 扱いとなる。

void Function() { ・・・}

テストで使うことになったよ。変えたら教えてね。

注意点2

参考

DSLのスクリプトでGUI以外のインターフェイスを使って受け入れテストを自動化する手法が紹介されている。

GUI以外の公開 APIを使ってテストを自動化する方法が紹介されている。

以下の書籍に GUI以外のインターフェイスを使ってシステムテストを実施する手法が紹介されている

string Func(int value){}

//テストプロセスpublic void Test(){ // 呼び出し string ret = form.Func(3); //Dllインジェクション ! WindowsAppExpander. LoadAssembly(app,GetType().Assembly);}

public class MainForm : Form{ string Func(int value) { ・・・ }}

Windowsアプリでこれを実現するライブラリ

http://www.codeer.co.jp/AutoTest

Friendly

プロセスの壁を突破できる!

無料Nugetから

基本 内部メソッド操作、 DLLインジェクション

Win32 WinForms WPF PinInterface

記述性 UP

Friendly.Windows.NativeStandardControlsFriendly.FormsStandardControlsFriendly.WPFStandardControlsFriendly.PinInterface

使用頻度の高い GUI 層の操作はラップした上位ライブラリもある

Windowsアプリでこれを実現するライブラリ全部無料

34

具体的な対応

アプリ操作インターフェイス最適化~内部 APIを使う~

35

・課題①②の根本原因は同じなので、 どの対応も両方の課題に効果が出ております。(つまり安定して操作できる範囲が拡大したということ)

具体的な対応

アプリ操作インターフェイス最適化~内部 APIを使う~

・テストの主目的は OSと各 GUIライブラリの結合ではない・安定性、実装容易性を重視・サードパーティー、自作の GUIも操作可能

GUI操作を内部 APIベースに変更

datepicker.SelectedDate = new DateTime(2014, 9, 11);

上位ライブラリの使用で、さらに工数カット

//ここの結合は不安が少ないvoid Event(object sender, EventArgs e){ EventCore(PointToClient(Control. MousePosition));}

//これを呼び出すvoid EventCore(Point mousePosClient){ //ここから先なら簡単に操作可能 //テストとしても問題がない}

自動化可能に!

自動化困難で効果の低い部分の分離

こういうの苦手・・・・キー、マウス直接参照・ D&D・ OS 提供の GUI

例)システムテスト自動化を実施したいが、GUI操作で、実行するには困難で諦めていた。

実装工数が大きいものは GUI操作を省略

サーバーと通信

例)システムテスト自動化を実施したいが、GUI操作で、実行するには困難で諦めていた。

重要な処理

分析の結果、この範囲のテストを自動化できたら十分効果アリと判断。

サーバーと通信

実装工数が大きいものは GUI操作を省略

分析の結果、品質を確認したい部分はGUIではなかったので、内部メソッドを利用。約 5 千ケースが自動化された。

例)文字列のパースをする処理があり、それはアプリの様々な設定により結果が変わる。しかも、レガシーコード。(単体化が困難)求められるテストケースは 15 万ケース。

設定A

設定B

設定 C

入力

実行時間が大きいものは GUI操作を省略

種類 実行平均時間 合計手動 30 秒 1250時間自動 GUI操作 2 秒 83時間

例)文字列のパースをする処理があり、それはアプリの様々な設定により結果が変わる。しかも、レガシーコード。(単体化が困難)求められるテストケースは 15 万ケース。種類 実行平均時間 合計手動 30 秒 1250時間自動 GUI操作 2 秒 83時間自動内部メソッド

10ミリ秒 24 分→ Dailyで回帰化可能な時間に!

設定A

設定B

設定 C

入力

実行時間が大きいものは GUI操作を省略

例)文字列のパースをする処理があり、それはアプリの様々な設定により結果が変わる。しかも、レガシーコード。(単体化が困難)求められるテストケースは 15 万ケース。種類 実行平均時間 合計手動 30 秒 1250時間自動 GUI操作 2 秒 83時間自動内部メソッド

10ミリ秒 24 分→ Dailyで回帰化可能な時間に!

設定A

設定B

設定 C

入力

時間がかかりすぎると Dailyの回帰環境に組み込めない。分散させることも可能。実際そうしたケースもある。ただ、分散には大がかりな仕組みが必要になる。シンプルに速くなれば開発者のローカル PCでも実行可能。

実行時間が大きいものは GUI操作を省略

43

気づき  GUI省略

パラメタライズが求めらるテストケースはGUIが重要でないことが多い。// 同一のテストシナリオを複数のパラメータで実行[TestMethod][DataSource(...)]public void TestScenario(){ ...}

とは言え、単体テストで済ませられるならそれに越したことはない・・・。

原因 対応タイミング依存の不具合 不具合修正タイマ、非同期処理、描画イベントを利用した実装

確実に同期がとれる情報を参照するテスト時は同期にする

不安定なテストが発見されたらすぐに対応アプリ実装起因で不安定になることがある

原因 対応タイミング依存の不具合 不具合修正タイマ、非同期処理、描画イベントを利用した実装

確実に同期がとれる情報を参照するテスト時は同期にする

不安定なテストが発見されたらすぐに対応アプリ実装起因で不安定になることがある

安定させられる手段 (内部 API)があればこそ!

とにかく、安定するテストでなければ許容しない。優先的に対応!

1 2 3 4 5 6 7 8 9 10 11 12 13 140

1

2

3

4

5

6

エラー数

例 ) 不安定な処理の周辺のテストを 86ケース投入してから安定するまで   備考として、個々では成功することを確認してから CI環境に投入している。 1日目にプロダクトの不具合を突き止め

修正テストにも問題があり、 3日目に気づいて修正

不安定なテストが発見されたらすぐに対応

4日目以降は運用コストは発生していない

アプリ実装起因で不安定になることがある

ランニングコスト化は絶対避ける!

原因 対応タイミング依存の不具合 不具合修正タイマ、非同期処理、描画イベントを利用した実装

確実に同期がとれる情報を参照するテスト時は同期にする

47

はい

48

ココ

ここまでは、操作技術の話でした。

49

ここからは、テストシナリオの書き方の話になります。

50

新たな課題

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

作業と ROI要素 新たな課題

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

課題③ 作成、メンテに内部仕様の知識が必要

//変数名を知っている必要があるvar _name = new WPFTextBox(window._name);var _founding = new WPFDatePicker(window._founding);var _member = new WPFDataGrid(window._ member);var _ok = new WPFButtonBase(window._ok);

//内部メソッドを知っている必要があるvar data = Window.GetData();

class InputWindow : Window { TextBox _name; DatePicker _founding; DataGrid _member; Button _ok;

public Data GetData() { ・・・ }}

しかも、テストシナリオにばら撒かれる・・・

54

テストシナリオから使うインターフェイス最適化

対応

~アプリケーションドライバの導入~

55

アプリケーションドライバとは

【備考】

アプリケーションドライバとは?

テストシナリオ .dll

テストプロセス

① ②アプリケーションドライバ .dll

アプリ操作の詳細とテストシナリオを分離して記述する設計手法。

内部 APIを使うときは必須!

アプリケーションドライバとは?

「継続的デリバリー」で紹介されている。詳細はこちらを参照。

テストシナリオ .dll

テストプロセス

① ②アプリケーションドライバ .dll

58

具体的な対応

テストシナリオから使うインターフェイス最適化

~アプリケーションドライバの導入~

59

→ほとんど書籍通りなので省略。 興味がある方は是非読んでください!

実装例

今回、実装したことと、必要だった知識

記述したこと 実装に必要な知識アプリケーションドライバ

・WindowDriver・内部仕様に依存する処理・汎用的な処理

内部仕様

C#

基本的なプログラム設計能力

テストシナリオ

・テストケース(できるだけシンプルに)

外部仕様

基本的な C#の知識

テストシナリオは簡単に書けるようにアプリケーションドライバの設計を頑張った!

61

アプリケーションドライバ .dll

テストシナリオ1 テストシナリオ2 テストシナリオ3

当然共通化にもなり、コード量が行数で約 35%減。また、共通処理を使うことでテスト作成効率もUP。

作業分担できた。

開発チーム

評価チーム

62

成果

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

作業と ROI要素

エラー!

成功

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

テスト起因のエラー。解析工数は運用コスト。

課題① 自動実行不安定

エラー!

成功

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

テスト起因のエラー。解析工数は運用コスト。

解決① 自動実行不安定

朝来て AllGreenって気持ちいい!テストに対する信頼も高いからRedの時は本腰入れて調査できる!

0

2

4

6

8

10

12

Before After

改善前は、ほぼ毎日結果を解析して、プロダクトに問題がないことを確認する必要があった。(半自動)改善後は、不安定なテストが混入することはあるが即座に対応して安定化させることができた。

テスト不安定によるエラー発生数 ( 異なる期間で 3カ月集計 )

← 無駄なコストは たまに出るだけ

A社

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

BugFix実行

課題② 自動化されたテストケースが少ない

指定のケースではデグレがないという情報を取得できた!でも→価値が低い。

作成

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

BugFix実行

解決② 自動化されたテストケースが少ない

Series10

50000

100000

150000

200000

自動化ケース数

Before After

部分的にリリース、リファクタリング実行の判断材料に使うことができるようになった。最終に実施する手動テスト数も減らすことに成功。

広範囲にわたり、ソースを改修した直後に「上手く作成された、多くのテストケースをパスした」という情報を得れるのは非常に価値がある。

多い!

A社

デグレ検出数も増えてはいる。ただ、 の方が主目的。

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

課題③ 作成、メンテに内部仕様の知識が必要

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

解決③ 作成、メンテに内部仕様の知識が必要

テストシナリオ作成だけなら不

負荷分散!

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

解決③ 作成、メンテに内部仕様の知識が必要

テストシナリオ作成だけなら不

実は!テストシナリオの品質 UPは全ての ROI要素に好影響を与えた!

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

解決③ 作成、メンテに内部仕様の知識が必要

テストシナリオ作成だけなら不

実は!テストシナリオの品質 UPは全ての ROI要素に好影響を与えた!

共通化により安定した処理を使いまわせた!

簡単になったから、多くのシナリオを作成、メンテできた!

エラー!

成功

テスト起因のエラー。解析工数は運用コスト。

仕様変更等でメンテ

作成

指定のケースではデグレがないという情報を取得できた!

BugFix実行

つまり・・・

エラー!

成功

仕様変更等でメンテ

作成

BugFix実行

コストダウン!

ROI向上!

利益 UP!

テストプログラムも設計が重要!テストプログラムの品質はすべての ROI要素に関わってくる。特に内部 APIを使うときはアプリケーションドライバは必須!

・アプリ操作インターフェイス

・テストシナリオから使うインターフェイス

内部 APIを有効に使うことで、低コストで安定した操作を実現できた。

まとめ

システム操作インターフェイス最適化によるテスト自動化 ROI向上!

75

ご清聴ありがとうございました。

【 Picture】Dawn Huczekvectorvaco.com

エラー!

成功

Specail Thanks.reviewrc( 資料レビュー )めとべや (WPFStandardControls)VS ハッカソン倶楽部 (PinInterface)

top related