AD

2024-11-28

Postman (newman) 到 Github actions 上的一些小記錄

前陣子遇到一個需求,團隊的 API 測試放在 postman 上,所以想要試試讓 Postman 放在 Github Actions 上面執行。當時花蠻多時間的,紀錄一些過程。
 
1. 在 Postman CLI 和 Newman 做選擇
 
Postman CLI 是官方提供的 CLI 套件,而 Newman 是社群維護的。
一開始我先用了 Postman CLI。
畢竟是官方提供,整合做得很好。有些 API 測試時需要上傳的檔案,有在 postman 上傳過並儲存在 postman cloud 的話,都可以直接使用。而測試結果直接顯示在 Postman 的 Runs 裡面——
沒想到這竟然是個缺點,它的 reporter 不能自訂,唯一的 report 就是要去剛剛提到的 Runs 裡面看,不然就是直接來自執行時的 CLI ⋯⋯(來源參考 https://community.postman.com/t/postman-cli-reporting/66763)
 
所以就因為 Newman 可以自訂 reporter,直接選了 Newman XDDDD
 
2. 上傳檔案的測試
 
用了 newman 也不是就一帆風順。
比方上傳檔案的話有點麻煩,要匯出 collection 之後填上檔案路徑。
這比起用 Postman CLI 麻煩多了。原先在 postman 改完 collection 裡的任何部分之後執行就能生效。但為了讓 Newman 上傳檔案,用匯出的 collection 就沒辦法了QQ
 
3. 執行失敗的 log
 
當時還有一點痛苦的,就是失敗時沒有 response 的 log ⋯⋯Postman CLI 也一樣。
可以做到的方法大致上是在每一個 API 的 post-script 加上紀錄:
pm.test("Response status code is 200", function () {
    if (pm.response.code !== 200) {
        throw new Error(`Response Code: ${pm.response.code} | Response Body: ${pm.response.text()} | Request Body: ${JSON.stringify(pm.request.body)}`);
    }
    pm.response.to.have.status(200);
});;


總之成功在 Actions 上跑了一段時間,不過後來還是決定換成自己寫的 API 框架了。謹此紀念沒跑多久的 Postman 上 Github Actions 經歷XDD

2024-11-25

Selenium 4.6 之後你真的不用下載 webdriver 或使用 WebDriverManager

如題。

在 Selenium 4.6 之後,已經不用另外下載 webdriver,不用帶路徑,不用使用 WebDriverManager 解決下載和帶路徑的問題。

你只需要:

from selenium import webdriver

driver = webdriver.Chrome()

這樣就可以跑了!預設是目前的 stable 版本。

-

如果你需要特定版本的 chrome,可以用Options指定,selenium manager 會自動下載你指定的版本:

options = webdriver.ChromeOptions()

options.browser_version = '120'

driver = webdriver.Chrome(options=options)

除了特定版本號,也可以帶標籤如stable(目前 CfT 版本)、beta(下一個版本穩定)、dev(目前正在開發版本)、canary(為開發人員每晚建置)、esr(擴充支援版本,僅用於 Firefox)。

2024-11-19

Selenium + ChromeDriver - 開啟 DevTools 的行動裝置模式

在 Google Chrome 瀏覽器的 F12 開發工具中,有個很方便的行動裝置模式,可以模擬網站在行動裝置上的顯示和行為。在測試為手機、平板設計的網站時非常好用!
 
在自動化的時候也可以用 add_experimental_option 來設定 webdriver 開啟行動裝置模式,上個最小 Python 範例:

from selenium import webdriver

mobile_emulation = { "deviceName": "iPhone 12 Pro" }
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome(options=options)

deviceName 具體有哪些 device,可以看一下自己的 Chrome 有哪些內建的裝置可以使用:
點擊上面選單的 Edit,還有更多的裝置,也可以新增自己設定:

至於在 code 裡可以用類似下面的方式來設定自己需要的裝置設定:

from selenium import webdriver

mobile_emulation = {
    "deviceMetrics": { "width": 360, "height": 640, "pixelRatio": 3.0 },
    "userAgent": "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
    "clientHints": {"platform": "Android", "mobile": True} 
}
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome("/driver/path", options=options)

2024-11-14

Appium iOS - 你確定 build 了 simulator 可以執行的 app,但還是一直噴錯怎辦?要不要用一下 bundleId?

事情是這樣的,我和開發拿到了可以給 simulator 執行的 .app 檔案。
直接拖曳 app 丟到 simulator 裡它可以順順打開、可以妥妥操作。

但是當我用 Appium 以這個 capability 開 app 就出4了:
  "appium:deviceName": "iPhone 15 Pro",
  "appium:automationName": "XCUITest",
  "platformName": "iOS",
  "appium:platformVersion": "17.5",
  "appium:app": "/Users/username/Desktop/folder/Demo.app" 
}

會遇到錯誤: Failed to create session. An unknown server-side error occurred while processing the command. Original error: The com.testdomain.test-demo-ios.dev application does not support the x86_64 Simulator architecture: Non-fat file: /Users/username/Desktop/folder/Demo.app/Demo is architecture: arm64 Please rebuild your application to support the x86_64 platform. 

為什麼?為什麼???直接裝也可跑啊?人家真的就有 support x86_64 啊。
我問天——我問天——甘會當莫創治—— 

然後啊,在我跟開發確認了幾次,很怕被揍的時候,我才想到我先在 simulator 安裝好就可以用 bundleId 開啟嘛:
  "appium:deviceName": "iPhone 15 Pro",
  "appium:automationName": "XCUITest", 
  "platformName": "iOS",
  "appium:platformVersion": "17.5", 
  "appium:bundleId": "com.testdomain.test-demo-ios.dev"
}

