AutomaitonElementって何?

 MSDNソースコードを読んだり、プロトタイプを作って動作を確認してみたりを繰り返した結果、以下のようなモノだと理解しています。

 

①「ウィンドウ」とは別の画面要素を識別可能な単位

②「AutomationElement」として、外形等の一部情報が取得できる

③WinForms、WPF、UWP が AutomationElement に対応している

④コントロールパターンという形で操作の実現ができる

 

 今回は、上記における①~③を確認することを目標とします。

 説明するより動作を見た方が早いと思いますので、コードをGitHubにアップしました。コードをダウンロードしてVisualStudioでビルドすれば動作するものが出来ます。

 

 https://github.com/hatarabo/automation-spy

 

 起動直後はこのような画面です。

 AutomaitonElement と Window Handle での画面要素を識別する単位が違うことを確認できるよう、識別方法を選択できるようにしています。

 選択方法を選択し、開始ボタンを押下すると識別機能が開始されます。

 任意のウィンドウ上等でマウスの左クリックを押すと、対象を識別します。

f:id:hatarabo:20200614192146p:plain

 

 挙動の違いをUWPアプリの電卓で確認してみます。

 Window Handle の場合、電卓アプリ識別できますが、その中のボタンは識別できません。

f:id:hatarabo:20200614193612p:plain

 

 Automation Element の場合、電卓アプリの中のボタン単位で識別できます。

 また、当該ボタンの一部情報(たとえば、IsEnable = True)が取得できます。このサンプルでは PropertyGrid.SelectedObjects に AutomationElement.Current を設定するようにしています。

f:id:hatarabo:20200614193822p:plain

 

 簡単にではありますが、AutomationElement と Windows Handle の違いがご確認いただけたかと思います。

 そして、AutomationElementの最大のポイントは「対象パスで指定できる」という点です。HTML要素を id 等の属性値で特定できる、と同等のことが可能です。この特性が「WindowsOS上で一意の画面要素の位置を特定する」ことに、とても有益です。

 

 

(※1)

 AutomationElementで識別できるか否かは「対象が AutomationElementとのインターフェースに対応しているか」に依ります。たとえば Chromeブラウザは、WindowHandleでは識別できますがAutomationElement では識別できません。

 とはいえ、WinForms、WPF、UWPの開発で利用する基底クラスがAutomationElementに対応しているので、大半のアプリケーションには対応可能だと思います。

SQLの結合と集計関数

私事で恐縮ですが、自分がどれくらいSQL書けるのかをチェックする機会がありまして、自分でも引くくらい集約関数のこと忘れていたので、自分に向けての備忘メモとなります。

 

■ 集約で使う関数一式

関数名 機能
GROUP BY

グループ化

SUM GROUP BY でまとめたデータの合計
AVG GROUP BY でまとめたデータの平均
MAX GROUP BY でまとめたデータにおける最大値
MIN GROUP BY でまとめたデータにおける最小値
COUNT GROUP BY でまとめたデータの件数
HAVING 集計結果に条件を追加したい場合に利用する

 

■結合で使う関数一式

関数名 機能
JOIN 別名 INNER JOIN。
条件に一致しないデータは消える。
LEFT JOIN 別名 LEFT OUTER JOIN。
左テーブルはすべて表示。
条件が一致する右テーブルの値を取得。
条件が一致しない場合、NULL。
RIGHT JOIN 別名 RIGHT OUTER JOIN。
LEFT JOIN の反対。
CROSS JOIN

条件未指定の場合、ほぼ、総当たり。

レコード数10件のテーブル間で CROSS JOIN 場合、結果は100件になる。
手元で条件指定して実行した場合、JOINと同じになった。

FULL JOIN ほぼ、総当たり。
条件指定不可。

 

■勘所

  • GROUP BY (和訳:グループ化)という名前だが、挙動はむしろ分割に近いかも。
  • GROUP BY を使わずに AVG(カラム名)を使うと結果が1件になるのは、分割していない(=1テーブル)の当該カラムの全レコード平均値になるため。
  • GROUP BY を使ってAVG(カラム名)を使うと、GROUP BY によってテーブルを分割した上で、各テーブルごとに、当該カラムのレコード平均値を計算する。

 

テスト自動化アプリをプライベートで作る意義

技術的な記事を2つ書いた後ということで順番が逆になってしまい恐縮ですが

「テスト自動化アプリをプライベートで作る」という解決方法に至ったまでの、

 

 1.そもそもの解決したい問題

 2.問題解決の選択肢

 3.その選択肢を選んだ理由

 

を書いておこうと思います。自戒を込めて。

 

