開發日誌 · 2026-07-07

2026-07-07#e2e-testing#appium#xcode-build#debugging

以下程式碼都是改成通用命名的示意片段,重點在當下怎麼判斷,不對應任何特定專案。

「他們的 commit 會不會弄壞我這邊?」

另一個平台的同事推了兩個 commit 上來,問題丟過來:iOS 這邊還會不會全過?有沒有被影響?

第一個 commit 只動 package.json,純加法,加了一個對方平台專用的 driver,我這邊用的那行原封不動。這種不用想。

第二個麻煩一點——它改的是一支跨平台共用的測試檔。這正是那種你會反射性緊張的地方:共用檔被動了,誰知道會不會波及我。

翻開來看。新增的那段程式碼在收鍵盤、然後 back,大概第 59 行。往上滑,第 51 行:

it('...', function () {
  if (driver.isIOS) this.skip()   // ← 第 51 行,先跳了
  // ...
  await keyboard.dismiss()        // ← 新增的在這,第 59 行
  await nav.back()
})

skip 在新程式碼上面。也就是說,在 iOS 上這支測案根本走不到那幾行——它在第 51 行就掉頭了。就算真的走到,那段也全程 .catch() 包著,不會拋。

對 iOS 零影響。可疑的東西一看就散了。

我把它寫下來不是因為這個判斷多難,而是因為「共用檔被改到」這件事本身很容易讓人跳過閱讀、直接去重跑整套求心安。其實花兩分鐘看一眼 skip 在第幾行,比跑一小時的套件還快、還準。

一份全紅的報告,我沒交出去

靜態看完覺得沒事,但「會不會全過」這種話,不實際跑一遍我不敢講。所以還是把整套十幾支 spec 丟背景跑了。

跑了一個多小時。結果回來:0 過,全倒。 連最基本的 smoke 都紅。

這時候有兩個很好交的結論擺在眼前:「iOS 測試壞了」,或者更誘人的——「對方那兩個 commit 把 iOS 弄壞了」。前面才靜態分析過不會影響,現在數據「打臉」我,寫成報告還很有戲劇性。

但我沒交。因為這份紅得不對。

一個從來會過的套件,不是這裡紅那裡紅,是全部一起倒,連 smoke 都倒——這個形狀不像「每個測案各自壞掉」,像是底下有個共通的東西塌了。抓幾條失敗訊息出來看,清一色是同一句:

Error: no such element: ...

找不到任何元素。不是斷言錯、不是值不對,是畫面上「什麼都定位不到」。這通常只有一種:app 根本沒渲染出測試預期的那個畫面。

那 app 是不是崩了?最快的地面真相——直接把剛 build 的 app 點開,截圖。

它好端端地停在第一個畫面,該有的欄位、按鈕全在。沒崩。

所以 app 活著、元素卻全找不到,只剩一種可能:這個 app 跑的畫面,跟測試以為它會跑的畫面,不是同一個。而這個 run 之所以無效,有一半是我自己造成的——套件在背景跑那一個多小時裡,我同時在改它會用到的共用檔。等於一邊量、一邊動被量的東西。這份紅,量的是一個正在移動的目標。

全綠會騙人,全紅一樣會。差別只在全綠讓你放心、全紅讓你想甩鍋,後者更難忍住不交。

mock 開了,app 卻在打真的後端

另一半原因,追下去更有意思。

這套測試要能跑,app 得 build 成「打假資料」的版本。控制走 mock 還是走真後端的,是一個編譯旗標:結尾 0 是關、1 是開。build 腳本的工作,就是在 build 前把 0 改成 1

它用 sed 去改 .pbxproj 裡的編譯條件設定。大概長這樣:

sed -i '' 's/"DEBUG MOCK0"/"DEBUG MOCK1"/' App.xcodeproj/project.pbxproj

腳本回報「已開啟 mock」。但 app 跑起來,打的還是真後端——畫面出不來,元素全找不到,跟前面那堆 no such element 對上了。

去翻 pbxproj 才發現問題:同一個旗標,檔裡有兩種寫法。 不同 target 各自寫了一份設定,格式還不一樣:

/* A target:引號連著 DEBUG 一起包住 */
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG MOCK0";

/* B target:裸的,沒有引號、沒有 DEBUG */
SWIFT_ACTIVE_COMPILATION_CONDITIONS = MOCK0;

我的 sed pattern 寫死了 "DEBUG MOCK0",只咬得到 A 那種。B 那個裸的 MOCK0 長得不一樣,pattern 對不上,sed 從它旁邊滑過去,原封不動留在 0——關著。

偏偏跑 UI 測試的,就是 B target。腳本改的是 A,測試 build 的是 B。所以「已開啟 mock」是真的(A 開了),測試跑的 app 卻沒開(B 沒動),它去打了真後端。畫面自然一片空,元素全找不到。

這是 sed 改 pbxproj 這類結構化檔的老陷阱:你以為自己在改「那個設定值」,其實你改的只是「長成這個樣子的那串文字」。同一個值換個 target、少個引號、多個空白,就從 pattern 底下溜掉了。要嘛把 pattern 放寬到涵蓋所有寫法,要嘛別拿 sed 硬碰 pbxproj——用讀得懂它結構的工具去改那個 build setting,而不是把它當純文字。

← 回部落格