太好了,太好了!
流程上不同的大概只有要先指令裝 app,需要的話加個 reset capability。

ADB - 從裝了 app 的手機拿到 apk 檔

有些時候在實體機上裝了 app,想拿到模擬器上安裝。這個時候複製檔案的 adb pull 就很好用!

首先找到你想抓的 app 安裝在哪:
adb shell "pm list packages -f | grep 你想抓的Package名稱" 

以下舉例,假設我想找蝦皮 app,在終端機輸入:
adb -d shell "pm list packages -f|grep shopee" 

會回傳:
package:/data/app/com.shopee.tw.int-X1xsowqyHAerEoslb2fxj00g==/base.apk=com.shopee.tw.int 

那個 /data/app/com.shopee.tw.int-X1xsowqyHAerEoslb2fxj00g==/base.apk 就是 app 安裝的位置!
把 app 拉到你現在終端機的工作路徑下:
adb pull /data/app/com.shopee.tw.int-X1xsowqyHAerEoslb2fxj00g==/base.apk 

現在你就有 base.apk 了!
不出意外的話,你可以把 base.apk 裝在你的模擬器上使用~

2024-11-11

Appium Android 起手式 - 取得 appPackage 和 appActivity

在使用 Appium 進行 Android 自動化測試時,appPackage 和 appActivity 是必要的參數。

取得方式很多,記錄一下我習慣用的方法:
adb shell dumpsys window | grep -E "mCurrentFocus"
確定已經連到了 Android 裝置,並開啟 app,輸入上面的指令。

回傳的結果會是目前開啟的 app 和 app 頁面,如:appPackage/appActivity 的格式的資訊。

實際例子,開啟 Chrome app 之後: mCurrentFocus=Window{1c35821 u0 com.android.chrome/com.google.android.apps.chrome.Main} appPackage 是 com.android.chrome,appActivity 是 com.google.android.apps.chrome.Main。
-
要注意的是,appActivity 是能進 app 的第一個畫面,有些 app 開啟時可能閃現一下就跳到下一個畫面。沒有找到正確的可能會有類似以下的錯誤:
exited with code 255'; Command output: Exception occurred while executing 'start': java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000
這種時候可以拼手速,在一開啟載入閃現那個第一個畫面就趕快 enter 指令,但也可以用 Android Studio 或其他編輯器打開 apk 檔的 AndroidMainfest.xml,找到含有 android.intent.action.MAIN 的 Activity。
實際例子,有個 Activity 有這樣的內容 :
<activity
    android:name="com.example.app.loading.LoadingActivity"
    android:exported="true"
    android:screenOrientation="1"
    android:hardwareAccelerated="false">

    <intent-filter>
        <action
            android:name="android.intent.action.MAIN" />
        <category
            android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

</activity>
那就是這個 Activity 了!

2024-11-06

Appium 2.0 錯誤 Could not find a driver for automationName 'xxxxxx' and platformName 'xxxxxx'

剛升到 Appium 2.0 執行以前的 code 可能會遇到錯誤:
could not find a driver for automationname 'uiautomator2' and platformname 'android'

因為 Appium 2.0 版本開始,driver(例如 uiautomator2、xcuitest 等)都變成獨立的套件,需要單獨安裝。

安裝:
appium driver install uiautomator2 

確認安裝了哪些 driver:
appium driver list 

會顯示你目前裝了什麼和沒裝什麼:
✔ Listing available drivers
- uiautomator2@3.8.1 [installed (npm)]
- xcuitest [not installed]
- espresso [not installed]
- mac2 [not installed]
- windows [not installed]
- safari [not installed]
- gecko [not installed]
- chromium [not installed]

裝自己要用到的就好! 

另外 appium driver list 有參數可以只看有裝的 driver:
appium driver list --installed

會顯示: 
✔ Listing installed drivers 
- uiautomator2@3.8.1 [installed (npm)] 

裝完之後,如果你原本有跑 appium server,記得重開才會生效~

2024-04-08

[筆記] 解決 remote chrome 不支援 network throttling

我之前遇到一個專案,需要在弱網環境測試影片播放的狀況。

一般 webdriver 用 set_network_conditions 就可以設定網路速度,但是我們需要使用 remote webdriver 來連線倒 webdriver 的 docker,這時就會發現 remote webdriver 沒有 set_network_conditions,會有這樣的錯誤:

AttributeError: module 'selenium.webdriver.chromium.webdriver' has no attribute 'set_network_conditions'

搜尋之後也確實發現官方說 vendor-specific endpoints 目前只支援 vendor-specific webdriver class(set_network_conditions 只有特定供應商比方 webdriver.Chrome 能使用),所以 webdriver.Remote 確實沒有 set_network_conditions。

一開始前人使用的方法是一個 docker 包含整個作業系統和測試的 code,雖然不常需要改動,但如果真的需要,每次要對 code 做小調整都要整個 docker 重包,實在很不放便,於是我想說還是該解決一下這個問題⋯⋯

雖然 webdriver.Remote 不支援 set_network_conditions,但 docker webdriver 和 selenium webdriver 當然還是有這個功能的,所以這裡使用 types.MethodType,將 ChromiumRemoteConnection 中的 set_network_conditions 和 get_network_conditions 方法綁定到 driver 物件上。

範例 code 如下:

這樣就成功讓 docker webdriver 限速了,有需要時都能夠方便的修改 code 了~

如果文章有幫助到你可以在 LikeCoin 上幫我拍手喔