
前言
做過自動(dòng)化測試的人應(yīng)該都會(huì)有這樣一種體會(huì),要寫個(gè)自動(dòng)化demo測試用例很容易,但是要真正將自動(dòng)化測試落地,對成百上千的自動(dòng)化測試用例實(shí)現(xiàn)較好的可復(fù)用性和可維護(hù)性就很難了。
基于這一痛點(diǎn),我開發(fā)了AppiumBooster框架。顧名思義,AppiumBooster基于Appium實(shí)現(xiàn),但更簡單和易于使用;測試人員不用接觸任何代碼,就可以直接采用簡潔優(yōu)雅的方式來編寫和維護(hù)自動(dòng)化測試用例。
原型開發(fā)完畢后,我將其應(yīng)用在當(dāng)前所在團(tuán)隊(duì)的項(xiàng)目上,并在使用的過程中,按照自己心目中理想的自動(dòng)化測試框架的模樣對其進(jìn)行迭代優(yōu)化,最終打磨成了一個(gè)自己還算用得順手的自動(dòng)化測試框架。
本文便是對AppiumBooster的核心特性及其設(shè)計(jì)思想進(jìn)行介紹。在內(nèi)容組織上,本文的各個(gè)部分相對獨(dú)立,大家可直接選擇自己感興趣的部分進(jìn)行閱讀。
UI交互基礎(chǔ)
UI交互是自動(dòng)化測試的基礎(chǔ),主要分為三部分內(nèi)容:定位控件、操作控件、檢測結(jié)果。
控件定位
定位控件時(shí),統(tǒng)一采用元素ID進(jìn)行定位。這里的ID包括accessibility_id或accessibility_label,需要在iOS工程項(xiàng)目中預(yù)先進(jìn)行設(shè)置。
另外,考慮到控件可能出現(xiàn)延遲加載的情況,定位控件時(shí)統(tǒng)一執(zhí)行wait操作;定位成功后會(huì)立即返回控件對象,定位失敗時(shí)會(huì)進(jìn)行等待并不斷嘗試定位,直到超時(shí)(30秒)后拋出異常。
wait { id control_id }
源碼路徑:AppiumBooster/lib/pages/control.rb
控件操作
根據(jù)實(shí)踐證明,UI的控件操作基本主要就是點(diǎn)擊、輸入和滑動(dòng),這三個(gè)操作基本上可以覆蓋絕大多數(shù)場景。
-
scrollToDisplay: 根據(jù)指定控件的坐標(biāo)位置,對屏幕進(jìn)行上/下/左/右滑動(dòng)操作,直至將指定控件展示在屏幕中 -
click: 通過控件ID定位到指定控件,并對指定控件進(jìn)行click操作;若指定控件不在當(dāng)前屏幕中,則先執(zhí)行scrollToDisplay,再執(zhí)行click操作 -
type(text): 在指定控件中輸入字符串;若指定控件不在當(dāng)前屏幕中,則先執(zhí)行scrollToDisplay,再執(zhí)行輸入操作 -
tapByCoordinate: 先執(zhí)行scrollToDisplay,確保指定控件在當(dāng)前屏幕中;獲取指定控件的坐標(biāo)值,然后對坐標(biāo)進(jìn)行tap操作 -
scroll(direction): 對屏幕進(jìn)行指定方向的滑動(dòng)
源碼路徑:AppiumBooster/lib/pages/actions.rb
預(yù)期結(jié)果檢查
每次執(zhí)行一步操作后,需要對執(zhí)行結(jié)果進(jìn)行判斷,以此來確定測試用例的各個(gè)步驟是否執(zhí)行成功。
當(dāng)前,AppiumBooster采用控件的ID作為檢查對象,并統(tǒng)一封裝到check_elements(control_ids)方法中。
在實(shí)際使用過程中,需要先確定當(dāng)前步驟執(zhí)行完成后的跳轉(zhuǎn)頁面的特征控件,即當(dāng)前步驟執(zhí)行前不存在該控件,但執(zhí)行成功后的頁面中具有該控件。然后在操作步驟描述的expectation屬性中指定特征控件的ID。
具體地,在指定控件ID的時(shí)候還可以配合使用操作符(!,||,&&),以此實(shí)現(xiàn)多種復(fù)雜場景的檢測。典型的預(yù)期結(jié)果描述形式如下:
-
A: 預(yù)期控件A存在; -
!A: 預(yù)期控件A不存在; -
A||B: 預(yù)期控件A或控件B至少存在一個(gè); -
A&&B: 預(yù)期控件A和控件B同時(shí)存在; -
A&&!B: 預(yù)期控件A存在,但控件B不存在; -
!A&&!B: 預(yù)期控件A和控件B都不存在。
源碼路徑:AppiumBooster/lib/pages/inner_screen.rb
測試用例引擎(YAML)
對于自動(dòng)化測試而言,自動(dòng)化測試用例的組織與管理是最為重要的部分,直接關(guān)系到自動(dòng)化測試用例的可復(fù)用性和可維護(hù)性。
經(jīng)過綜合考慮,AppiumBooster從三個(gè)層面來描述測試用例,從低到高分別是step、feature和testcase;描述方式推薦使用YAML格式。
steps(測試步驟描述)
首先是對于單一操作步驟的描述。
從UI層面來看,每一個(gè)操作步驟都可以歸納為三個(gè)方面:定位控件、操作控件和檢查結(jié)果。
AppiumBooster的做法是,將App根據(jù)功能模塊進(jìn)行拆分,每一個(gè)模塊單獨(dú)創(chuàng)建一個(gè)YAML文件,并保存在steps目錄下。然后,在每個(gè)模塊中以控件為單位,分別進(jìn)行定義。
現(xiàn)以如下示例進(jìn)行詳細(xì)說明。
---
AccountSteps:
enter Login page:
control_id: tablecellMyAccountLogin
control_action: click
expectation: btnForgetPassword
input test EmailAddress:
control_id: txtfieldEmailAddress
control_action: type
data: leo.lee@debugtalk.com
expectation: sectxtfieldPassword
check if coupon popup window exists(optional):
control_id: inner_screen
control_action: has_control
data: btnViewMyCoupons
expectation: btnClose
optional: true
其中,AccountSteps是steps模塊名稱,用于區(qū)分不同的steps模塊,方便在features模塊中進(jìn)行引用。
描述單個(gè)步驟時(shí),有三項(xiàng)是必不可少的:步驟名稱、控件ID(control_id)和控件操作方式(control_action)。當(dāng)控件操作方式為輸入(type)時(shí),則還需指定data屬性,即輸入內(nèi)容。
在檢查步驟執(zhí)行結(jié)果方面,可通過在expectation屬性中指定控件ID進(jìn)行實(shí)現(xiàn),前面在預(yù)期結(jié)果檢查一節(jié)中已經(jīng)詳細(xì)介紹了使用方法。該屬性可以置空或不進(jìn)行填寫,相當(dāng)于不對當(dāng)前步驟進(jìn)行檢測。
另外還有一個(gè)optional屬性,對步驟指定該屬性并設(shè)置為true時(shí),當(dāng)前步驟的執(zhí)行結(jié)果不影響整個(gè)測試用例。
features(功能點(diǎn)描述)
各個(gè)模塊的單一操作步驟定義完畢后,雖然可以直接將多個(gè)步驟進(jìn)行組合形成對測試場景的描述,即測試用例,但是操作起來會(huì)過于局限細(xì)節(jié);特別是當(dāng)測試用例較多時(shí),可維護(hù)性是一個(gè)很大的問題。
AppiumBooster的做法是,將App根據(jù)功能模塊進(jìn)行拆分,每一個(gè)模塊單獨(dú)創(chuàng)建一個(gè)YAML文件,并保存在features目錄下。然后,在每個(gè)模塊中以功能點(diǎn)為單位,通過對steps模塊中定義好的操作步驟進(jìn)行引用并組合,即可實(shí)現(xiàn)對功能點(diǎn)的描述。
以系統(tǒng)登錄功能為例,功能點(diǎn)的描述可采用如下形式。
---
AccountFeatures:
login with valid test account:
- AccountSteps | enter My Account page
- AccountSteps | enter Login page
- AccountSteps | input test EmailAddress
- AccountSteps | input test Password
- AccountSteps | login
- AccountSteps | close coupon popup window(optional)
login with valid production account:
- AccountSteps | enter My Account page
- AccountSteps | enter Login page
- AccountSteps | input production EmailAddress
- AccountSteps | input production Password
- AccountSteps | login
- AccountSteps | close coupon popup window(optional)
logout:
- AccountSteps | enter My Account page
- SettingsSteps | enter Settings page
- AccountSteps | logout
其中,AccountFeatures是features模塊名稱,用于區(qū)分不同的features模塊,方便在testcase中進(jìn)行引用。
在引用steps模塊的操作步驟時(shí),需要同時(shí)指定steps模塊名稱和操作步驟的名稱,并以|進(jìn)行分隔。
testcases(測試用例描述)
在功能點(diǎn)描述的基礎(chǔ)上,AppiumBooster就可以在第三個(gè)層面,簡單清晰地描述測試用例了。
具體做法很簡單,針對每個(gè)測試用例創(chuàng)建一個(gè)YAML文件,并保存在testcases目錄下。然后,通過對features模塊中定義好的功能點(diǎn)描述進(jìn)行引用并組合,即可實(shí)現(xiàn)對測試用例的描述。
同樣的,在引用features模塊的功能點(diǎn)時(shí),也需要同時(shí)指定features模塊名稱和功能點(diǎn)的名稱,并以|進(jìn)行分隔。
如下示例便是實(shí)現(xiàn)了在商城中購買商品的整個(gè)流程,包括切換國家、登錄、選擇商品、添加購物車、下單完成支付等功能點(diǎn)。
---
Buy Phantom 4:
- SettingsFeatures | initialize first startup
- SettingsFeatures | Change Country to China
- AccountFeatures | login with valid account
- AccountFeatures | Change Shipping Address to China
- StoreFeatures | add phantom 4 to cart
- StoreFeatures | finish order
- AccountFeatures | logout
另外,在某些測試場景中可能需要重復(fù)進(jìn)行某一個(gè)功能點(diǎn)的操作。雖然可以將需要重復(fù)的步驟多寫幾次,但會(huì)顯得比較累贅,特別是重復(fù)次數(shù)較多時(shí)更是麻煩。
AppiumBooster的做法是,在測試用例的步驟中可指定執(zhí)行次數(shù),并以|進(jìn)行分隔,如下例所示。
---
Send random text messages:
- SettingsFeatures | initialize first startup
- AccountFeatures | login with valid test account
- MessageFeatures | enter follower user message page
- MessageFeatures | send random text message | 100
測試用例引擎(CSV)
基本上,YAML測試用例引擎已經(jīng)可以很好地滿足組織和管理自動(dòng)化測試用例的需求。
但考慮到部分用戶會(huì)偏向于使用表格的形式,因?yàn)楸砀窨瓷先ジ庇^一些,AppiumBooster同時(shí)還支持CSV格式的測試用例引擎。
testcases(測試用例描述)
采用表格來編寫測試用例時(shí),只需要在任意表格工具,包括Microsoft Excel、iWork Numbers、WPS等,按照如下形式對測試用例進(jìn)行描述。

