前言:node
在開始測試React Native App(上篇)中編寫了redux-upload-queue針對Reducer
和Action Creator
的單元測試,測試代碼能夠在這裏查閱。這篇文章基於開始測試React Native App(上篇)繼續完成集成測試以及E2E測試。react
在Action Creator
的測試中,引入了redux-mock-store庫,按官方的話來講,這個庫只是用來測試Redux async action creators
和 middleware
,它不是用來測試reducer
相關的邏輯,換句話來講它不會更新Redux Store
,因此若是你想把reducer
和action
結合在一塊兒測試建議使用redux-actions-assertions。 筆者在剛學測試時沒有認真看文檔這段話,致使寫出了以下代碼:android
const rootReducer = combineReducers({
upload: UploadReducer
})
let initState = {}
export const store = mockStore((actions) => {
let currentState = initState
actions.forEach(action => {
currentState = rootReducer(currentState, action)
});
return currentState
})
複製代碼
變相的使用redux-mock-store
實現告終合reducer
和action
的測試,能更改Redux Store
,在性能上確定是不優的,每次獲取State
都要遍歷全部派發的action
和reducer
。因此仍是建議使用redux-actions-assertions,在該篇文章中採用的是不優的解決方案。ios
在解決了以上測試的技術點後,就能夠開始寫組合reducer
和action
在一塊兒的集成測試了:git
import * as UploadActions from '../UploadActions'
import config, {store} from './UploadConfig'
afterEach(() => {
store.clearActions()
fetch.resetMocks()
})
...
//使用reducer和action模擬多張圖片部分上傳失敗,從新上傳成功的集成測試
it('upload mult fail and reupload action test', () => {
fetch.mockResponses(
[
JSON.stringify({ error: null, id: '123456' })
],
[
JSON.stringify({ error: null, id: '123456' })
],
[
JSON.stringify({ error: new Error('fail') })
],
[
JSON.stringify({ error: null, id: '123456' })
],
)
store.dispatch(UploadActions.registerUpload({upload: 'uploadKey'}))
store.dispatch(UploadActions.pushUploadItem({upload: 'uploadKey', name: 'fileOne', filePath: 'filePathOne'}))
store.dispatch(UploadActions.pushUploadItem({upload: 'uploadKey', name: 'fileTwo', filePath: 'filePathTwo'}))
store.dispatch(UploadActions.pushUploadItem({upload: 'uploadKey', name: 'fileThree', filePath: 'filePathThree'}))
return store.dispatch(UploadActions.upload('uploadKey', config))
.then(() => {
return store.dispatch(UploadActions.upload('uploadKey', config))
})
.then(() => {
expect(store.getActions()).toMatchSnapshot()
expect(store.getState()).toMatchSnapshot()
})
})
複製代碼
上面的測試代碼首先派發出注冊上傳隊列的動做(UploadActions.registerUpload
),而後依次派發出在註冊的上傳隊列中添加上傳項的動做(UploadActions.pushUploadItem
),再派發異步上傳動做(UploadActions.upload
)開始上傳,由於使用fetch.mockResponses
mock了屢次網絡請求的返回結果來模擬上傳的結果,因此模擬出了第一次上傳時第三個文件(fileThree
)上傳失敗,失敗後再次派發上傳動做UploadActions.upload
返回成功,判斷整個流程走完後store.getActions()
和store.getState()
是否符合預期。github
這個測試用例涉及到了派發action
,使用reducer
處理action
,以及更改Store
的狀態,因此它是一個集成測試,也是單元測試的組合測試。web
示例代碼json
其實集成測試更加的符合初學者對測試的直觀想法,好比當我說我要測試上傳組件的redux
邏輯是否有問題時,天然而然就會想到要派發一系列action
,再看reducer
是否能正常的處理這些action
,Store
結果是否符合預期。在redux-upload-queue這個組件中,不但實現了Redux
處理上傳隊列的整套邏輯,還使用HOC
的方式,讓任意組件能夠快速的集成上傳隊列功能,例如:redux
...
import {redux_upload} from 'redux-upload-queue'
class Foo extends Component {
componentDidMount() {
this.props.pushUploadItem('fileOnePath', 'fileOne')
this.props.startUpload()
}
render() {return <View/>}
}
...
export default redux_upload({ upload: 'uploadKey', config: config })(Foo)
複製代碼
上面的示例中對組件Foo
快速的集成了上傳隊列的功能,那麼redux_upload
是否能正確的讓被包裹的組件有上傳功能呢?咱們能夠寫如下集成測試用例來證實:後端
import config, {store, Foo} from './UploadConfig'
import uploadComponent from '../UploadComponent'
...
test('uploadComponent new', () => {
fetch.mockResponseOnce(JSON.stringify({ error: null, id: '123456' }))
const Component = uploadComponent({ upload: 'uploadKey', config: config })(Foo)
const componentWrap = shallow(
<Component store={store}/>
)
const fooWrap = componentWrap.shallow()
const fooProps = fooWrap.props()
fooProps.pushUploadItem('fileOnePath', 'fileOne')
return fooProps.startUpload().then(() => {
expect(store.getActions()).toMatchSnapshot()
})
})
複製代碼
經過shallow
來模擬組件裝載,而後使用ShallowWrapper
的props()
來獲取被裝載的Foo
組件的全部屬性,調用屬性的pushUploadItem
和startUpload
方法來觸發上傳操做,預期會觸發與以前測試上傳隊列Redux
邏輯差很少的Actions
,都是先註冊隊列,添加上傳項而後開始上傳等,只是註冊的惟一標識符、添加上傳項的對象以及數量、上傳的結果不一樣。
注意<Component store={store}/>
這一行代碼,store={store}
是用來給Redux connect
提供Store
的,至關於使用react-redux
中的Provider
:<Provider store={store}><Component/></Provider>
。 示例代碼
E2E測試就是編譯安裝App到模擬器或真機,在App中模擬用戶的行爲進行測試,通常用來測試App的主要流程(不是所有流程),由於E2E測試受周邊環境影響較大(網絡等因素),所以測試結果不徹底可靠。
Detox
Detox
是一個移動App自動化E2E灰盒測試框架,是第一個支持React Native
項目的E2E
測試框架,能夠結合Jest
使用,安裝與配置也是很快的。
在Detox
的設計原則中咱們能夠了解到它是一個灰盒測試框架,這種測試框架是從App的內部操控測試(經過testId
等方式查詢到UI元素,而後執行Tap
等Actions
來觸發各類手勢輸入等(模擬用戶),最後經過isVisible
等Matcher
來判斷指望值),保證App的核心流程正確。它依賴Native
端的灰盒測試框架:EarlGrey for iOS
和Espresso for Android
,使用基於JSON的反射機制,讓JavaScript直接調用Native
測試框架的方法,在JavaScript端提供了一系列易於使用API,徹底的抽象了Native
引擎下發生的複雜調用邏輯,所以它寫出來的測試可讀性高。 測試腳本與被測試的App的通訊原理:
依賴websockets
讓運行在nodejs
的測試腳本和運行在設備上的App通訊,實現了真實的雙工通訊,相比與其餘相似REST的協議要更快更靈活,運行在nodejs
端的測試讓它能在多個平臺上運行。
測試與App同步
這種E2E測試腳本執行App流程,讓人最困惑的的就是它是如何將測試與App同步,App複雜的操做(例如訪問服務器數據或執行動畫)常常須要大量的時間去完成,在這些操做完成以前咱們不能繼續執行測試代碼,不然會使測試失敗(例如正在測試登陸流程,在沒登陸成功時你就斷言進入首頁,測試就會失敗),那咱們如何將測試與App同步?
常常會想到的解決方案是手動執行sleep()
來同步,可是在不一樣的設備上,不一樣的網絡狀態下,執行相同的操做所花費的時間不一樣,手動sleep()
要不會形成沒必要要的時間浪費,讓測試變慢,要不時間不給充足會讓測試直接失敗。
Detox
的同步方式是:自動同步,這種同步方式就像魔術同樣,你在寫了一行測試代碼後寫下一行測試代碼無需關心中間的時間間隔問題(數據是否是尚未獲取到,轉場動畫是否還沒執行完等),Detox
會等待App穩定以後纔會去執行下一行代碼。例若有一個已經發出的網絡請求,那麼直到網絡請求完成測試纔會執行下一行代碼。
這種自動同步要百分之百的正確是很是困難的,常常會有一些異常狀況,Detox
正在對這些異常狀況進行優化,所以大部分狀況下都須要考慮同步問題。那若是遇到了同步問題應該怎麼辦呢?這裏給出了具體的解決方案,包括:
waitFor
作手動同步。*.ios.js
、*.android.js
同樣,能夠經過*.e2e.js
來加載在E2E環境測試時運行的代碼。注意: 一、同步狀態難以解救時要去看下一本身的代碼是否是使用
setTimeout
等不當操做形成了濫用資源,內存泄漏。 二、react-native-repackager在0.55.*以後的版本由於這個PR而再也不須要,但依然是經過定義E2E的flavor
來使用特定的*.e2e.js
自定義擴展名。
Mock
以前提到過,E2E測試受環境因素影響大,例如網絡狀態,模擬器中沒有圖片庫,沒有聯繫人等,想象一下若是咱們可以在運行E2E測試時達到如下需求:
在對真實項目E2E時,諸如以上的場景還有許多,所以可使用build flavouring
來自定義file extensions
,而後編寫Mock。這樣能夠大量減小受E2E運行結果受環境因素的影響,具體能夠看react-native-repackager和 Better support for custom file extensions (and build flavours)。
Artifacts
最後一個我特別喜歡的功能點,那就是Artifacts了,它能夠在測試過程當中以多種方式記錄下測試過程,例如錄像、截圖、log等。你們有興趣能夠看文檔,簡單實用。
總結選擇Detox進行E2E測試的緣由:
waitFor
。js
端定義的UI,能夠查找到native
端定義的UI。還有更多好用的API能夠在文檔中查閱。
可運行官方示例體驗:github.com/wix/detox/t…
之全部寫【完(初)】,是由於在這裏測試的初級學習就結束了,其實在學習測試的過程當中Mock是一個很重要的概念,幾乎無處不在Mock,想必你們在文章中也看到了我用的Mock庫:
Action creators
和Middleware
的庫:redux-mock-store。這些Mock不限於Jest中的Mock,還有在編寫開發代碼中的Mock,除了使用這些Mock庫,在實際項目中寫測試時也須要本身寫大量的對第三方庫或者對本身寫的模塊的Mock,以及React Native雖然自帶Mock可是還有一些模塊(Platform等)沒有被Mock到,也要本身Mock。除了模塊的Mock還有Function的Mock,數據的Mock,Global的Mock等等,具體參考Testing React Native Apps。
Test Runner:
Test Utility:
歡迎關注個人簡書主頁:www.jianshu.com/u/b92ab7b3a… 文章同步更新^_^