# iOS Appium 環境設置 + Python 測試 Demo App
>日期:2022/09/28
>作者:Scott

## 前言
為了紀錄這次研究 ***Appium*** 的一些過程,所以寫了這個文章,文內也會附上當初參考的教學網頁,有興趣的人也可以點進去看,本篇分為以下幾個部分:
- [原理](#原理)
- [***Appium*** 環境設定](#Appium-環境設定)
- [***Appium*** 環境驗證](#Appium-環境驗證)
- [***iOS*** 的 **WebDriverAgent**](#iOS-的-WebDriverAgent)
- [測試環境設定](#測試環境設定)
- [正式測試](#正式測試)
<br/>
------
## 原理

***Appium*** 是一個開放原始碼的自動化測試框架,可以使用同一套測試語法,透過 **WebDriver** 協議,跨平台的驅動 ***iOS***、***Android***、***Windows*** 達到自動化測試。
使用 ***Appium*** 支援的語言編寫測試碼,透過 Http Request 發送請求給 Appium Server,然後 Server 會再把這些請求打包成各語言平台測試架構的語法,部屬在 Device 上執行。
所以概念上,***Appium*** 就只是一個 Server,像翻譯人員一樣的接受到訊號後,負責將測試方的 Action 通知給其他平台,而測試方要做哪些 Action 都由測試方決定,與 ***Appium*** 無太大關係。
在 ***iOS*** 方面,支援 ***Appium*** 的 Libary 為 **XCUITest**,***Android*** 則是 **uiAutomator2**。
目前 ***Appium*** 支援的語言有:***python***、***Java***、***JavaScript***、***Ruby***、***C#***。
<br/>
------
## ***Appium*** 環境設定
以下透過 **Command Line** 安裝需要的工具
- 安裝 ***Homebrew***:要建立 ***Appium*** 環境,需要安裝多個協助工具,所以先安裝 ***Homebrew*** 方便後續作業。
```
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
<br/>
- 安裝 ***Python***:
```
$ brew install python3
```
<br/>
- 安裝 ***appium-python-client***:讓 ***Python*** 連結 ***Appium*** 的一個驅動
```
$ pip3 install appium-Python-Client
```
<br/>
- iOS 需要安裝 ***Carthage*** :
***Carthage*** 是一款 ***iOS*** 項目依賴管理工具,與 **Cocoapods** 有著相似的功能,可以幫助你方便的管理三方依賴,**WebDriverAgent** 本身使用了 ***Carthage*** 管理項目依賴,因此需要提前安裝 ***Carthage***。
```
$ brew install carthage
```
<br/>
- 安裝 ***libimobiledevice***:如果沒有安裝,***Appium*** 會無法連線到 iOS Device
```
$ brew install libimobiledevice --HEAD
```
<br/>
- 安裝 ***node***:***Appium*** 本身是由 ***node.js*** 開發的,所以需要安裝 ***node***,安裝後也會自動安裝了 ***npm*** (***npm*** 全名是 node package manager,就是套件管理工具)
```
$ brew install node
```
<br/>
- 安裝 ***appium-doctor***:驗證 Appium 環境
``` Java
$ npm install appium-doctor -g
```
<br/>
- 安裝 ***Appium***:
```
$ npm install -g appium
```
<br/>
- 安裝 ***Appium Client***:
```
$ npm install wd
```
安裝 ***Appium*** 測試環境的參考網址:
1. http://blog.autoruby.com/2018/07/appium-ios-ui.html
2. https://ithelp.ithome.com.tw/tags/articles/appium
3. https://tw511.com/a/01/6679.html (有 Android 教學)
:::warning
備註:參考網址提到的 Appium Desktop GUI 不一定要安裝,主要是能連接到 Appium Server 後執行 .py 檔。
:::
<br/>
------
## ***Appium*** 環境驗證
在 **Command Line** 輸入指令
```
$ appium-doctor --ios
```
必須要全部都是打 V 的狀態才代表環境是 OK 的。

如果有出現打 X 的情形,由於項目過多,就不在這邊贅述,可以參考以下的網址進行調整:
- https://cloud.tencent.com/developer/article/1801366
- https://www.jianshu.com/p/e33d80978083

<br/>
------
## ***iOS*** 的 **WebDriverAgent**
iOS 移動測試框架,簡稱 WDA,它通過連結 XCTest.framework 和呼叫 ***Apple*** 的 API 來直接在裝置上執行命令,可遠程控制 iOS 設備。
***Facebook*** 的 WDA 在 iOS 10 就被 ***Apple*** 廢棄了,如果是自己上網找載點的,不要抓到 facebook 的版本,有很多坑且無法 compile,會白費很多時間,目前有在更新的就是 ***Appium*** 官方的 WDA。
下載網址:https://github.com/appium/WebDriverAgent
(2022/09/29 測試還可以正常使用)
下載好之後,打開 **webDriverAgent.proj** 檔,更改成你自己的開發者憑證,scheme 請選擇 **WebDriverAgentRunner**

接著點選上方工具列的 **Product** -> **Test**,如果能在測試機或模擬器看到下圖就代表成功了。

:::warning
注意:
1. 不要點到 local build,雖然可以 build Success,但 WebDriverAgent 並不會吃進到測試機/模擬器。
2. 其他的教學網頁有提到要執行 sh ./Scripts/bootstrap.sh -d,我個人是沒有做這個動作就可以測試,我有去 WebDrvierAgnet 的資料夾去找,但資料夾找不到 bootstrap.sh 的檔案。
:::
參考網址:https://cdmana.com/2021/08/20210816192543381l.html
<br/>
-------
## 測試環境設定
#### 我的測試環境版本
>系統 :iOS
>Appium版本 :1.21.0
>python版本 :3.10.6
>測試機 :iphone7
>測試機版本 :13.5.1
>模擬器 :iPhone 11
>其他軟體 :Visual Studio Code (寫 Python 時使用)
#### 設定專案 App 裡元件的 ID
在自動化測試中,需要針對 iOS 元件做操作,所以需要給元件設定 ID,方法很簡單,只要對元件的 Accessibility Identifier 設定 ID 就好,以我的 Demo App 為例,當我開始測試時,希望系統能自動點擊兩個按鈕,讓中間的方塊變色。

所以我就需要針對那兩個按鈕的 Accessibility Identifier 分別設定:redBtn 和 greenBtn
你可以選擇用程式碼去寫,也可以用 Storyboard 直接設定,而方塊因為是按下 Btn 才會變色,屬於 Btn 的 Action,所以方塊不需要設定 ID。
``` Swift=10
greenBtn.accessibilityIdentifier = "greenBtn"
```

<br/>
測試的部分,我是用 ***Python*** 下去寫,搭配 ***Visual Studio Code*** 這個軟體,可以自行去 ***Visual Studio Code*** 官網下載,***Python***、***Visual Studio Code*** 的教學可以參考這個 ***YouTube*** 連結:https://www.youtube.com/watch?v=zdMUJJKFdsU
建好 ***Python*** 的專案後,先 import Library
``` Python
import unittest
import os
from random import randint
from appium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
```
再來就看你是要用實機測試或模擬器測試,設定方式會不同:
<br/>
#### Xcode 模擬器的設定
``` Python
def setUp(self):
app = ("請輸入 iOS 專案的 .app 路徑")
self.driver = webdriver.Remote(
command_executor='http://0.0.0.0:4723/wd/hub',
desired_capabilities={
"app": app,
"platformName" : "iOS",
"automationName" : "XCUITest",
"deviceName" : "請輸入模擬器名稱",
"bundleId" : "請輸入 iOS 專案的 bundleID",
"noReset" : "true",
"autoAcceptAlerts": "true"
}
)
```
:::info
各個欄位的用途,可以參考這個網址:
https://appium.io/docs/cn/writing-running-appium/caps/index.html
:::
這邊的 .app 路徑,並不是指專案在 Mac 裡的路徑,而是指專案在 Xcode Compile 後所產生的 .app 檔的路徑,要找到 .app 路徑的話,可以在 **Command line** 將位置切換到專案的資料夾底下,輸入下列指令找出現在正在使用的模擬器版本
```
xcodebuild -showsdks
```

<br/>
然後 **Command line** 繼續輸入:
```
xcodebuild -sdk iphonesimulator15.2
```
<br/>

<br/>
#### 實機的設定
``` Python
def setUp(self):
app = ("請輸入 iOS 專案的 .app 路徑")
self.driver = webdriver.Remote(
command_executor='http://0.0.0.0:4723/wd/hub',
desired_capabilities={
"app": app,
"platformName" : "iOS",
"automationName" : "XCUITest",
"platformVersion" : "請輸入測試機的 iOS 版本",
"deviceName" : "請輸入 iOS 測試機的名稱",
"udid" : "請輸入 iOS 測試機的 udid",
"bundleId" : "請輸入 iOS 專案的 bundleID",
"noReset" : "true",
"autoAcceptAlerts" : "true",
"xcodeOrgId" : "請輸入你開發者帳號的 team ID",
"xcodeSigningId" : "iPhone Developer",
}
)
```
.app 路徑一樣是到 **Command line** 並將位置切換到你的專案的資料夾底下,連接著測試機,輸入下列指令找出
```
$ xcodebuild -project iOS專案名稱.xcodeproj -scheme iOS專案的Scheme名稱 -destination 'platform=iOS,name=iOS測試機名稱'
```
:::info
如果是有 ***Cocoapods*** 的 iOS 專案,要記得把「**<font color="#f00">-project</font>**」改成「**<font color="#f00">-workspace</font>**」,以及「**<font color="#f00">專案名稱.xcodeproj</font>**」 改成 「**<font color="#f00">專案名稱.xcworkspace</font>**」;後面的 -destination 的 「**<font color="#f00">name="測試機名稱"</font>**」,可以改成 「**<font color="#f00">id="測試機的 udid"</font>**」,但 name 跟 id 只能選一個輸入,兩個都輸入的話會error。
:::
<br/>
回到 ***Python*** 的部分,模擬器/實機設定好之後,接著是找到 App 的 Btn:點擊變紅色的按鈕 (綠色按鈕的 Action 以此類推)
``` Python
def redAction(self):
self.driver.find_element(By.ID,"redBtn").click()
sleep(1)
```
最後就是測試 func,名稱可以自訂,但前面必須要是 test 開頭
``` Python
def testMultiTime(self):
for i in range(2):
self.redAction()
self.greenAction()
sleep(1)
```
<br/>
------
## 正式測試
以上環境都設定好之後:
1. 連上你的測試機。
2. 把你的專案 local build 到測試機裡,測試時,專案並不一定要在 compile 的狀態,但必須要有安裝這個 App。
3. 開啟 **WebDriverAgent.xcodeproj**,點選 **Product** -> **Test**,測試時一樣不需要保持在 **Test** 的狀態,但 **WebDriverAgentRunner** 至少要啟動過一次。
4. **Command Lin** 輸入 「**<font color="#f00">appium</font>**」或是 **Appium Desktop GUI** 開啟 **Appium Server**。
5. compile 你自己寫的 Python Code 就會開始自動測試了。
:::info
測試完如果要關閉 **Appium Server** 的話,可在 **Command Line** 按下「 Ctrl + C 」,GUI 工具則是點選 Stop 即可。
:::

<br/>
以上,就是我的 ***Appium*** 設定 + 測試的經驗分享,如有寫不好的地方,歡迎提出討論,謝謝。
<br/>
------