然后,將表格內(nèi)容另存為CSV格式的文件,并放置于testcases目錄中即可。
可以看出,CSV格式的測試用例和YAML格式的測試用例是等價(jià)的,兩者包含的信息內(nèi)容完全相同。
在具體實(shí)現(xiàn)上,AppiumBooster在執(zhí)行測試用例之前,也會(huì)將兩個(gè)測試用例引擎的測試用例描述轉(zhuǎn)換為相同的數(shù)據(jù)結(jié)構(gòu),然后再進(jìn)行統(tǒng)一的操作。
統(tǒng)一轉(zhuǎn)換后的數(shù)據(jù)結(jié)構(gòu)如下所示:
{
"testcase_name": "Login and Logout",
"features_suite": [
{
"feature_name": "login with valid account",
"feature_steps": [
{"control_id": "btnMenuMyAccount", "control_action": "click", "expectation": "tablecellMyAccountSystemSettings", "step_desc": "enter My Account page"},
{"control_id": "tablecellMyAccountLogin", "control_action": "click", "expectation": "btnForgetPassword", "step_desc": "enter Login page"},
{"control_id": "txtfieldEmailAddress", "control_action": "type", "data": "leo.lee@debugtalk.com", "expectation": "sectxtfieldPassword", "step_desc": "input EmailAddress"},
{"control_id": "sectxtfieldPassword", "control_action": "type", "data": 12345678, "expectation": "btnLogin", "step_desc": "input Password"},
{"control_id": "btnLogin", "control_action": "click", "expectation": "tablecellMyMessage", "step_desc": "login"},
{"control_id": "btnClose", "control_action": "click", "expectation": nil, "optional": true, "step_desc": "close coupon popup window(optional)"}
]
},
{
"feature_name": "logout",
"feature_steps": [
{"control_id": "btnMenuMyAccount", "control_action": "click", "expectation": "tablecellMyAccountSystemSettings", "step_desc": "enter My Account page"},
{"control_id": "tablecellMyAccountSystemSettings", "control_action": "click", "expectation": "txtCountryDistrict", "step_desc": "enter Settings page"},
{"control_id": "btnLogout", "control_action": "click", "expectation": "uiviewMyAccount", "step_desc": "logout"}
]
}
]
}
測試用例轉(zhuǎn)換器(yaml2csv)
既然CSV格式的測試用例和YAML格式的測試用例是等價(jià)的,那么兩者之間的轉(zhuǎn)換也就容易實(shí)現(xiàn)了。
當(dāng)前,AppiumBooster支持將YAML格式的測試用例轉(zhuǎn)換為CSV格式的測試用例,只需要執(zhí)行一條命令即可。
$ ruby start.rb -c "yaml2csv" -f ios/testcases/login_and_logout.yml
過程記錄及結(jié)果存儲(chǔ)
在自動(dòng)化測試執(zhí)行過程中,應(yīng)盡量對測試用例執(zhí)行過程進(jìn)行記錄,方便后續(xù)對問題根據(jù)定位和追溯。
過程記錄方式
當(dāng)前,AppiumBooster已實(shí)現(xiàn)的記錄形式有如下三種:
- logger模塊:可指定日志級(jí)別對測試過程進(jìn)行記錄
- 截圖功能:測試用例運(yùn)行過程中,在每個(gè)步驟執(zhí)行完成后進(jìn)行截圖
- DOM source:測試用例運(yùn)行過程中,在每個(gè)步驟執(zhí)行完成后保存當(dāng)前頁面的DOM內(nèi)容
測試結(jié)果存儲(chǔ)
由于Appium分為Server端和Client端,因此AppiumBooster在記錄日志的時(shí)候也將日志分為了三份:
-
appium_server.log: Appium Server端的日志,這部分日志是由Appium框架打印的 -
appium_booster.log: 包括測試環(huán)境初始化和測試用例執(zhí)行記錄,這部分日志是由AppiumBooster中采用logger模塊打印的 -
client_server.log: 同時(shí)記錄AppiumBooster和Appium框架的日志,相當(dāng)于appium_server.log和appium_booster.log的并集,優(yōu)點(diǎn)在于可以清晰地看到測試用例執(zhí)行過程中Client端和Server端的通訊交互過程
另外,當(dāng)測試用例執(zhí)行失敗時(shí),AppiumBooster會(huì)將執(zhí)行失敗的步驟截圖和日志提取出來,單獨(dú)保存到errors文件夾中,方便問題追溯。
具體地,每次執(zhí)行測試前,AppiumBooster會(huì)在指定的results目錄下創(chuàng)建一個(gè)以當(dāng)前時(shí)間(%Y-%m-%d_%H:%M:%S)命名的文件夾,存儲(chǔ)結(jié)構(gòu)如下所示。
2016-08-28_16:28:48
├── appium_server.log
├── appium_booster.log
├── client_server.log
├── errors
│ ├── 16_31_29_btnLogin.click.dom
│ ├── 16_31_29_btnLogin.click.png
│ ├── 16_32_03_btnMenuMyAccount.click.dom
│ └── 16_32_03_btnMenuMyAccount.click.png
├── screenshots
│ ├── 16_30_34_tablecellMyAccountLogin.click.png
│ ├── 16_30_41_txtfieldEmailAddress.type_leo.lee@debugtalk.com.png
│ ├── 16_30_48_sectxtfieldPassword.type_123456.png
│ ├── 16_31_29_btnLogin.click.png
│ └── 16_32_03_btnMenuMyAccount.click.png
└── xmls
├── 16_30_34_tablecellMyAccountLogin.click.dom
├── 16_30_41_txtfieldEmailAddress.type_leo.lee@debugtalk.com.dom
├── 16_30_48_sectxtfieldPassword.type_123456.dom
├── 16_31_29_btnLogin.click.dom
└── 16_32_03_btnMenuMyAccount.click.dom
對于每一個(gè)測試步驟的截圖和DOM,存儲(chǔ)文件命名格式為%H_%M_%S_ControlID.ControlAction。采用這種命名方式有兩個(gè)好處:
- 文件通過時(shí)間排序,對應(yīng)著測試用例執(zhí)行的步驟順序
- 可以在截圖或DOM中直觀地看到每一步操作指令對應(yīng)的執(zhí)行結(jié)果
環(huán)境初始化
Appium Server
在執(zhí)行自動(dòng)化測試時(shí),某些情況下可能會(huì)造成Appium Server出現(xiàn)異常情況(e.g. 500 error),并影響到下一次測試的執(zhí)行。
為了避免這類情況,AppiumBooster在每次執(zhí)行測試前,會(huì)強(qiáng)制性地對Appium Server進(jìn)行重啟。方式也比較簡單暴力,運(yùn)行測試之前先檢查系統(tǒng)是否有bin/appium的進(jìn)程在運(yùn)行,如果有,則先kill掉該進(jìn)程,然后再啟動(dòng)Appium Server。
需要說明的是,由于Appium Server的啟動(dòng)需要一定時(shí)間,為了防止運(yùn)行Appium Client時(shí)Appium Server還未初始化完畢,因此啟動(dòng)Appium Server后最好能等待一段時(shí)間(e.g. sleep 10s)。
iOS/Android模擬器
在模擬器中運(yùn)行一段時(shí)間后,也會(huì)存在緩存數(shù)據(jù)和文件,可能會(huì)對下一次測試造成影響。
為了避免這類情況,AppiumBooster在每次執(zhí)行測試前,會(huì)先刪除已存在的模擬器,然后再用指定的模擬器配置創(chuàng)建新的模擬器。
對于iOS模擬器,AppiumBooster通過調(diào)用xcrun simctl命令的方式來對模擬器進(jìn)行操作,基本原理如下所示。
# delete iOS simulator: xcrun simctl delete device_id
$ xcrun simctl delete F2F53866-50A5-4E0F-B164-5AC1702AD1BD
# create iOS simulator: xcrun simctl create device_type device_type_id runtime_id
$ xcrun simctl create 'iPhone 5' 'com.apple.CoreSimulator.SimDeviceType.iPhone-5' 'com.apple.CoreSimulator.SimRuntime.iOS-9-3'
其中,device_id/device_type_id/runtime_id這些屬性值可以通過執(zhí)行xcrun simctl list命令獲取得到。
$ xcrun simctl list
== Device Types ==
iPhone 5s (com.apple.CoreSimulator.SimDeviceType.iPhone-5s)
iPhone 6 (com.apple.CoreSimulator.SimDeviceType.iPhone-6)
== Runtimes ==
iOS 8.4 (8.4 - 12H141) (com.apple.CoreSimulator.SimRuntime.iOS-8-4)
iOS 9.3 (9.3 - 13E230) (com.apple.CoreSimulator.SimRuntime.iOS-9-3)
== Devices ==
-- iOS 8.4 --
iPhone 5s (E1BD9CC5-8E95-408F-849C-B0C6A44D669A) (Shutdown)
-- iOS 9.3 --
iPhone 5s (BAFEFBE1-3ADB-45C4-9C4E-E3791D260524) (Shutdown)
iPhone 6 (F23B3F85-7B65-4999-9F1C-80111783F5A5) (Shutdown)
== Device Pairs ==
增強(qiáng)特性
除了以上基礎(chǔ)特性,AppiumBooster還支持一些輔助特性,可以增強(qiáng)測試框架的使用體驗(yàn)。
Data參數(shù)化
在某些場景下,測試用例執(zhí)行時(shí)需要?jiǎng)討B(tài)獲取數(shù)值。例如,注冊賬號(hào)的測試用例中,每次執(zhí)行測試用例時(shí)需要保證用戶名為未注冊的,常見的做法就是在注冊用戶名中包含時(shí)間戳。
AppiumBooster的做法是,可以在測試步驟的data字段中,傳入Ruby表達(dá)式,格式為${ruby_expression}。在執(zhí)行測試用例時(shí),會(huì)先對ruby_expression進(jìn)行eval計(jì)算,然后用計(jì)算得到的值作為實(shí)際參數(shù)。
回到剛才的注冊賬號(hào)測試用例,填寫用戶名的步驟就可以按照如下形式指定參數(shù)。
input test EmailAddress:
control_id: txtfieldEmailAddress
control_action: type
data: ${Time.now.to_i}@debugtalk.com
expectation: sectxtfieldPassword
實(shí)際執(zhí)行測試用例時(shí),data就會(huì)參數(shù)化為1471318368@debugtalk.com的形式。
全局參數(shù)配置
對于某些配置參數(shù),例如系統(tǒng)的登錄賬號(hào)密碼等,雖然可以直接填寫到測試用例的steps中,但是終究不夠靈活。特別是當(dāng)存在多個(gè)測試用例引用同一個(gè)參數(shù)時(shí),涉及到參數(shù)改動(dòng)時(shí)就需要同時(shí)修改多個(gè)地方。
更好的做法是,將此類參數(shù)提取出來,在統(tǒng)一的地方進(jìn)行配置。在AppiumBooster中,可以在config.yml文件中配置全局參數(shù)。
---
TestEnvAccount:
UserName: test@debugtalk.com
Password: 123456
ProductionEnvAccount:
UserName: production@debugtalk.com
Password: 12345678
然后,在測試用例的steps就可以采用如下形式對全局參數(shù)進(jìn)行引用。
---
AccountSteps:
input test EmailAddress:
control_id: txtfieldEmailAddress
control_action: type
data: ${config.TestEnvAccount.UserName}
expectation: sectxtfieldPassword
input test Password:
control_id: sectxtfieldPassword
control_action: type
data: ${config.TestEnvAccount.Password}
expectation: btnLogin
optional選項(xiàng)
在執(zhí)行測試用例時(shí),有時(shí)候可能會(huì)存在這樣的場景:某個(gè)步驟作為非必要步驟,當(dāng)其執(zhí)行失敗時(shí),我們并不想將測試用例判定為不通過。
基于該場景,在測試用例設(shè)計(jì)表格中增加了optional參數(shù)。該參數(shù)值默認(rèn)不用填寫。但如果在某個(gè)步驟對應(yīng)的optional欄填寫了true值后,那么該步驟就會(huì)作為非必要步驟,其執(zhí)行結(jié)果不會(huì)影響整個(gè)用例的執(zhí)行結(jié)果。
例如,在電商類APP中,某些賬號(hào)有優(yōu)惠券,登錄系統(tǒng)后,會(huì)彈出優(yōu)惠券的提示框;而有的賬號(hào)沒有優(yōu)惠券,登錄后就不會(huì)有這樣的彈框。那么關(guān)閉優(yōu)惠券彈框的步驟就可以將其optional參數(shù)設(shè)置為true。
---
AccountSteps:
close coupon popup window(optional):
control_id: btnClose
control_action: click
expectation: !btnViewMyCoupons
optional: true
命令行工具
AppiumBooster通過在命令行中進(jìn)行調(diào)用。
$ ruby start.rb -h
Usage: start.rb [options]
-p, --app_path <value> Specify app path
-t, --app_type <value> Specify app type, ios or android
-f, --testcase_file <value> Specify testcase file(s)
-d, --output_folder <value> Specify output folder
-c, --convert_type <value> Specify testcase converter, yaml2csv or csv2yaml
--disable_output_color Disable output color
執(zhí)行測試用例
指定執(zhí)行測試用例時(shí)支持多種方式,常見的幾種使用方式示例如下:
$ cd ${AppiumBooster}
# 執(zhí)行指定的測試用例文件(絕對路徑)
$ ruby run.rb -p "ios/app/test.zip" -f "/Users/Leo/MyProjects/AppiumBooster/ios/testcases/login.yml"
# 執(zhí)行指定的測試用例文件(相對路徑)
$ ruby run.rb -p "ios/app/test.zip" -f "ios/testcases/login.yml"
# 執(zhí)行所有yaml格式的測試用例文件
$ ruby run.rb -p "ios/app/test.zip" -f "ios/testcases/*.yml"
# 執(zhí)行ios目錄下所有csv格式的測試用例文件
$ ruby run.rb -p "ios/app/test.zip" -t "ios" -f "*.csv"
測試用例轉(zhuǎn)換
將YAML格式的測試用例轉(zhuǎn)換為CSV格式的測試用例:
$ ruby start.rb -c "yaml2csv" -f ios/testcases/login_and_logout.yml
總結(jié)
什么才算是心目中理想的自動(dòng)化測試框架?我也沒有確切的答案。
為什么要登山?
因?yàn)樯皆谀抢铩?/p>
原文鏈接:http://debugtalk.com/post/build-ideal-app-automation-test-framework/
項(xiàng)目源碼:https://github.com/debugtalk/AppiumBooster