淺談使用 Appium 進行 React Native 雙平台(iOS & Android)App 的 E2E 自動化測試

Standard

前言

先前在公司的產品流程中導入了單元測試的部份,而最近手上的任務是為 App 產品導入 E2E 測試(End-to-End Test)。由於目前的公司團隊沒有 QA 人員,因此每次產品新版 release 前都必須仰賴工程師自己與產品 Owner 等成員自行手動測試(Manual Testing),隨著產品功能越來越龐大,這個過程越來越曠日費時,也無法確保每次都能測到所有的項目,因此才會有導入 E2E 測試的想法。

本篇文章視角是給像我一樣的非 App 工程師(例如從沒接觸過原生 App 開發、準備踏入 React Native 開發的前端工程師)的經驗分享,又因公司 App 產品是用 React Native 寫的,所以也會提到一些 React Native 在搭配 Appium 測試時需要注意的一些部分(一點點啦)。這也是我首次嘗試 E2E 的測試,著墨不深,有不精確或誤導之處,一樣請偷偷告訴我以便修正文章囉 🙂

自動化測試中的 E2E 測試與比重

自動化測試(Unit test、Integration Test、E2E Test)能為產品的品質帶來更多信心,E2E 測試更是貼近真實使用者的情境下進行整體性的操作測試,「專注在真實使用者情境」--嗯,聽起來 E2E 是很值得投資的事情!不過 Google Testing Blog 曾在 2015 年的 Just Say No to More End-to-End Tests 中提出一些不同的思路。

A failing test does not directly benefit the user.

A bug fix directly benefits the user.

實際上只有在Bug 被修復的時候才能為使用者帶來好處,僅僅測出有錯誤是不夠的。Bug 可能是測試本身不穩定,或是在某種極端情況下才會發生,這不僅費時也很難直接指出錯誤在哪,更別說開發者要怎麼從大量的程式碼中找出錯誤並修復了。

得從小處建立起測試的價值,Unit Test 能夠確保快速(範圍小所以測試快)、可靠(較少受到不穩定因素影響,例如可以離線測試,不會受到網路連線品質影響)、隔離錯誤發生點(單元測試未通過,也能很快地找出錯誤發生點)的特性是個不錯的切入點。在這樣的基石之上,再搭建上整合測試、E2E 測試等,能夠更有效率地讓測試價值最大化。

這些自動化測試的比重如何安排呢?測試金字塔(TestPyramid)的實踐方式滿值得參考的。而在 2014 GTAC (Google Test Automation Conference) 中的 Move Fast & Don’t Break Things 中亦提到了它們的金字塔狀比重,以及反模式的甜筒狀比重:

Pyramid:
測試金字塔

Ice Cream Cone:
測試反模式

Google 建議採用 70/20/10 的比例,70% 用於單元測試、20% 的整合測試,最後是 10% 的 E2E 測試,當然依每個團隊情況不同,但理想上是金字塔狀的,避免甜筒狀及沙漏狀。


唔,好像談太遠了,回來繼續介紹今天的主題--Appium。

Appium 簡介

Appium 是一套跨平台的自動化測試工具,可以測試原生應用程式、含混合型 (Hybird) 的應用程式、Web 等,詳情可見官網的介紹

不僅跨平台,而且它希望能封裝相關的框架(各個平台有自己的測試框架,例如 iOS 9.3+ 的 XCTest、Android 的 UiAutomator 等)成為一套 API(也就是 Selenium WebDriver),讓我們可以在撰寫不同平台的應用程式測試時,使用體驗一致,也增加測試程式碼的重複使用性。

它另外還提供了 GUI 工具 – Appium Desktop,可以在這裡下載

ps.如果結合 Appium Robots 專案,還可以寫遊戲的自動掛機程式(?) XDDD

憤怒鳥


Why Appium?

因為我要撰寫 E2E 測試的產品是雙平台 iOS 及 Android App,所以那些眾多只能測 Web 的框架(例如 PhantomJS)就先掰掰了,而只能測 Android 的框架也不大合用(例如 selendroidRobotium),所以最後是使用 Appium 這個解決方案,且它也發展多年,應該累積不少社群生態圈及資源。

它可以使用任何 WebDriver 能支援的語言,像我們前端團隊可以直接使用 JavaScript,就不用增加其他語言學習成本了。而且是個開源專案,有自己的論壇與 GitHub Issues,以自己的經驗來說,問問題一天內就能獲得合作開發者迅速地回覆,還滿熱心的。

