stack2017 自動化困難な状況での活動方法
TRANSCRIPT
自己紹介
・石川達也
・(株)Codeer 代表取締役
・Microsoft MVP
・ささいなことですが(ブログ)
・OSS
FriendlySelenium拡張
LambdicSql
Visual Studio and Development Technologies
http://ishikawa-tatsuya.hatenablog.com/
https://www.nuget.org/profiles/ishikawa-tatsuya
趣味はギターとライブラリ作成
【Quick Shot】
メソッド単位で確認、デバッグできるVisualStudio拡張https://marketplace.visualstudio.com/items?itemName=ishikawa-tatsuya.Quickshot
【LambdicSql】
SQLをC#で表現する
SqlBuilderhttps://github.com/Codeer-Software/LambdicSql
今はこんなのも作ってます。
ご興味あれば、是非ご利用ください。
Windowsアプリを意のままに操作するためのライブラリ
弊社製品FriendlyはMicrosoft MVP Showcaseで2位になりました。http://blogs.msdn.com/b/mvpawardprogram/archive/2014/11/04/mvp-showcase-winners.aspx
IPAの「先進的な設計・検証技術の適用事例報告書 2015年度版」に掲載。http://www.ipa.go.jp/sec/reports/20151118.html
Friendly!
https://github.com/Codeer-Software/Friendly
人間は優秀。人間と全く同じことは2017/12/10時点では不可能。
ちょっと待って!
あれできるの?これは?そこはできないの?その部分は人がやるのと違うよね?
じゃあ、やりません。
自動テストの可能不可能を最初に明確にする
【コラム】ちなみに、こんな話よくありますよね?
なりません。
無理っす。
↑最近よく言われる
AI使って何とかならないのですか?
ランダムに実行させて問題のあるところ見つけてください。
キャプチャリプレイがあれば全て解決するはずでしょう? 色々問題あります。
↑何故かみんな期待している
それでも十分効果があります!
全部は無理だし、人間が実施するのとは違うし、泥臭いことやらないとダメだけど
・同じ操作でパラメータを変える必要がある場合(機能確認)・同じ操作を繰り返す必要がある場合(信頼性確認)・正常系の操作/確認(回帰検査化するとさらに効果UP)
システムテスト自動化に向いている部分
自動化では困難/人しかできないこと
・複雑なマウス操作とそのレスポンス確認・GUIコントロール自体の確認・想定外の不具合の認識・不具合傾向から怪しいところを発見する(探索的テスト)
理論的に技術的に説明
アプリを触りつつ、「テスト設計のこの部分は自動化に向いてますよねー。」
「緑の部分は自動化で保障できますね。だから、毎日実行できてお得ですよ。その他は、人でやりましょう。」
エモいのはビジネスの場では引かれる・・・アドリブで一つシナリオ動かせれば完璧。
どのタイミングで役に立つのか?どのリスクを減らしているのか?
1 1 1
2
1
3
1
4
1
5
2 2
3
2
3
4
2
3
4
5
1
2
1
3
2
1
4
3
2
1
積みあがったテストが毎日のリスクを軽減
+
・もちろん、リリース直前、緊急リリース対応時
・開発、デバッグフェーズで威力を発揮
リリース前は人間のテストもやるけど自動でできる部分もあって楽になってるよね
裏技:過去の例から試算した値を出すと理解される場合もある
項目 工数(人日)
テスト実装工数 +800 + 120 + 90 = 1010
調査設計 -20×10×2 = -400
実装 -20×10×2 = -400
不具合修正 -20×20×2 = -800
テスト工数 -300×3×2 = -1800
その後の緊急リリース -24×5 = -120
合計 -2510
実装者 20人
テスト担当者 20人
期間 1年×2
【試算に使った条件】・自動テストは1回目開始前に大量に作成。プロジェクト中にも追加、メンテは発生している。・調査設計、実装工数は一人あたり10人日は削減できている。・不具合修正はテストフェーズで見つかる不具合数とその後の修正→周辺確認→場合によっては再修正の分を加味している。
・テストは手動ならリリースまでに全チェックは3回は実行していると考える。自動化しているテストを手動でやるなら300人日は必要。
削減工数 : 試算上は2510人日削減(バージョンアップリリース二回分で試算)
使った工数(実際の値)
エミュレート方式とAPI方式がある
人間の操作に近いことキーマウスをドライバレベルでエミュレート
Application Programming Interfaceプログラムから使われることを目的としている。確実、高速な動作。テスト自動化と相性が良い。最近流行り?のRPAもこちらを推奨。
ここが困難
タイミング
App OS Test
重い処理
テストとしては複数個処理を投げ込んだけど、どこまで進んでるかわからない
保守性の高い記述が難しい
例えば365個目までスクロールしてそれをクリックとかほんのちょっとの変化で使えなくなるよね?
同期可能なキー、マウスエミュレートを作ってみました。
App OS Test
重い処理
タイマが動くまで待つWait
キー、マウス送信
処理が終わったことが分かる
Friendly.Windows.KeyMouse
あれだけ、ディスっておきながら
var window = WindowControl.FromZTop(app);var target = new WindowControl(window.Dynamic()._target);
//中央を左クリックtarget.Click();
//ボタンと座標指定でクリックtarget.Click(MouseButtonType.Middle, new Point(4, 5));
//ダブルクリックtarget.DoubleClick();target.DoubleClick(MouseButtonType.Middle, new Point(4, 5));
//Drag & Drop.var dropTarget = new WindowControl(window.Dynamic()._dropTest);target.MouseDown(MouseButtonType.Left, new Point(0, 0));dropTarget.MouseUp(MouseButtonType.Left, new Point(2, 3));
//コンテキストメニューのクリックユーティリティPopupUtility.ExecuteContextMenu(target, new PopupTarget(5, 4), new PopupTarget(5, 4));
//キー送信target.SendKeys("aBc");
//キーとマウスapp.KeyDown(Keys.Menu);target.Click();app.KeyUp(Keys.Menu);
書き味もいい感じ!
あくまで最終手段
<script type="text/javascript">function ExecuteButton() {
//ここは待ってるvar start = new Date();while (new Date().getTime() - start.getTime() < 5000);
//ダイアログは待たないalert("1");
}</script><input id="_button" type="button" value="Wait" onclick=“executeButton()" />
ちなみにSeleniumはAPI方式なのでいい感じに同期されます
var element = driver.FindElement(By.Id("_button"));element.Click();
操作側
html
API方式
プログラムから扱いやすいインターフェイスを公開。タイミング依存の問題が起こりにくいので、運用コストを下げることができる。反面、人間の操作とは完全には一致しない。
・Seleniumはブラウザというアプリの公開インターフェイスを操作
・FriendlyはWindowsアプリに内在するAPIを操作
自動化困難なケースではピンを生やして対応
テスト用に使いやすいインターフェイスを追加で作る(組み込み機器でテスト用にピンを使うところから命名)
・Webアプリ→ JavaScript に仕込む(Seleniumから呼ぶ)
・.NetWindowsアプリ→普通に実装(Friendlyから呼ぶ)
・Win32アプリ→DLL公開関数(Friendlyから呼ぶ)
Win32アプリとかの場合は、結構沢山ピンを出します。
ピンを出す場合、ピンの仕様を共有することが大事
意図を正しく伝えて、ピンを出してもらう。(そのピンを使うことによって、カバーできる部分とスルーされる分を確認。)また、その後メンテも正しくできるようにする。
・テスト設計へフィードバック
スルーされる部分はあるけど、ピンがないと、そもそもそこは自動化できなかったわけだし。
・開発チームとの連携
自動化開発中に、ピンを生やすことになった場合はテスト設計へフィードバックし手動テストで確認する部分をつけ足す
【コラム】操作困難 Win32アプリ
APIとしては昔ながらのWin32APIやSendMessageが使える。が、普通にやると問題が起きることがある。
Friendlyは、PostMessageを応用した割り込みなので、処理中は割り込まない。DLL公開関数(ユーザー作成も含めて)も安全に使えるのでテスト用にピンを出すことも可能。
App Test
割り込み強烈!
SendMessage
特定のAPIを使えばメッセージループが回らなくても割り込まれる
App Testそれなら安心
ここで実行
Friendlyで実行
Friendlyを使おう!
【コラム】操作困難を乗り越える! Selenium-IEDriver
何が言いたいかというと、テスト自動化は自動操作力!これに限らず、困難に遭遇しても解決方法を考えることが重要。ピンを生やすのもその一つ。テスタビリティは自分で上げる。でも、ダメなときはサクッと撤退することも重要。(初期調査重要
http://ishikawa-tatsuya.hatenablog.com/entry/2016/06/04/100121
Seleniumの仕事を前にやってIE対応でハマりました。IEDriverServer.exeが落ちるというもの。
絶望しましたが、その処理だけCOMを直接叩いて回避したりWinFormsのSendKeysでキーエミュレートしたりで回避しました。
人間と同じ確認はできません。
通常は画面に現れた文字列データで確認するもちろんAPI経由で。OCRとかは通常はやらない。
※対象とする箇所以外に異常があってもそれは気づけない。
仮にこんなの出てもそれはスルー。出る可能性のあるコードなら事前にそこも対象箇所に加えておく必要がある。
ここを確認
そういうのもあって、システムテストは自動テストのチェッキングの他に人のテスティングも通常は必要。
どうしても画像比較になるなら(画像自体のテストなど)
でも、その場合、絶対に画像が完全一致する条件を開発時に決めておく(最低限、マシンごとに一致すること)
画像のテストなので似ているからOKは判断が難しすぎる→不具合でゴミピクセルが1dot混ざることとかありえるしね。
【コラム】内部状態をダンプ
本来は、外に見える情報(もしくはその元となる情報)を期待値として検証するのが望ましいですが、私の経験的にはスタンドアロンのアプリは超絶ステートフル。
特に歴史が長く、内部データの構造が比較的安定しているものならそれをダンプして検証するのもアリと思ってやってます。
こういうケースは自動テストの方が向いています。
ダンプもバイナリではなくテキストにして人間も見れるようにしておくと効率が良い。