2021年2月23日火曜日

appium windows driver 入門 1

やりたいこと
appium windows driverを使って、C#のサンプルコードを動作させたい。
電卓を操作するサンプルコードです。

ためした環境
Win10 20H2 Home
Microsoft Visual Studio Community 2019

Step1.Windows10をdevelop modeにする
設定 > 更新とセキュリティ > 開発者向け > 開発者モード : ON
※なんのためにこれをやるのかは分かっていないです。

Step2.WinAppDriver install
こちらのサイトからWindowsApplicationDriver_1.2.1.msiをダウンロードしました。
https://github.com/Microsoft/WinAppDriver/releases
インストーラを起動して、ウィザードに従ってインストールしました。

Step3.サンプルコードのダウンロード
1.こちらのサイトにアクセスします。
https://github.com/microsoft/WinAppDriver
2.右上のcode → download zipを選択します。
Step4.サンプルコードを開く
1.ダウンロードしたフォルダのC#の電卓用のサンプルコードを開きます。以下のパスにあります。
\WinAppDriver-master\Samples\C#\CalculatorTest
CalculatorTest.sln

2.CalculatorTest.slnをダブルクリックして開きます。
※Visual Studioが必要になりますので、入っていない場合はインストールしてください。


Visual Studioが起動したら、一旦このままにしておきます。

Step5.WinAppDriverを起動
C:\Program Files (x86)\Windows Application DriverにあるWinAppDriver.exeをダブルクリックします。 コマンドプロンプトが起動します。
これでWinAppDriverが起動したこのになるので、このままにしておきます。
Step6.テスト実行
いよいよテストを実行します。
Visual Studioにて、テストメニュー > 全てのテストをデバッグを選択します。
電卓が起動して、VisualStudio側で例外が発生したら、ひとまず成功です。

112行目の「splitViewPane.FindElementByName("Standard Calculator").Click();」で例外となります。
これはsampleコードが英語環境用に作られているためとなります。

電卓の左上あたりの「標準」をクリックするというプログラムなのですが、sampleでは「standard calculator」を探しているので、それがなくてエラーとなります。
Step7.UIの情報
日本語環境ではうまく動かないので、日本語のコントロールの名称に置き換えて、sampleコードをまともに動くようにしていきます。

1.UIの情報を取得するツール inspect.exeを起動します。
Visual Studio がインストールされている場合は、下記のパスにあります。
C:\Program Files (x86)\Windows Kits\10\bin\XXXXX\x64 (XXXXX はバージョン番号)
なければ、こちらのページを参考にインストールしてください。
https://qiita.com/RPAbot/items/f1d6438c8f2500db65ae

2.inspect.exeを起動したまま、電卓のクリックしたい場所をマウスでポイントすると、inspect.exeにその情報が表示されます。
sampleの「standard calculator」に該当するのは、「標準 電卓」という名前のようです。


3.先ほど例外が発生したところを下記のように書き換えて、もう一度テストを実行してみます。
(変更前)
splitViewPane.FindElementByName("Standard Calculator").Click();
(変更後)
splitViewPane.FindElementByName("標準 電卓").Click();

先ほどよりは少し進むようになりますが、また別のところで例外が発生すると思います。
あとは同じような感じで直していけば最後まで動くようになります。
最後まで直したコードがこちらになります。
Step8.コードを全面的に修正
全面的に日本語環境用に修正したコードがこちらになります。
//******************************************************************************
//
// Copyright (c) 2017 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
//******************************************************************************

using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using System.Threading;
using System;

namespace CalculatorTest
{
    [TestClass]
    public class ScenarioStandard : CalculatorSession
    {
        private static WindowsElement header;
        private static WindowsElement calculatorResult;

        [TestMethod]
        public void Addition()
        {
            // Find the buttons by their names and click them in sequence to perform 1 + 7 = 8
            session.FindElementByName("1").Click();
            session.FindElementByName("プラス").Click();
            session.FindElementByName("7").Click();
            session.FindElementByName("等号").Click();
            Assert.AreEqual("8", GetCalculatorResultText());
        }

        [TestMethod]
        public void Division()
        {
            // Find the buttons by their accessibility ids and click them in sequence to perform 88 / 11 = 8
            session.FindElementByAccessibilityId("num8Button").Click();
            session.FindElementByAccessibilityId("num8Button").Click();
            session.FindElementByAccessibilityId("divideButton").Click();
            session.FindElementByAccessibilityId("num1Button").Click();
            session.FindElementByAccessibilityId("num1Button").Click();
            session.FindElementByAccessibilityId("equalButton").Click();
            Assert.AreEqual("8", GetCalculatorResultText());
        }