後來在撰寫的過程中,發現有一套阿里釋出的 Macaca E2E 工具也滿優秀的,下次有機會再試試看它囉!

另外還看到一套由 wix 釋出、滿有潛力的 Detox,跟 React Native 整合得很不錯,只不過目前(2017/05)還不支援 Android 的測試,期待它的發展囉!


仍有改進空間的地方

  • iOS 同時多個裝置測試必須透過 SauceLabs 這樣的服務
  • 1.6.4 IDE 還不是很穩定,選擇器也不夠方便
  • 1.6.4 IDE 沒有自動腳本錄製功能
  • 並不像 Jest 般都幫你包好好的服務(測試框架、斷言庫、測試報告等),必須自己上街買菜(?),而不是超值套餐

環境安裝

主要參考官方文件及這幾篇文章:

  1. https://testerhome.com/topics/7775
  2. http://chase-seibert.github.io/blog/2017/01/06/appium-react-native-quickstart.html (這篇是用 python 寫)

在此還是簡單列一下步驟吧!

  1. 安裝 appium 及 appium-doctor
    npm install -g appium
    npm install -g appium-doctor
    

    appium-doctor 是幫你檢查環境是否有闕漏的設定的工具。

  2. 下載 安裝 Appium Desktop。
      (在 1.5.x 版本時,Appium Desktop 不支援 iOS + Xcode 8.3 以上版本,1.6.x 就可以了,不過後者的 XPath Inspector 在 1.6.4 版本反而改的不完整,而且似乎滿不穩定的,常常會遇到 Session has been terminated,只好重開。)
  3. 安裝 Xcode (從 App Store 安裝) & Xcode command line tools
    xcode-select --install
    
  4. 安裝 Carthage
    brew install carthage
    
  5. 安裝 JDK
  6. 安裝 Android Studio 及 Android SDK (可參考 RN 官網說明)
  7. ~/.zshrc (我用 zsh) 設好 ANDROID_HOMEJAVA_HOME 等環境變數
  8. 執行 appium-doctor 看看有什麼還有問題的
    appium-doctor
    

    跑出結果:

    info AppiumDoctor Appium Doctor v.1.4.2
    info AppiumDoctor ### Diagnostic starting ###
    info AppiumDoctor  ✔ The Node.js binary was found at: /Users/patw/.nvm/versions/node/v7.2.1/bin/node
    info AppiumDoctor  ✔ Node version is 7.2.1
    info AppiumDoctor  ✔ Xcode is installed at: /Applications/Xcode.app/Contents/Developer
    info AppiumDoctor  ✔ Xcode Command Line Tools are installed.
    info AppiumDoctor  ✔ DevToolsSecurity is enabled.
    info AppiumDoctor  ✔ The Authorization DB is set up properly.
    info AppiumDoctor  ✔ Carthage was found at: /usr/local/bin/carthage
    info AppiumDoctor  ✔ HOME is set to: /Users/patw
    info AppiumDoctor  ✔ ANDROID_HOME is set to: /Users/patw/Library/Android/sdk
    info AppiumDoctor  ✔ JAVA_HOME is set to: /Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home
    info AppiumDoctor  ✔ adb exists at: /Users/patw/Library/Android/sdk/platform-tools/adb
    info AppiumDoctor  ✔ android exists at: /Users/patw/Library/Android/sdk/tools/android
    info AppiumDoctor  ✔ emulator exists at: /Users/patw/Library/Android/sdk/tools/emulator
    info AppiumDoctor  ✔ Bin directory of $JAVA_HOME is set
    info AppiumDoctor ### Diagnostic completed, no fix needed. ###
    info AppiumDoctor
    info AppiumDoctor Everything looks good, bye!
    info AppiumDoctor
    
  9. 上面都沒問題的話,繼續安裝其他東西:
    brew install libimobiledevice --HEAD  # 注意不要安裝到 1.2.0 版了,該版無法在 iPhone 實機正確印出 log
    npm install -g ios-deploy 
    sudo gem install xcpretty
    npm install app-inspector -g
    

注意:因為 Xcode 7 introduces new UI testing features. Moving forward, Appium iOS Driver will leverage this framework, replacing UI Automation.,所以 iOS 9.3 之後(不含)的版本需要使用 appium-xcuitest-driver,依照它的文件,在這邊我們就不安裝 ideviceinstaller,而是安裝 ios-deploy


Appium Desktop

用途與下載