1.そもそもの解決したい問題

 これはド直球に「値段が高い」ことです。

 巷のWindowsアプリ向けのテスト自動化アプリのお値段はすべからず高価です。1つ例として、画面テスト機能を持ったVisualStudioのEnteprise版は、初期購入で70万円くらいします。

 

https://visualstudio.microsoft.com/ja/vs/pricing/

 

 私が在籍している会社では人数短期での開発が多く、予算はカツカツなことがほとんどです。テスト自動化アプリを購入する予算は組めません。開発受託会社なので保守・運用を行う機会が少なく回帰テストの重要性が低く、テスト自動化アプリの有用性が高くない環境なので勘定に組みづらいという面もあります。

 でも、受託開発中でもテスト自動化は導入できるものならしたいです。1日ノルマ50件でアプリ立ち上げてスナップショット撮ってExcelに貼って、、という退屈から解放されたい。もしお値段が安ければ個人の裁量で導入できる。こうなったら素晴らしいことだと思います。

 

2.問題解決の選択肢

 要はテスト自動化出来れば、別に自作する必要はありません。しかし、どうやら今の世の中には個人裁量で気軽に購入できるほどの安価な商品は見つかりませんでした。

 「無いなら作ろう」

 という話にしても、普通のサラリーマンであれば「会社で提案してみる」なんていう方法もアリなのではないでしょうか。企画書作ってデモして。

 実は私、テスト自動化アプリについて簡単な企画書とプロトタイプで社内提案してみました。市場調査や競合他社、特許、ブランド化イメージ、etc...と、パワポで箇条書きして。結果、役員の方から「いいじゃない」とご意見貰いまして、ウチの部署でやってみてよ、という手筈になりました。

 その後、紆余曲折(※1)あって、この話は私の方から上司にお断りの話をさせて頂きました。いっそのこと、もう自作しようと。その方が納得できるかなと。

 

3.その選択肢を選んだ理由

 これは別案件でモバイル向け通話アプリの市場調査をしていた時に知ったのですが、日本だとLINEがシェアの大半です。しかし、海外だと「WhatsApp」が最もメジャーです。この「WhatsApp」の売上モデルがとても印象的でして。(※2)

 この記事を知って、私は単純に「WhatsAppかっけ~」と感動しました。もし、自分に同じような舵取りを決める機会があるならば、LINEではなくWhatsAppを目指したいと。

 で、仮に、このテスト自動化アプリが自社商品として成長したとき、どのようなビジネスモデルになるのだろうか、と考えました。そして、会社だとWhatsAppのようなビジネスモデルは難しいだろうと思いました。

 WhatsAppは1人当たり年間0.99ドル支払ったとしても利用者数が 4.5億人 いれば 450億円の売上で、その市場規模ならビジネスとして成り立つのでしょう。しかし、Windowsのテスト自動化アプリはニッチです。「ニッチだけど需要があるから高い値段でも買う人がいる」モデルなので、値段が高いのは構造上仕方がない。そして、値段が高くなると、そもそもの「値段が高い」という問題を解決できない。

 なら、いっそのこと個人でやろうと。自分で使いたいアプリを好き勝手作ろうと。最近もうWinFormsの新規開発案件なんて稀だし、折角だから最後に、今まで努力してきた技術もふんだんに使ってやろうと。その方が気ままに楽しそうだなと、そんな感じです。

 

 

(※1)

 細かいこともあったのですが、一番の理由は、一緒にプロトタイプを作ってくれた後輩が会社を辞めてしまいまして。それで人手が確保できなくて、且つ、私のモチベーションも下がってしまって。また、この直後に業務でAWSを勉強する機会に恵まれてしまい、そちらに没頭してしまいました。おかげ様でAWSの資格を取ることができました。

 

(※2)

2014年の記事なのでちょっと古いですが

https://diamond.jp/articles/-/52086?page=2

マウス操作をグローバルフックする

C#でのグローバルフックですが、すでに多くの情報がネット上にありますし、他と差別化できるような情報は持っていませんごめんなさい、というのが本音です。

 

何で書いたかというと、テスト自動化においての肝となる「AutomationElement」について触れる前に、グローバルフックの話をしておいた方が分かりやすのでは、と思ったからです。

 

ちょっと脱線しますが、自動化というと主に2つのやり方があるかと思います。

 1.スクリプトを実行する

 2.ユーザ操作を再現する

 

1は「スクリプト」を書く必要があるので利用者への敷居は高くなります。

2は「ウィンドウズ座標の(x, y)位置でマウス右クリックして3秒後にEnterキー押して、、、」みたいな、ユーザ操作そのまま記録・再生だと、結果の再現率が低くなりがちです。

 

私もテストアプリを作成しながら、この点はかなり考えさせられました。

