廢話
最近有朋友說React Native 自動(dòng)化測(cè)試這塊網(wǎng)上鮮有教程,正好我們的項(xiàng)目中有這樣的實(shí)踐,特地拿出來顯擺顯擺,嘿嘿,開個(gè)玩笑啊別介意,廢話不多說,開始講解
Detox
detox 是移動(dòng)應(yīng)用程序的灰盒端到端測(cè)試和自動(dòng)化框架。
移動(dòng)自動(dòng)化測(cè)試中最困難的部分是測(cè)試金字塔的頂端 - E2E。 E2E測(cè)試的核心問題是片狀的 - 測(cè)試通常不是確定性的。我們認(rèn)為解決片狀問題的唯一方法是從黑盒測(cè)試轉(zhuǎn)向灰盒測(cè)試。這就是Detox發(fā)揮作用的地方。
優(yōu)點(diǎn):
-?跨平臺(tái)
用JavaScript編寫跨平臺(tái)測(cè)試。目前支持iOS,Android
-?在真機(jī)上運(yùn)行
(iOS尚未支持):通過在設(shè)備/模擬器上測(cè)試您的應(yīng)用程序,就像真實(shí)用戶一樣
-?自動(dòng)同步
通過監(jiān)控應(yīng)用程序中的異步操作,可以在核心處停止
-?為CI而做
在像Travis這樣的CI平臺(tái)上執(zhí)行您的E2E測(cè)試,Jenkins不清楚支不支持,后期有經(jīng)驗(yàn)了會(huì)出這個(gè)教程,應(yīng)該是支持的。
-?測(cè)試獨(dú)立
使用您喜歡的Mocha,AVA或任何其他JavaScript測(cè)試運(yùn)行器
- 可調(diào)試
Modern async-await API允許異步測(cè)試中的斷點(diǎn) 按預(yù)期工作。
以上是官方對(duì)它的介紹,從目前來看,這個(gè)框架基本達(dá)到我們的預(yù)期,是可以嘗試一下的。
環(huán)境配置
ios自動(dòng)化測(cè)試要求:
- Mac with macOS (at least macOS El Capitan 10.11)
- Xcode 8.3+ with Xcode command line tools
通過在終端中鍵入gcc -v來驗(yàn)證是否已安裝Xcode命令行工具(如果未安裝則顯示彈出窗口)
安裝依賴:
1. Install the latest version of?Homebrew
Homebrew是macOS的包管理器,我們需要它來安裝其他命令行工具。
終端輸入:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.?Install?Node.js
Node是Detox將運(yùn)行的JavaScript運(yùn)行時(shí)。安裝節(jié)點(diǎn)8.3.0或更高版本
終端 輸入:?brew update && brew install node
3.?Install?applesimutils
用于Apple模擬器的utils集合,Detox使用它與模擬器進(jìn)行通信。
終端駛?cè)耄?br>brew tap wix/brew
brew install applesimutils
通過鍵入終端applesimutils來輸出工具幫助信息,驗(yàn)證它是否有效
4.?Install Detox command line tools (detox-cli)
該軟件包使命令行中的Detox更容易操作。 detox-cli應(yīng)該全局安裝,允許在npm腳本之外使用命令行工具。 detox-cli只是一個(gè)腳本,它將命令傳遞給detox包中提供的命令行工具(在node_modules / .bin / detox中)
npm install -g detox-cli
注意:官方說的是全局安裝,但實(shí)際使用過程中,本人實(shí)在RN項(xiàng)目的根目錄中使用的該命令跑成功就可以了
5.?Add Detox to your project
在RN項(xiàng)目根目錄的終端里輸入一下安裝命令
?npm install detox --save-dev
6. Install a test runner
您可以使用任何JavaScript測(cè)試運(yùn)行器。 Detox CLI支持開箱即用的Jest和Mocha
這里跳過Jest 建議使用?Mocha?同樣在項(xiàng)目根目錄執(zhí)行
npm install mocha --save-dev
7.?Add Detox config to package.json
"detox": {
? ? ? ?"configurations": {
? ? ? ? ? ? ? ? "ios.sim.debug": {
? ? ? ? ? ? ? ? ? ? ? ? "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
? ? ? ? ? ? ? ? ? ? ? ? ?"build": "xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
? ? ? ? ? ? ? ? ? ? ? ? ? "type": "ios.simulator", "name": "iPhone 7"
? ? ? ? ? ? ? ? }
? ? ? ? ?}
?}
如圖:放到 package.json 這里
如圖配置,需要將下圖中三個(gè)地方改成ios項(xiàng)目的名字。
ios/build/Build/Products/Debug-iphonesimulator/example.app
xcodebuild -project ios/example.xcodeproj -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build
以上步驟順利進(jìn)行的話,接下來可以寫測(cè)試代碼了。
Create your first test
項(xiàng)目根目錄輸入一下命令
detox init -r mocha
這個(gè)命令將在項(xiàng)目的根目錄創(chuàng)建一個(gè)e2e目錄,如圖3
Build your app and run Detox tests
detox build
實(shí)際執(zhí)行的是這段命令如圖4
最終結(jié)果如圖5,看到BUILD SUCCEEDED 說明打包成功,馬上就可以真正測(cè)試了
detox test
輸入以上命令后,模擬器會(huì)啟動(dòng),然后自動(dòng)跑firstTest.spec.js文件中的測(cè)試用例,同時(shí)終端有如下輸輸出:
同時(shí)如圖7所指,測(cè)試輸出是跟代碼中 it 函數(shù)第一個(gè)參數(shù)是一致的,有多少個(gè)it就會(huì)有多少個(gè)測(cè)試輸出。
測(cè)試用例已經(jīng)跑了起來,下面簡(jiǎn)單說下語法。
1. 如何找到組件 如圖8
2. 找到組件能干嘛,如圖9
簡(jiǎn)單例子:
await element(by.id('tappable')).tap();??
await element(by.id('tappable')).longPress();await element(by.id('tappable')).multiTap(3);
await element(by.id('tappable')).tapAtPoint({x:5, y:10});
await element(by.id('textField')).typeText('passcode');
await element(by.id('textField')).replaceText('passcode again');
await element(by.id('textField')).clearText();
await element(by.id('scrollView')).scroll(100, 'down');
await element(by.id('scrollView')).scroll(100, 'up');
await element(by.id('scrollView')).scrollTo('bottom');
await element(by.id('scrollView')).scrollTo('top');
await element(by.id('scrollView')).swipe('down');
await element(by.id('scrollView')).swipe('down', 'fast');
await element(by.id('scrollView')).swipe('down', 'fast', 0.5);
await expect(element(by.type('UIPickerView'))).toBeVisible();
await element(by.type('UIPickerView')).setColumnToValue(1,"6");
await element(by.type('UIPickerView')).setColumnToValue(2,"34");
3. 如何驗(yàn)證結(jié)果 如圖10
簡(jiǎn)單例子:
await expect(element(by.id('UniqueId204'))).toBeVisible();
await expect(element(by.id('UniqueId205'))).toBeNotVisible();
await expect(element(by.id('UniqueId205'))).toExist();
await expect(element(by.id('RandomJunk959'))).toNotExist();
await expect(element(by.id('UniqueId204'))).toHaveText('I contain some text');
await expect(element(by.id('UniqueId204'))).toHaveLabel('Done');
await expect(element(by.text('I contain some text'))).toHaveId('UniqueId204');
await expect(element(by.id('UniqueId533'))).toHaveValue('0');
到此就簡(jiǎn)單介紹到這里,更詳細(xì)的請(qǐng)看官方文檔,如有疑問,請(qǐng)留言給我。
總結(jié)
在實(shí)踐了這段時(shí)間以來,碰到了不少問題,這里介紹的是IOS的測(cè)試,相對(duì)來說還簡(jiǎn)單一些,Android的配置就有些復(fù)雜,下次專門介紹下Android的環(huán)境配置。