真的撰寫 Test Case 還是會寫成腳本,工具只是方便我們觀察欲抓取的元素,而 Appium Desktop 就是這套工具。

可以在這裡下載

設定步驟

以 Mac 上的 1.6.4 版本為例:

  1. 下載完後,安裝至 Application 中。
  2. 啟動它,照預設設定點 Start Server v1.6.4 即可。

    image

  3. Server 啟動好了,接著按右上角的 Start New Session

    image

  4. 接著可以用 Automatic Server 進行。(其他的還沒試過,看起來還支援一些雲端測試服務如 SauceLabs 耶)

    image

  5. Desired Capabilities 請參考下面資訊與官方文件填入變數值(目前只能一格一格填,無法直接貼上 json 格式),這邊是以本機啟動的 iOS App + iPhone 6s Simulator 為例:
    {
      "app": "/Users/patw/Projects/news/ios/build/Build/Products/Debug-iphonesimulator/news.app", // iOS 其中一個限制是無法測別人家的 App
      "newCommandTimeout": 60,
      "platformName": "iOS",
      "platformVersion": "10.3",
      "deviceName": "iPhone 6s"
    }
    

    其中 app 就是 Xcode 編譯出來 iOS App 的位置,其餘欄位請依照實際情況填寫。

  6. 可以考慮把這組設定 Save As... 存起來,方便以後使用。存起來之後,會被放在 Saved Capability Sets 頁籤中。
  7. 啟動之後,會看到這樣的畫面:

    image

    這樣就可以透過 Inspector 去觀察頁面元素了。

版本差異

  • 1.5.x
    • 優點:
      1. 可以觀察完整的 XPath
      2. 相較 1.6.4 版穩定
      3. 功能比較多(可以把動作錄成程式碼、有一些不同的手勢等等)
    • 缺點:
      1. iOS + Xcode 8.3 以上版本跑不起來,不支援此版本的 Xcode。但 Android 可行。
      2. 介面比較醜
  • 1.6.4
    • 優點:
      1. 介面美觀多了
      2. 可以跑 iOS + Xcode 8.3 以上版本了
      3. 似乎整合進更多服務
      4. xpath 比較短,是用 * + 第幾個 的方式列的
    • 缺點
      1. 介面簡潔到第一次不大知道該怎麼設定 New Session
      2. 不大穩定,遇過好幾次開好的 Session 掛掉,只能重開
      3. 如果有 accessibility id、name、label 或 type 的情況下,就不會列 xpath 出來

實機測試

iOS

想要進行實機測試(而非模擬器)的設定~~略有~~不同(其實滿多坑的,請繼續看下去),下面一一介紹。

本節的環境是 Xcode 8.3 + iPhone 6s (iOS 10.3) 實機 + Appium Desktop 1.6.4。

英文不錯的朋友也可以直接看 Appium 官方文件 噢。

  1. 首先請先安裝下面兩個軟體:
    brew install libimobiledevice --HEAD
    npm install -g ios-deploy
    
  2. New Session 中的 Desired Capabilities 請加入 xcodeOrgIdxcodeSigningId。後者可以直接填入 iPhone Developer,而前者是什麼呢?其實就是 Team ID(如果你可以佈署到實機上,應該自然是 Apple Developer 了,就應該會有此組設定),請登入 https://developer.apple.com/account 後,在側邊欄的 Membership 頁面中找到 Team ID,是一組 10 個字元的代碼。
  3. 接下來 Desired Capabilities 中的 app 檔案路徑必須是 Xcode 佈署到實機時編譯的 .app 檔案。我曾經傻傻地繼續用佈署到 Simulator 的那個,就可能遇到這樣的錯誤:
    [XCUITest] Error: Could not install app: 'Command 'ios-deploy --id xxxxxxxxxxxxxxxxxxxxxxx --uninstall --bundle /Users/patw/Projects/xxxxxx/ios/build/Build/Products/Debug-iphonesimulator/xxxxx.app' exited with code 253'
    
  4. 另外還要加上修改對應的 platformVersiondeviceName,此外還要加上裝置的 udid。在哪找呢?請打開 Xcode,Window > Devices:
    image

    image

    就是圖中的 Identifier 這個值。

  5. 現在我們的實機設定檔會長得像這樣:
    {
      "app": "/Users/patw/Library/Developer/Xcode/DerivedData/xxxx-drfnlsqbltdfekdfdijibwdepdfn/Build/Products/Debug-iphoneos/xxxx.app",
      "newCommandTimeout": 60,
      "platformName": "iOS",
      "platformVersion": "10.3",
      "deviceName": "XXXX IPhone",
      "udid": "b0fbf219dc0a39239e6df30e166f01a6405f9636",
      "xcodeOrgId": "XXXXXXXXXX",
      "xcodeSigningId": "iPhone Developer"
    }
    
  6. OK,如果現在 Start Session 後,還遇到 info XCUITest xcodebuild exited with code '65' and signal 'null' 的錯誤的話,可能是關於WebDriverAgent 這支 app 應用程式憑證簽署 (code signing) 的問題(我們要在 iPhone 上先啟動這支 app,再啟動要測試的 app,以進行 E2E 測試),請繼續看下去。(Appium 官方文件請看這)。或是直接參考這篇
  7. 我們得去作一個 WebDriverAgent 的簽署設定,請用 Xcode 新建一個專案:

    image

  8. 請選擇 iOSSingle View Application

    image

  9. 這步頗重要的,請設定一組獨特的 Product NameOrganization NameTeam 還有 Organization Identifier

    image

  10. 建立完後,請把 Bundle Identifier 複製下來,在 Appium 中的 Desired Capabilities 增加一個變數 key updatedWDABundleId,值就是 Bundle Identifier
  11. 然後再次 Start Session,應該就能成功安裝 WebDriverAgent 到實機上了。

