Appium自動化Windows APP

博客首發
前提條件
環境搭建
  • 打開Windows PC的開發者模式

  • 下載Windows SDK並默認安裝

  • 下載Windows driver並默認安裝

  • 運行WinAppDriver.exe(記得要用admin權限運行), 默認路徑 (C:\Program Files (x86)\Windows Application Driver)
    可以自定義地址或端口:

    WinAppDriver.exe 4727
    WinAppDriver.exe 127.0.0.1 4725
    WinAppDriver.exe 127.0.0.1 4723/wd/hub
    

    如下圖:
    在這裏插入圖片描述

Windows 自動化腳本

運行腳本前要打開 WinAppDriver.exe
對於Windows App來說,只需要傳一個app capabilities 即可。
對於UWP的App,app對應的值爲Application Id(App ID)。關於如何獲取APP ID,可以使用powershell命令get-StartApps來獲取,打開powershell終端運行:get-StartApps | select-string "計算器"即可獲取值(運行命令之前先打開計算器)。以下是java樣例代碼:

 DesiredCapabilities cap = new DesiredCapabilities();
 cap.setCapability("app", "LexisNexisAPAC.LexisRed_wsek3cqrhvvz2!App");
 driver = new WindowsDriver(new URL("http://127.0.0.1:4723"), cap);
 driver.findElementByAccessibilityId("CalculatorResults");

對於經典的Windows App,app對應的值爲可執行的.exe文件路徑。以下是java樣例代碼:

// Launch Notepad
DesiredCapabilities cap= new DesiredCapabilities();
cap.SetCapability("app", "C:\\Windows\\System32\\notepad.exe");
cap.SetCapability("appArguments", "MyTestFile.txt");
cap.SetCapability("appWorkingDir", "C:\\MyTestFolder");
driver= new WindowsDriver(new URL("http://127.0.0.1:4723"), cap);
// Use the session to control the app
driver.FindElementByClassName("Edit").SendKeys("This is some text");
Windows定位元素

使用Windows SDK提供的工具inspect.exeC:\Program Files (x86)\Windows Kits\10\bin\x86或者C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64根據系統查看)來定位,詳情查看inspect,或者使用AccExplorer32UISpy定位。
支持的定位方式:

API 定位方法 對應inspect.exe的屬性 例子
FindElementByAccessibilityId accessibility id AutomationId AppNameTitle
FindElementByClassName class name ClassName TextBlock
FindElementById id RuntimeId (decimal) 42.333896.3.1
FindElementByName name Name Calculator
FindElementByTagName tag name LocalizedControlType (upper camel case) Text
FindElementByXPath xpath Any //Button[0]
計算器的例子

Python(GitHub):

import unittest
from appium import webdriver


class WindowsCalculatorTest(unittest.TestCase):

    @classmethod
    def setUpClass(self):
        # set up appium
        desired_caps = {}
        desired_caps["app"] = "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"
        self.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities=desired_caps)

    @classmethod
    def tearDownClass(self):
        self.driver.quit()

    def getresults(self):
        displaytext = self.driver.find_element_by_accessibility_id("CalculatorResults").text
        displaytext = displaytext.strip("顯示爲 ")
        displaytext = displaytext.rstrip(' ')
        displaytext = displaytext.lstrip(' ')
        return displaytext

    def test_addition(self):
        self.driver.find_element_by_name("一").click()
        self.driver.find_element_by_name("加").click()
        self.driver.find_element_by_name("七").click()
        self.driver.find_element_by_name("等於").click()
        self.assertEqual(self.getresults(), "8")

    def test_combination(self):
        self.driver.find_element_by_name("七").click()
        self.driver.find_element_by_name("乘以").click()
        self.driver.find_element_by_name("九").click()
        self.driver.find_element_by_name("加").click()
        self.driver.find_element_by_name("一").click()
        self.driver.find_element_by_name("等於").click()
        self.driver.find_element_by_name("除以").click()
        self.driver.find_element_by_name("八").click()
        self.driver.find_element_by_name("等於").click()
        self.assertEqual(self.getresults(), "8")

    def test_division(self):
        self.driver.find_element_by_name("八").click()
        self.driver.find_element_by_name("八").click()
        self.driver.find_element_by_name("除以").click()
        self.driver.find_element_by_name("一").click()
        self.driver.find_element_by_name("一").click()
        self.driver.find_element_by_name("等於").click()
        self.assertEqual(self.getresults(), "8")

    def test_multiplication(self):
        self.driver.find_element_by_name("九").click()
        self.driver.find_element_by_name("乘以").click()
        self.driver.find_element_by_name("九").click()
        self.driver.find_element_by_name("等於").click()
        self.assertEqual(self.getresults(), "81")

    def test_subtraction(self):
        self.driver.find_element_by_name("九").click()
        self.driver.find_element_by_name("減").click()
        self.driver.find_element_by_name("一").click()
        self.driver.find_element_by_name("等於").click()
        self.assertEqual(self.getresults(), "8")


