測試 React Native 應用程式
在 Facebook,我們使用 Jest 來測試 React Native 應用程式。
透過閱讀以下系列文章,深入了解測試一個可運作的 React Native 應用程式範例:第 1 部分:Jest – Snapshot 應運而生 和 第 2 部分:Jest – Redux Snapshots,用於您的動作和簡約器。
設定
從 react-native 版本 0.38 開始,執行 react-native init
時會預設包含 Jest 設定。以下設定應會自動新增至您的 package.json 檔案
{
"scripts": {
"test": "jest"
},
"jest": {
"preset": "react-native"
}
}
執行 yarn test
以使用 Jest 執行測試。
如果您正在升級您的 react-native 應用程式,且之前使用過 jest-react-native
預設值,請從您的 package.json
檔案中移除相依性,並將預設值變更為 react-native
。
快照測試
讓我們為一個小型 Intro 元件建立一個快照測試,其中包含一些檢視和文字元件,以及一些樣式
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
class Intro extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>
This is a React Native snapshot test.
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#F5FCFF',
flex: 1,
justifyContent: 'center',
},
instructions: {
color: '#333333',
marginBottom: 5,
textAlign: 'center',
},
welcome: {
fontSize: 20,
margin: 10,
textAlign: 'center',
},
});
export default Intro;
現在,讓我們使用 React 的測試渲染器和 Jest 的快照功能與元件互動,並擷取已渲染的輸出,並建立一個快照檔案
import React from 'react';
import renderer from 'react-test-renderer';
import Intro from '../Intro';
test('renders correctly', () => {
const tree = renderer.create(<Intro />).toJSON();
expect(tree).toMatchSnapshot();
});
當您執行 yarn test
或 jest
時,將會產生類似這樣的輸出檔案
exports[`Intro renders correctly 1`] = `
<View
style={
Object {
"alignItems": "center",
"backgroundColor": "#F5FCFF",
"flex": 1,
"justifyContent": "center",
}
}>
<Text
style={
Object {
"fontSize": 20,
"margin": 10,
"textAlign": "center",
}
}>
Welcome to React Native!
</Text>
<Text
style={
Object {
"color": "#333333",
"marginBottom": 5,
"textAlign": "center",
}
}>
This is a React Native snapshot test.
</Text>
</View>
`;
下次執行測試時,已渲染的輸出將與先前建立的快照進行比較。快照應與程式碼變更一起提交。當快照測試失敗時,您需要檢查它是有意還是無意的變更。如果變更符合預期,您可以使用 jest -u
呼叫 Jest 來覆寫現有的快照。
此範例的程式碼可在 examples/react-native 中取得。
預設設定
預設設定會設定環境,並基於我們在 Facebook 中發現有用的內容,非常具有主觀性。所有設定選項都可以覆寫,就像在不使用預設設定時可以自訂一樣。
環境
react-native
附帶一個 Jest 預設設定,因此 package.json
的 jest.preset
欄位應指向 react-native
。預設設定是一個節點環境,模擬 React Native 應用程式的環境。由於它不會載入任何 DOM 或瀏覽器 API,因此大幅縮短了 Jest 的啟動時間。
transformIgnorePatterns 自訂
transformIgnorePatterns
選項可用於指定哪些檔案應由 Babel 轉換。不幸的是,許多 react-native
npm 模組在發佈前並未預先編譯其原始碼。
預設情況下,jest-react-native
預設值僅處理專案本身的原始檔和 react-native
。如果您有必須轉換的 npm 依賴項,您可以透過將 react-native
以外的模組分組並用 |
算子分隔,自訂此組態選項
{
"transformIgnorePatterns": [
"node_modules/(?!(react-native|my-project|react-native-button)/)"
]
}
您可以使用 類似此工具 來測試哪些路徑會相符(因此會從轉換中排除)。
如果路徑與提供的 任何 模式相符,transformIgnorePatterns
會將檔案從轉換中排除。因此,如果您不小心,拆分為多個模式可能會產生意外的結果。在以下範例中,foo
和 bar
的排除(也稱為負向先行斷言)會互相抵消
{
"transformIgnorePatterns": ["node_modules/(?!foo/)", "node_modules/(?!bar/)"] // not what you want
}
setupFiles
如果您想為每個測試檔案提供其他組態,可以使用 setupFiles
組態選項 來指定設定指令碼。
moduleNameMapper
moduleNameMapper
可以用來將模組路徑對應到不同的模組。預設情況下,預設值會將所有影像對應到影像 stub 模組,但如果找不到模組,此組態選項可以提供協助
{
"moduleNameMapper": {
"my-module.js": "<rootDir>/path/to/my-module.js"
}
}
提示
使用 jest.mock 模擬原生模組
內建於 react-native
的 Jest 預設值附帶一些預設模擬,這些模擬會套用在 react-native 儲存庫上。不過,有些 react-native 元件或第三方元件仰賴原生程式碼才能呈現。在這種情況下,Jest 的手動模擬系統可以協助模擬底層實作。
例如,如果您的程式碼仰賴名為 react-native-video
的第三方原生影片元件,您可能想使用類似以下的手動模擬來將其 stub 化
jest.mock('react-native-video', () => 'Video');
這會將元件呈現為 <Video {...props} />
,並在快照輸出中包含其所有 props。另請參閱 Enzyme 和 React 16 周圍的注意事項。
有時您需要提供更複雜的手動模擬。例如,如果您想將原生元件的 prop 類型或靜態欄位轉送至模擬,您可以透過 jest-react-native 的這個輔助程式,從模擬傳回不同的 React 元件
jest.mock('path/to/MyNativeComponent', () => {
const mockComponent = require('react-native/jest/mockComponent');
return mockComponent('path/to/MyNativeComponent');
});
或者,如果您想建立自己的手動模擬,您可以執行類似以下的動作
jest.mock('Text', () => {
const RealComponent = jest.requireActual('Text');
const React = require('react');
class Text extends React.Component {
render() {
return React.createElement('Text', this.props, this.props.children);
}
}
Text.propTypes = RealComponent.propTypes;
return Text;
});
在其他情況下,您可能想模擬不是 React 元件的原生模組。可以套用相同的技術。我們建議檢查原生模組的原始程式碼,並在實際裝置上執行 react native 應用程式時記錄模組,然後根據實際模組建構手動模擬。
如果您最後重複模擬相同的模組,建議在個別檔案中定義這些模擬,並將其新增至 setupFiles
清單中。