Android

Android 的設定簡單多了,請參考這邊:

{
  "newCommandTimeout": 60,
  "platformName": "Android",
  "platformVersion": "5.0",
  "deviceName": "ASUS_Z00LD - 5.0.2",
  "app": "/Users/patw/Projects/xxx/android/app/build/outputs/apk/app-debug.apk" // 有 apk 就行,所以也可以測別人的 App
}

基礎架構

我是參考這個專案的:react-native-starter-kit
然後再自己加上測 Android 的部分。

  1. 請先安裝相關套件
    yarn add --dev appium@^1.6.4 appium-doctor@^1.4.2 babel-polyfill@^6.23.0 babel-core@6.14.0 caching-transform@^1.0.1 mocha@^3.1.0 sinon-chai@^2.9.0 wd@^1.2.0
    
  2. 新增 e2e 相關目錄與檔案:
    appium/
      utils/
        compile.js               <--- mocha compiler 設定
        setup.js                 <--- appium 測試腳本用的環境變數定義
      actionServer.js            <--- 主要是啟動 appium server 的方法
      appiumUtils.js             <--- 常用方法,例如啟動 App、自動點擊接受推播要求
      testConfig.js              <--- Desired Capabilities 設定檔
      webDriver.js               <--- WebDriver 相關方法
    scripts/
      build-tests-android.sh     <--- 建置 Android apk 的 script
      build-tests-ios.sh         <--- 建置 iOS app 的 script
      push-test-notification.sh  <--- 發送測試用推播訊息的 script
    test/
      e2e/                       <--- 測試腳本都放這,用附檔名前的 `android` 或 `ios` 區分不同裝置的腳本
        xxx.android.test.js
        xxx.android.test.js
        xxx.ios.test.js
      mocha.opts                 <--- mocha 的預先設定相關參數
    

參考檔案內容如下:

  • appium/actionServer.js
  • appium/appiumUtils.js
  • appium/testConfig.js
  • appium/webDriver.js
  • appium/utils/compile.js
  • appium/utils/setup.js
  • scripts/build-test-android.sh
  • scripts/build-test-ios.sh
  • scripts/push-test-notification.sh
  • test/mocha.opts
  1. 最後在 packages.json 中將入相關的指令:
    "appium:iphonesimulator": "DEVICE_TYPE=iOS DEVICE_CONFIG=iphonesimulator mocha `find test/e2e -name '*.ios.test.js'`",
    "appium:iphone6s": "DEVICE_TYPE=iOS DEVICE_CONFIG=iphone6s mocha `find test/e2e -name '*.ios.test.js'`",
    "appium:android": "DEVICE_TYPE=Android DEVICE_CONFIG=android_asus mocha `find test/e2e -name '*.android.test.js'`",
    

大致是這樣,請依需求自行設定。


遇到的問題

目前選取器 (Selector) 的方案有些半殘

在撰寫 test case 時,我們必須先搞定「選取」元件這件事情,才能指定元件去作點擊之類的行為,在 web 上相對簡單,我們可以很簡單地透過 classname、id、tag 等方式選擇元件,但 React Native 搭配 Appium 就麻煩很多了。