if __name__ == '__main__':
    unittest.main()

java(GitHub):

import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.util.concurrent.TimeUnit;
import java.net.URL;
import io.appium.java_client.windows.WindowsDriver;

import org.testng.Assert;
import org.testng.annotations.*;

public class WindowsCalculatorTest {

    private static WindowsDriver CalculatorSession = null;
    private static WebElement CalculatorResult = null;

    @BeforeClass
    public static void setup() {
        try {
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability("app", "Microsoft.WindowsCalculator_8wekyb3d8bbwe!App");
            CalculatorSession = new WindowsDriver(new URL("http://127.0.0.1:4723"), capabilities);
            CalculatorSession.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
            CalculatorResult = CalculatorSession.findElementByAccessibilityId("CalculatorResults");

        }catch(Exception e){
            e.printStackTrace();
        } finally {}
    }

    @AfterClass
    public static void TearDown()
    {
        CalculatorResult = null;
        if (CalculatorSession != null) {
            CalculatorSession.quit();
        }
        CalculatorSession = null;
    }

    @Test
    public void Addition()
    {
        CalculatorSession.findElementByName("七").click();
        CalculatorSession.findElementByName("七").click();
        CalculatorSession.findElementByName("加").click();
        CalculatorSession.findElementByName("八").click();
        CalculatorSession.findElementByName("等於").click();
        Assert.assertEquals("顯示爲 85", CalculatorResult.getText());
    }

    @Test
    public void Combination()
    {
        CalculatorSession.findElementByName("七").click();
        CalculatorSession.findElementByName("乘以").click();
        CalculatorSession.findElementByName("九").click();
        CalculatorSession.findElementByName("加").click();
        CalculatorSession.findElementByName("一").click();
        CalculatorSession.findElementByName("等於").click();
        CalculatorSession.findElementByName("除以").click();
        CalculatorSession.findElementByName("八").click();
        CalculatorSession.findElementByName("等於").click();
        Assert.assertEquals("顯示爲 8", CalculatorResult.getText());
    }

    @Test
    public void Division()
    {
        CalculatorSession.findElementByName("六").click();
        CalculatorSession.findElementByName("四").click();
        CalculatorSession.findElementByName("除以").click();
        CalculatorSession.findElementByName("八").click();
        CalculatorSession.findElementByName("等於").click();
        Assert.assertEquals("顯示爲 8", CalculatorResult.getText());
    }

    @Test
    public void Multiplication()
    {
        CalculatorSession.findElementByName("六").click();
        CalculatorSession.findElementByName("乘以").click();
        CalculatorSession.findElementByName("八").click();
        CalculatorSession.findElementByName("等於").click();
        Assert.assertEquals("顯示爲 48", CalculatorResult.getText());
    }

    @Test
    public void Subtraction()
    {
        CalculatorSession.findElementByName("九").click();
        CalculatorSession.findElementByName("減").click();
        CalculatorSession.findElementByName("一").click();
        CalculatorSession.findElementByName("等於").click();
        Assert.assertEquals("顯示爲 8", CalculatorResult.getText());
    }
}
參考
  • http://appium.io/docs/en/drivers/windows/
  • https://github.com/Microsoft/WinAppDriver?WT.mc_id=-blog-scottha
問題總結

org.openqa.selenium.WebDriverException: Failed to locate opened application window with appId

遇到此問題是在啓動APP時報的錯,成功的啓動了APP,但是拋出這個異常,導致後續無法測試,目前找了一個臨時解決方案:在new driver時增加try catch機制,即可避免,例如:

try {
   driver = new WindowsDriver(new URL("http://127.0.0.1:4723"), cap);
}catch (Exception e){
//            e.printStackTrace();
   driver = new WindowsDriver(new URL("http://127.0.0.1:4723"), cap);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章