        [TestMethod]
        public void Multiplication()
        {
            // Find the buttons by their names using XPath and click them in sequence to perform 9 x 9 = 81
            session.FindElementByXPath("//Button[@Name='9']").Click();
            session.FindElementByXPath("//Button[@Name='乗算']").Click();
            session.FindElementByXPath("//Button[@Name='9']").Click();
            session.FindElementByXPath("//Button[@Name='等号']").Click();
            Assert.AreEqual("81", GetCalculatorResultText());
        }

        [TestMethod]
        public void Subtraction()
        {
            // Find the buttons by their accessibility ids using XPath and click them in sequence to perform 9 - 1 = 8
            session.FindElementByXPath("//Button[@AutomationId=\"num9Button\"]").Click();
            session.FindElementByXPath("//Button[@AutomationId=\"minusButton\"]").Click();
            session.FindElementByXPath("//Button[@AutomationId=\"num1Button\"]").Click();
            session.FindElementByXPath("//Button[@AutomationId=\"equalButton\"]").Click();
            Assert.AreEqual("8", GetCalculatorResultText());
        }

        [TestMethod]
        [DataRow("1",   "プラス", "7", "8")]
        [DataRow("9",  "マイナス", "1", "8")]
        [DataRow("8", "除算", "8", "1")]
        public void Templatized(string input1, string operation, string input2, string expectedResult)
        {
            // Run sequence of button presses specified above and validate the results
            session.FindElementByName(input1).Click();
            session.FindElementByName(operation).Click();
            session.FindElementByName(input2).Click();
            session.FindElementByName("等号").Click();
            Assert.AreEqual(expectedResult, GetCalculatorResultText());
        }

        [ClassInitialize]
        public static void ClassInitialize(TestContext context)
        {
            // Create session to launch a Calculator window
            Setup(context);

            // Identify calculator mode by locating the header
            try
            {
                header = session.FindElementByAccessibilityId("Header");
            }
            catch
            {
                header = session.FindElementByAccessibilityId("ContentPresenter");
            }            

            // Ensure that calculator is in standard mode
            if (!header.Text.Equals("Standard", StringComparison.OrdinalIgnoreCase))
            {
                session.FindElementByAccessibilityId("TogglePaneButton").Click();
                Thread.Sleep(TimeSpan.FromSeconds(1));
                var splitViewPane = session.FindElementByClassName("SplitViewPane");
                splitViewPane.FindElementByName("標準 電卓").Click();
                Thread.Sleep(TimeSpan.FromSeconds(1));
                Assert.IsTrue(header.Text.Equals("標準", StringComparison.OrdinalIgnoreCase));
            }

            // Locate the calculatorResult element
            calculatorResult = session.FindElementByAccessibilityId("CalculatorResults");
            Assert.IsNotNull(calculatorResult);
        }

        [ClassCleanup]
        public static void ClassCleanup()
        {
            TearDown();
        }

        [TestInitialize]
        public void Clear()
        {
            session.FindElementByName("クリア").Click();
            Assert.AreEqual("0", GetCalculatorResultText());
        }

        private string GetCalculatorResultText()
        {
            string newStr = "";
            newStr = calculatorResult.Text.Replace("表示は", string.Empty).Trim();
            return newStr.Replace("です", string.Empty).Trim();
            //return calculatorResult.Text.Replace("Display is", string.Empty).Trim();
        }
    }
}
Step9.できた!!
これで実行すると、電卓が立ち上がって、計算をして、終了するところまで走ります。
できた。
参考にしたサイト
(1)Appium Windows Driverのページ
http://appium.io/docs/en/drivers/windows/
(2)Windows Application Driver を使った Windows ネイティブアプリケーションの UI テスト自動化
https://qiita.com/yuuhu04/items/5a96608ad96eccee34a0

2021年2月11日木曜日

2021年2月6日土曜日

Android Keystore パスワード 忘れた2

 5年ぐらい前に自分のアプリのkeystoreのパスワードを忘れたという記事を書きました。

こちらです。

当時は、Android_Keystore_Password_Recover_1.07.jar を使用して、忘れたパスワードを探したのですが見つからずあきらめてました。


たまたまこちらの記事を見つけて試してみたら見つかりました。

忘れてしまったAndroidの署名情報は見つかるかもしれない


よかった。


ざっくり言うと、taskartifacts.binをバイナリエディタで開いて、storePasswordで検索したところ、そのちょっと後ろにばっちり書いてありました。keyAliasもありました。

※バイナリエディタで検索するときは大文字/小文字をちゃんと意識して検索したほうがよさそうです。

↓の図では赤いところにパスワードが表示されました。