RN 有個叫 testID 的屬性,文件在此,但在 Android 似乎沒有作用,所以有些人就改用 accessibilityLabel 作為測試時的選取標的,但這個屬性原意是給需要無障礙的使用者使用的,移作測試不大不符合語意,但似乎是目前最好的解法了(不知道官方為何一直不收相關的 Pull Request?)。不過要注意的是,這些屬性都只能加在 RN 原生的元件(例如:ViewTouchableOpacity 之類的)上,自訂或第三方元件若沒有實作傳遞到原生元件就會無效。

Android 會把 accessibilityLabel render 成 content-desc 這個屬性:
image

不過 iOS 卻會乖乖地把 accessibilityLabel render 成 labeltestID render 成 name

再不然就得走 XPath 這條路了(雖然又臭又長,又很難一眼辨認出它是什麼元素,而且結構一變更就破壞 test case 了),下面還是簡單介紹一下怎麼用吧。

ps. 因為 Appium Desktop 1.6.4 版對於 XPath 的選擇器顯示不完整,所以也可以透過 Macaca App Inspector 去看 XPath 路徑。(註:Macaca 是阿里釋出的一套自動化測試方案,Inspector 是方案中的選擇器工具,也滿厲害的!)

  1. 安裝
    npm install app-inspector -g
    
  2. 怎麼取得 iOS 的模擬器裝置 udid 呢?
    xcrun simctl list | grep Booted
    

    上面指令會列出目前啟動中的 iOS 裝置,udid 長得像這樣 XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

  3. 然後就可以透過下面指令把 app-inspector 跑起來
    app-inspector -u YOUR-DEVICE-ID
    

    注意:如果上述方法無法跑起來的話,請確認目前開著 iPhone Simulator,且此 Simulator 是由 react-native run-ios 啟動的。

  4. 稍待片刻,會看到訊息
    $ app-inspector -u 4014F798-9485-47DA-AB25-9F0E00C5AD79
    >> xctest-client start with port: 8900
    >> WebDriverAgent version: 1.1.6
    
    >> iOS device started: 4014F798-9485-47DA-AB25-9F0E00C5AD79
    >> inspector start at: http://192.168.6.242:5678
      <-- GET /
      --> GET / 200
      <-- GET /
      --> GET / 200
    
  5. 開啟瀏覽器,就可以看指定項目的 XPath 了image

    看那可怕的 XPath…

另一種方法,也可以在 test cases 中加入

  console.log(await driver.source());

去觀察目前頁面的結構,不過這個方法看不到實際畫面的對應,很不直覺。

其他關於 XPath 的線上工具:

得到 XPath 之後,我們可以透過 wd 中的 elementById 或是 elementByXPath 選擇,詳見 wd API 說明文件,可以依需採用 waitForElementByXXelementByXXIfExists 等方式使用,或是使用 async/await 來非同步地等待尋找元素。

注意:撰寫腳本中盡量不要使用 sleep 加上單純 elementBy 的方式去選取元素,自己估計秒數頗不牢靠,網路一延遲就容易失敗。

Appium Inspector 觀察開發中 Android App 遇到 Could not get BatchedBridge 的解法

如果遇到紅畫面 Could not get BatchedBridge, make sure your bundle is packaged correctly 錯誤,請參考此解法


開始撰寫 test cases

參考資料

實測影片、部分參考測試腳本與小技巧

測試推播

  • 我們推播是透過 OneSignal 發的,然後在 React Native 中是透過 react-native-onesignal 實作。測試時要注意的是,Android 手機接收到推播時畫面當下不能在 App 中,不然有可能會看到「對話框」型的推播通知,而不是出現在通知列。Android 可以透過 .deviceKeyEvent(3) 發送 Home 鍵指令以返回桌面。
  • 「滑開通知列」在 Android 可以用 .openNotifications() 方法達成,而 iOS 得用 TouchAction 自己模擬出 swipe 的動作。
  • 實際測試影片:
    • iPhone 6s:
      E2E
    • Android (ASUS Z00LD):
      E2E

測試 pull to refresh

  • 情境:透過 react-native-scrollable-tab-view 0.7.3(搭配 react-native 0.43.4)實作 pull to refresh 的功能會踩到這個雷,Android 上 pull 到一半有機會會卡死 loading 的圈圈。詳情請見它的這張 issue
  • 比較特別的是,在實際寫這個 case 時,發現這個行為必須是用手指往下滑動(swipe)外,x 軸也必須有 >=18 的偏移量,否則不會觸發卡住的問題。
  • 實際測試影片:
    • Android (ASUS Z00LD):
      E2E

