Windows 10

WinAppDriver UI Recorderを試してみました。

下記記事にある通り、「WinAppDriver UI Recorder」が公開されたので、さっそく試してみました。

米Microsoftは20日(現地時間)、新しいオープンソースツール「WinAppDriver UI Recorder」を「Windows Application Driver」の一部としてリリースした。自動UIテストを作成するのに役立つ。

https://forest.watch.impress.co.jp/docs/news/1128952.html より

Microsoftは2018年6月20日(米国時間)、「Windows Application Driver」(WinAppDriver)コミュニティー向けの新しいオープンソースツール「WinAppDriver UI Recorder」(以下、UI Recorder)の公開を発表した。UI Recorderは、自動化されたUI(ユーザーインタフェース)テストのスクリプトを簡単に作成できるツールだ。

http://www.atmarkit.co.jp/ait/articles/1806/22/news036.html

WinAppDriver UI Recorderの使い方

GitHubReleasesページにZip形式で圧縮されたバイナリファイルがありますが、今回はVisual Studio Community 2017でビルドしたものを使用しました。

WinAppDriver UI Recorderを使うとUI要素のXPathクエリを生成でき、上図の通り「Record」ボタンをクリックすると、操作を記録することができます。

生成されたコード

電卓を操作した際に生成されたコードが下記になります。

// LeftClick on "One" at (75,20)
Console.WriteLine("LeftClick on \"One\" at (75,20)");
string xp1 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num1Button\"][@Name=\"One\"]";
var winElem1 = MyDesktopSession.FindElementByXPath(xp1);
if (winElem1 != null)
{
    winElem1.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp1}");
    return;
}


// LeftClick on "Two" at (44,20)
Console.WriteLine("LeftClick on \"Two\" at (44,20)");
string xp2 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num2Button\"][@Name=\"Two\"]";
var winElem2 = MyDesktopSession.FindElementByXPath(xp2);
if (winElem2 != null)
{
    winElem2.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp2}");
    return;
}


// LeftClick on "Three" at (36,20)
Console.WriteLine("LeftClick on \"Three\" at (36,20)");
string xp3 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num3Button\"][@Name=\"Three\"]";
var winElem3 = MyDesktopSession.FindElementByXPath(xp3);
if (winElem3 != null)
{
    winElem3.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp3}");
    return;
}


// LeftClick on "Plus" at (19,18)
Console.WriteLine("LeftClick on \"Plus\" at (19,18)");
string xp4 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"StandardOperators\"][@Name=\"Standard operators\"]/Button[@AutomationId=\"plusButton\"][@Name=\"Plus\"]";
var winElem4 = MyDesktopSession.FindElementByXPath(xp4);
if (winElem4 != null)
{
    winElem4.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp4}");
    return;
}


// LeftClick on "Four" at (57,18)
Console.WriteLine("LeftClick on \"Four\" at (57,18)");
string xp5 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num4Button\"][@Name=\"Four\"]";
var winElem5 = MyDesktopSession.FindElementByXPath(xp5);
if (winElem5 != null)
{
    winElem5.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp5}");
    return;
}


// LeftClick on "Five" at (80,19)
Console.WriteLine("LeftClick on \"Five\" at (80,19)");
string xp6 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num5Button\"][@Name=\"Five\"]";
var winElem6 = MyDesktopSession.FindElementByXPath(xp6);
if (winElem6 != null)
{
    winElem6.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp6}");
    return;
}


// LeftClick on "Six" at (34,18)
Console.WriteLine("LeftClick on \"Six\" at (34,18)");
string xp7 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num6Button\"][@Name=\"Six\"]";
var winElem7 = MyDesktopSession.FindElementByXPath(xp7);
if (winElem7 != null)
{
    winElem7.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp7}");
    return;
}


// LeftClick on "Equals" at (59,29)
Console.WriteLine("LeftClick on \"Equals\" at (59,29)");
string xp8 = "/Pane[@Name=\"デスクトップ 1\"][@ClassName=\"#32769\"]/Window[@Name=\"Calculator ‎- Calculator\"][@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"StandardOperators\"][@Name=\"Standard operators\"]/Button[@AutomationId=\"equalButton\"][@Name=\"Equals\"]";
var winElem8 = MyDesktopSession.FindElementByXPath(xp8);
if (winElem8 != null)
{
    winElem8.Click();
}
else
{
    Console.WriteLine($"Failed to find element {xp8}");
    return;
}

これをこのままコピー&ペーストしても動作しないので、一部コードを書き足して実行したところ、要素の取得で躓きました。

仕方が無いので、XPathの一部を編集したのが下記のコードです。
(「Windows Application Driverを試してみました。」記事に書いている通り、コードを実行する際はNuGetで「Appium.WebDriver」を追加してください。)

using System;
using OpenQA.Selenium.Appium.Windows;
using OpenQA.Selenium.Remote;

namespace WinAppDriverTest
{
    class Program
    {
        private const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
        private const string CalculatorAppId = "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App";
        protected static WindowsDriver<WindowsElement> session;

        static void Main(string[] args)
        {
            string serverPath = System.IO.Path.Combine(
                System.Environment.GetFolderPath(
                    System.Environment.SpecialFolder.ProgramFilesX86
                ), @"Windows Application Driver", "WinAppDriver.exe"
            );
            System.Diagnostics.Process.Start(serverPath);

            DesiredCapabilities appCapabilities = new DesiredCapabilities();
            appCapabilities.SetCapability("app", CalculatorAppId);
            session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
            session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(1.5));

            // LeftClick on "One" at (75,20)
            Console.WriteLine("LeftClick on \"One\" at (75,20)");
            string xp1 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num1Button\"][@Name=\"One\"]";
            var winElem1 = session.FindElementByXPath(xp1);
            if (winElem1 != null)
            {
                winElem1.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp1}");
                return;
            }

            // LeftClick on "Two" at (44,20)
            Console.WriteLine("LeftClick on \"Two\" at (44,20)");
            string xp2 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num2Button\"][@Name=\"Two\"]";
            var winElem2 = session.FindElementByXPath(xp2);
            if (winElem2 != null)
            {
                winElem2.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp2}");
                return;
            }

            // LeftClick on "Three" at (36,20)
            Console.WriteLine("LeftClick on \"Three\" at (36,20)");
            string xp3 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num3Button\"][@Name=\"Three\"]";
            var winElem3 = session.FindElementByXPath(xp3);
            if (winElem3 != null)
            {
                winElem3.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp3}");
                return;
            }

            // LeftClick on "Plus" at (19,18)
            Console.WriteLine("LeftClick on \"Plus\" at (19,18)");
            string xp4 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"StandardOperators\"][@Name=\"Standard operators\"]/Button[@AutomationId=\"plusButton\"][@Name=\"Plus\"]";
            var winElem4 = session.FindElementByXPath(xp4);
            if (winElem4 != null)
            {
                winElem4.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp4}");
                return;
            }

            // LeftClick on "Four" at (57,18)
            Console.WriteLine("LeftClick on \"Four\" at (57,18)");
            string xp5 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num4Button\"][@Name=\"Four\"]";
            var winElem5 = session.FindElementByXPath(xp5);
            if (winElem5 != null)
            {
                winElem5.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp5}");
                return;
            }

            // LeftClick on "Five" at (80,19)
            Console.WriteLine("LeftClick on \"Five\" at (80,19)");
            string xp6 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num5Button\"][@Name=\"Five\"]";
            var winElem6 = session.FindElementByXPath(xp6);
            if (winElem6 != null)
            {
                winElem6.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp6}");
                return;
            }

            // LeftClick on "Six" at (34,18)
            Console.WriteLine("LeftClick on \"Six\" at (34,18)");
            string xp7 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"NumberPad\"][@Name=\"Number pad\"]/Button[@AutomationId=\"num6Button\"][@Name=\"Six\"]";
            var winElem7 = session.FindElementByXPath(xp7);
            if (winElem7 != null)
            {
                winElem7.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp7}");
                return;
            }

            // LeftClick on "Equals" at (59,29)
            Console.WriteLine("LeftClick on \"Equals\" at (59,29)");
            string xp8 = "//*[@ClassName=\"ApplicationFrameWindow\"]/Window[@Name=\"Calculator\"][@ClassName=\"Windows.UI.Core.CoreWindow\"]/Group[@ClassName=\"LandmarkTarget\"]/Group[@AutomationId=\"StandardOperators\"][@Name=\"Standard operators\"]/Button[@AutomationId=\"equalButton\"][@Name=\"Equals\"]";
            var winElem8 = session.FindElementByXPath(xp8);
            if (winElem8 != null)
            {
                winElem8.Click();
            }
            else
            {
                Console.WriteLine($"Failed to find element {xp8}");
                return;
            }

            /*
            if (session != null)
            {
                session.Quit();
                session = null;
            }
            */

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}

実行画面

下図の通り、WinAppDriverを使って問題なく電卓の操作ができました。

感想

軽く触ってみた感じ、要素のXPathを取得できる点は便利でしたが、生成されるコードは冗長で、Excelのマクロ記録機能のような印象を受けました。

UI要素を調べるツールとして、現時点(2018年6月)ではInspectの代わりになるものではなく、Inspectと併用することで、WinAppDriverを使ったコードが書きやすくなるツールなのだと思います。

まだ、出始めのツールなので、今後に期待ですね!

関連記事

  1. Windows 10

    YouTubeの「歌ってみた」動画を非表示にするMicrosoft Edge拡張機能

    私はよくYouTubeで動画を見るのですが、公式PVを見たいだけなのに…

  2. Windows 10

    Microsoft EdgeでWebページを開くインターネットショートカット

    2015/10/12 記事を追加しました。・Microsoft E…

  3. Windows 10

    Microsoft Edgeの拡張機能でHello Worldしてみた。

    「【Windows 10ユーザーズ・ワークベンチ】Edgeの拡張機能サ…

  4. Windows関連

    Windows 8にClassic Shellをインストールしてみました。

    ※ 下記はWindows 8 RTM(日本語版・64ビット)に基づいて…

  5. Windows 10

    PowerShellでMicrosoft Edgeを操作する

    前回の記事でWebDriverを使ってMicrosoft Edgeを操…

  6. Windows 10

    Windows 10に昔のソフトを入れてみました。

    「Windows 10 Technical PreviewにOffic…

コメント

  • コメント (0)

  • トラックバックは利用できません。

  1. この記事へのコメントはありません。

Time limit is exhausted. Please reload CAPTCHA.

最近の記事

アーカイブ

RapidSSL_SEAL-90x50
PAGE TOP