最初は何にも考えずに「操作の記録・再生」でプロトタイプを作ってみたのですが『「マウスダウン・アップ」と「クリック」』『「クリック」と「ダブルクリック』等の曖昧さを回避するために、各操作ごとに判定の時間を外部ファイルに持たせて、、とか色々やった結果、「操作の記録・再生」は、いったん諦めました。

じゃあ、スクリプトを丸々書かせるだと「自動化のために時間をたくさん使う」という自動化の意義、みたいなところが弱くなってしまう。これも避けたい。

 

今のところは「ユーザ操作の再現」ではなく「ユーザ操作の対象と操作をデータとして記録」し「静的なスクリプトでデータを解釈してユーザ操作を疑似再現」という形式にしています。

 

だいぶ脱線が長くなりましたが、この「ユーザ操作の対象と操作をデータとして記録」というときにグローバルフックを利用しております。

 

マウス操作のグローバルフックのサンプルコードをGitHubにアップしました。

 

https://github.com/hatarabo/hook-mouse

 

VisualStudioでビルド実行すると、こんな画面が表示されます。

 

f:id:hatarabo:20200607165538p:plain

 

開始を押すと Corsor Locaiton に カーソルのデスクトップ座標位置が表示されます。

適当なアプリ画面上でマウス左ボタンを押すと、アプリのタイトルと画面サイズが表示されます。以下は電卓アプリ上でマウス左ボタンを押した結果です。

 

f:id:hatarabo:20200607165948p:plain

 

これで、カーソル位置上にあるアプリケーションの識別ができました。

次回以降、グローバルフックが使えるという前提でAutomationElementに触れたいと思います。

 

 

Formの見た目をカスタマイズする


2017年頃、Microsoft様の以下サイトに

「ソフトウェアのブランド化にはオリジナルデザインがイイヨ」

という内容が(たしか)載っておりまして、仕事中「どうです、フルドロー導入しませんか」と提案ネタにしておりました。

 

https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa511284.aspx

 

今、上記URLを叩くと別ページに飛びます。

これは個人的にですが、おそらく、情報が"古く"なったからなのだと思います。

私が C# + WinForms に出会ったのは10年前で「これできればご飯食べていけるだろ」と思い取り組んだものが、技術発展の中で表舞台から少しずつ姿を消していくという現実に「他の食い扶持探さねば」と思い改める日々です。

 

ともあれ、利用者の目を惹くには画面デザインへの配慮は不可欠です。というわけで、WinFormsにおけるFormのカスタマイズを行うサンプルをGitHubにアップしました。

 

https://github.com/hatarabo/owner-draw-form

 

任意の Form に FormBase というクラスを継承することで

 

f:id:hatarabo:20200607020105p:plain

 

こんな画面が

 

f:id:hatarabo:20200607020318p:plain

 

こんな画面になります。

私のセンスはともかく、見た目が変わっていることはお分かりいただけるかと思います。

処理的にはおおまかに

  ①WndProc()で非クライアント領域を 0 に

  ②WM_NCHITTEST で 非クライアント領域への操作に応答(※1)

  ③非クライアント領域の機能を実装(※2)

という方法で機能を実現しています。

ご参考まで。

 

(※1)

非クライアント領域への操作に対する応答の網羅率は 100% ではありません。タイトルを左クリックでコンテキストメニューが出ない等、未対応な箇所があります。

 

(※2)

たとえば、画面タイトルのFontは本来アプリケーション管理ではなくシステム設定(テーマとか)の担当なのですが、今回は自作なので機能として補う必要がありました。

 

本ブログの趣旨

プライベートでWindows上で動作するテスト自動化アプリを作成しています。

作りこみや考慮不足はたくさんありますが、手元でならそこそこ動く形になってきました。

が、当初の想定よりアプリケーション規模が大きくなってきたこと、プライベートということで好き勝手スクラップ&ビルドしていたこともあり、最近

 

・技術検証結果を忘れがち

・ゴールが遠くてモチベーションが維持できない

・もしかしたら作り切れないかも、という不安

 

等の弊害が出てきました。

 

というわけで、上記3つを解決するにあたり「スモールウィン」を導入しようと、手段としてブログで情報発信することで

 

・検証結果を見直せる

・技術検証そのものに価値が出る

・最悪、技術検証結果は残る

 

と、ポジティブな効果を期待してブログを開始しました。

開発言語はC#が主で、一部機能実現に C++/CLIJavaScriptを使っています。

画面は 、、WinFormsです。WPF、UWPでなくてごめんなさい。

よろしくお願いします。

 

また、現職がシステムエンジニアということもあり、お仕事でフィジビリティスタディ等を行う機会も多いので、そのあたりの情報も出していきたいです。

こちらは主に自分の勉強結果を知識として定着させる備忘としての用途で考えています。