測試往下滑動直到找到某個元素

  • 每個單篇文章詳細頁都有「相關文章」的區塊,但各篇文章長短不一,有可能滾好幾個頁面才會看到該區塊,而 App 機制上又為了省資源而不會把「不在可見範圍」的元素 render 出來,這樣是無法透過 XPath 選取到的,只好自己實作「往下捲動直到找到某元素」的機制了:
    // 捲動的 helper function
    function scrollTo(driver, from, to) {
      const action = new TouchAction(driver);
      const scrollAction = action.press(from)
        .wait(100)
        .moveTo(to) // drag finger up
        .release(); // release finger
    
      return scrollAction;
    }
    
    // 捲動直至找到某元素
    async function scrollUntilFindElement(driver, xpath, scrollAction) {
      const element = await driver.elementByXPathIfExists(xpath);
    
      if (element && await driver.isDisplayed(element)) {
        // found!
      } else {
        await driver.performTouchAction(scrollAction);
        await driver.sleep(1000);
    
        await scrollUntilFindElement(driver, xpath, scrollAction);
      }
    }
    

    實際搭配使用範例:

    await scrollUntilFindElement(driver, '/xx12/xx23/xx231/xx123',
      scrollTo(
        driver,
        { x: winWidth / 2, y: winHeight - 100 },
        { y: -2000 },
      ),
    );
    
  • 實際測試影片:
    • iPhone 6s:
      E2E
    • Android (ASUS Z00LD):
      E2E

swipe 手勢

  • 可透過 wd.TouchAction 模擬 swipe 的手勢,可以這樣寫:
    const action = new TouchAction(driver);
    const scrollDown = action.press({ x: 100, y: 100  })
       .wait(1000)
       .moveTo({ y: 500 }) // drag finger down
       .release(); // release finger
    await driver.performTouchAction(scrollDown);
    

    相當於模擬從 A 點按壓開始、延遲 1000 毫秒、再移動到 B 點、最後放開的一連串動作,也就是 swipe 實際的行為。要特別注意的是,iOS 系統上 B 點的 x, y 的值指的是偏移量,而 Android 則真的是指 B 點座標(因此往上拖動就不能是負的值了);參考資料請見此 Issue,實測 1.6.x 似乎還沒被解決不一致的問題wait 的部分在 Android 上不能太短,不然會沒有效果,建議就用 1000 一秒吧。

印出 React Native 中的 console.log

有時候我們想在 test case 過程中除錯,可能需要在原程式碼中埋些 trace code 方便追查,而因為我們是使用 React Native,所以是用 console.log 作這件事情。

在 Android 中會被放在 logcat 中,可以用 adb logcat *:S ReactNative:V ReactNativeJS:V 篩出相關的訊息,而 iOS 可以透過 deviceconsole 觀察。

若要在測試腳本中印出相關訊息呢?可以透過 .log 這個 API,而因為此方法需要帶入一個 logType 的參數,在 Android 上就是 logcat,而 iOS 分為三種:syslogperformancecrashlog。而且這個方法取出的訊息是全部的 logs,非常大量… 很難找到實際想要追查的部分,所以在 RN 中,也許我們可以寫 console.log('[PATW LOG] foo'),也就是自己加上一個像 [PATW LOG] 這樣一個方便事後可以篩選的字串,之後就可以這樣篩出相關訊息了:

const logs = await driver.log(DEVICE_TYPE === 'iOS' ? 'syslog' : 'logcat');

return logs.filter((log) => {
  return log.message && log.message.includes('[LOG]');
});

不過目前實測發現,iOS 的實機似乎都只能印出空陣列,但在模擬器上一切正常,而 Android 倒是沒什麼問題。這是因為必須安裝 HEAD 版本 (本例是 HEAD-53fede0,而 1.2.0 以前(含)的版本會有這個問題) 的 libimobiledevice

brew install --HEAD libimobiledevice

相關討論請見此 issue


未竟之處

  1. 將測試腳本優化重構,頁面細節抽象化
    (例如 Page Object Modal 的作法)、常用動作抽出
  2. 尚未整合進 CI 流程中
  3. 產出測試報告
    (現有很簡略的 mocha reporter。也許可以加上錯誤時自動擷圖的機制哦)
  4. 多機平行測試
  5. 需求規格如何轉變為 Test Case 的流程
    以及如何挑選哪些情境成為 E2E 的案例

參考文章

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *