眾所周知,appium和selenium使用的都是客戶/服務架構,它的特色是在客戶端寫測試指令,在服務端執行。這種架構有兩大優點:
1、跨語言,可以使用任何語言編寫Appium代碼;
2、可以構建大型私有或公有的Appium設備雲。
這種架構也存在致命的缺點:降低性能。客戶/服務架構用網絡傳輸測試指令,這必然會受到網絡延遲的影響,甚至天氣不好也會波及。
網絡太不可靠了,總會導致意想不到的卡頓、請求失敗等等。這意味着你在本地跑代碼時很完美,但傳輸到Appium雲去運行時,可能完全不同,可能導致代碼高度脆弱,甚至測試失敗。
最重要的是,很多人不是直接使用Appium命令,而是一些框架。那些基於Appium的封裝工具(對Appium命令進行了封裝,存在過度使用的情況)。
比如,我看到有測試用5~10個請求去找一個元素,僅僅為了檢索元素是否可用,我覺得這個方法不好。它會讓腳本在雲環境上的執行時間存在巨大差異。
除了網速慢,網絡延遲也是一個殺手。比如你想執行命令A,之后立刻執行命令B,基本不可能使用網絡來實現這個功能(B需要延遲才能到達Appium雲服務器,不可能緊接着命令A馬上執行)。
於是,W3C WebDriver規范團隊想出了一個辦法,創造新的Actions API(把整個action chain
編碼成一個API去調用),一旦action開始,鏈可能需要幾秒或幾分鍾才能實際執行
(原文:even though the chain might take seconds or minutes to actually execute
once the action begins.)。
** 使用Execute Driver Script**
Appium團隊已經做了同樣的事情,不僅僅actions,甚至是任何Appium命令。允許在一個Appium命令中打包其它Appium命令。所有這些命令都將在Appium服務器上執行,因此不會受到網絡延遲的影響。它是如何運作的?顯然這很神奇!比如,我們在Java客戶端中編寫下面這個測試腳本:
@Test
p
ublic void testLoginNormally() { driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.findElement(MobileBy.AccessibilityId("Login Screen")).click(); driver.findElement(MobileBy.AccessibilityId("username")).sendKeys("alice"); driver.findElement(MobileBy.AccessibilityId("password")).sendKeys("mypassword"); driver.findElement(MobileBy.AccessibilityId("loginBtn")).click(); driver.findElement(By.xpath("//*[@text='Logout']")).click();}
這是一個簡單的登錄/注銷功能。我們可以使用ExecuteDriverScript命令一次性批量運行所有這些命令:
@Test
public void testLoginWithExecute() {
driver.executeDriverScript(
"await driver.setImplicitTimeout(10000);\n" +
"await (await driver.$('~Login Screen')).click();\n" +
"await (await driver.$('~username')).setValue('alice');\n" +
"await (await driver.$('~password')).setValue('mypassword');\n" +
"await (await driver.$('~loginBtn')).click();\n" +
"await (await driver.$('//*[@text=\"Logout\"]')).click();\n");
}
這到底是怎么回事?它把Appium客戶端的代碼包裹到了字符串里,Appium團隊討論了許多方法,他們一致認為靈活性至關重要。
因此Execute Driver Script命令的參數是一個字符串(字符串使用起來更靈活),表示要在當前運行的Appium
session中執行的JavaScript代碼。該字符串最終由Appium服務器執行。
哇哦!這么做顯然會引發遠程代碼執行漏洞(remote code execution
vulnerability,比如在ExecuteDriverScript中輸入獲取賬號密碼,然后讓服務器來執行)!所以我們需要談談安全問題。
首先,服務器必須指令參數才能啟用Execute Driver Script
(原文:the server must be started in a special mode that allows this feature
explicitly:)
appium --allow-insecure=execute_driver_script
其次,所有代碼都在NodeJS VM中運行,這意味着它無法干擾Appium主程序。
實際上,我們可以嚴格控制執行代碼可以訪問什么方法。除了driver object之外,只提供訪問權限。這個driver
object是什么?它是WebdriverIO session object的一個實例。您可以WebdriverIO API和所有JavaScript語法!
這也正好解釋了上面的代碼,比如代碼中driver.$
相當於findElement,而代碼中的〜表示ID定位。您還可以在字符串中返回文本,數據甚至元素,這些結果在父腳本中也可以使用。
** 使用 Execute Driver Script**
我想了解Execute Driver
Script對測試執行時間的影響,因此我在支持此功能的Appium雲提供商上進行了大量實驗:HeadSpin(感謝HeadSpin)
。我的測試結果(客戶端位置在Vancouver, Canada):
Server|
Using Execute
Driver?
|
Avg Test Time
|
Avg Command
Time
|
Avg Speedup
---|---|---|---|---
Localhost
|
No
|
49.12s
|
0.55s
|
Localhost
|
Yes
|
48.71s
|
0.54s
|
0.8%
Mountain
View, CA
|
No
|
72.53s
|
0.81s
|
Mountain
View, CA
|
Yes
|
43.15s
|
0.48s
|
40.5%
Tokyo,
Japan
|
No
|
102.03s
|
1.13s
|
Tokyo,
Japan
|
Yes
|
42.10s
|
0.47s
|
58.74%
** 分析**
如果在本地執行,使用Execute Driver Script
並不會帶來太多改進。這也很好理解,當客戶端和服務器使用相同的網絡接口時,基本上沒有時間丟失的延遲。但是當Appium服務器位於其他地方時,進步就特別大。
Mountain View, CA離我在Vancouver的辦公室要近一些,而
Tokyo離我的辦公室則遠一些,數據上的差異接近30%(Tokyo的平均時間更長)。這種差異首要問題是延遲,延遲加深了client/server
model中存在的問題。比如命令很多時(每個測試有90個命令),測試時間大約30秒。
當我使用Execute Driver
Script時,所有的90個命令都包含在一個批處理中,結果顯示測試時間降低。由於我只進行了一次網絡調用,因地理分布引起的延遲變得可以忽略不計,將測試行為時間縮短了40-60%!當然,此功能也受其它因素影響,包括批處理調用中輸入的命令數等等……我也不建議將每個命令都填充到
Execute Driver Script,這里僅演示可能的性能改進。
**
**
** 測試方法**
-
這些測試是在HeadSpin在世界各地的真實網絡上運行,並且使用真實的Android設備上,這些設備位於加州山景城和日本東京。(在本地,測試則使用我自己的筆記本電腦,運行手機模擬器和Appium服務器,因此與真實設備有些不同)
-
對於每個測試條件(不同位置,是否使用Execute Driver Script),運行了15個不同的測試。
-
每個測試包括重復登錄和注銷5次。
-
Appium命令的總數(不計算會話開始和退出)是每次測試90個,這意味着每個測試條件總共為1,350個。
-
表中的數字會丟棄會話開始和退出時間,僅計算會話中的測試時間(如果你的時間主要集中在會話開始上,有非常少的命令,那么本篇文章對您用處不大)。
** 總結**
Execute Driver Script
是新的Appium功能,在分布式測試時尤其有用。如果雲服務器或設備位於世界各地,則每個命令將花費很長時間(甚至長於服務器關閉命令)。設備越遠,命令執行時間就越長。管理員可以選擇打開Appium中的Execute
Driver
Script,以允許其用戶批量命令,這樣可以避免與服務器進行大量不必要的延遲,為用戶提供了很多優勢,減少了延遲成本。當然,這是一項高級功能,您只應該用它來解決具體問題!
如果您想查看項目的java代碼,可以在GitHub上查看:
https://github.com/cloudgrey-
io/appiumpro/blob/master/java/src/test/java/Edition085_Execute_Driver_Script.java。
其他Appium客戶端也支持這個新命令,包括WebdriverIO(所以你可以使用WebdriverIO-ception!)
非常感謝HeadSpin啟用該功能並讓我使用設備,因此我可以為本文收集數據。
Cheers,
Jonathan & Jonah
翻譯:若桐
往期推薦
大話JMeter2|正確get參數傳遞和HTTP如何正確使用
- 今日互動 -
**
**
歡迎文章下方留言並分享給其他測試小伙伴哦~
小編PS:
因為很多小伙伴想深入學習性能測試。我們邀請了專注性能十多年的性能架構師高樓老師給大家帶來了《高級性能測試實戰訓練營》,想了解的小伙伴可以添加小助手微信進行咨詢哦。課程信息可點擊下方藍色字體“閱讀原文”進行試聽。
(別忘了 長按 加小助手微信:jasmine07222
回復“ 性能測試 ”即可入群交流哦~)
來霍格沃茲測試開發學社,學習更多軟件測試與測試開發的進階技術,知識點涵蓋web自動化測試 app自動化測試、接口自動化測試、測試框架、性能測試、安全測試、持續集成/持續交付/DevOps,測試左移、測試右移、精准測試、測試平台開發、測試管理等內容,課程技術涵蓋bash、pytest、junit、selenium、appium、postman、requests、httprunner、jmeter、jenkins、docker、k8s、elk、sonarqube、jacoco、jvm-sandbox等相關技術,全面提升測試開發工程師的技術實力
QQ交流群:484590337
公眾號 TestingStudio
點擊獲取更多信息