使用React Native Testing庫進行組件測試(案例詳解)

2021-12-26 React

原文:https://around25.com/blog/component-testing-using-react-native-testing-library/

譯者:明月

在本篇文章中,我們將探討 React Native 應用程式開發生態系統中的單元測試基礎知識。首先,讓我們了解一下什麼是單元測試以及為什麼在任何軟體開發生命周期中都需要用到它。在單元測試中,項目中的每個組件都作為一個單元進行單獨測試。這樣就可以測試獨立的組件,直到它們滿足設計和功能規範要求。

主要思想是弄清楚該軟體的每個組件是否按照預期工作。僅當軟體的每個單元正常工作時,環境才能有效地工作並按預期運行。

作為開發人員,您可以進行單元測試,也可以由獨立的測試人員執行。

測試初學者的注意事項:單元測試可以是手動的也可以是自動的。整個過程涉及創建測試用例,對這些用例進行審查,重新處理然後執行。

簡而言之,它是關於採用測試驅動的開發方法。測試驅動的開發涉及在將組件的每個模塊引入主系統之前對其進行開發和測試,這是構建系統的一種更為精簡的方法。

單元測試作為功能實現。通過引用各種輸入值來檢查功能的輸出。這使調試過程變得更加容易。

整個軟體開發過程變得敏捷:引入任何新的修改後,就可以單獨測試組件並將其集成到系統中,從而節省大量時間和成本。

由於可以在早期階段檢測和管理漏洞,因此減少了最後獲得煩人bug的機會。整體重構和更新變得更加方便。

由於您已經進行了單元測試,可以為每個模塊及其功能提供深入的概述,因此文檔將變得不再那麼繁瑣。

整個代碼成為模塊化的。這將是代碼變得可靠和可重用。

它有助於從統計角度衡量每個組件和整個系統的性能,同時還能確定組件在系統中覆蓋的區域。

您避免交付容易出錯的產品。另外,您可以在降低複雜性的同時提高代碼質量。

總體而言,單元測試是交付成功產品的最安全方法之一。

React Native測試庫 提供了簡單而完整的 React Native測試實現程序。

這是用於測試React Native組件的輕量級解決方案,它在react-test-renderer之上促進了實用方法。這將鼓勵更好的測試實踐。該庫與Jest並駕齊驅,但也可以與其他測試運行者合作。

為為了在React Native 項目中進行測試,我們首先需要一個入門項目,您可以繼續從snack項目中下載並啟動項目。

下載後,我們需要通過執行以下命令在仿真器或連接的設備上運行項目:

在應用程式中,我們有一個輸入欄位,一個用於添加項目的按鈕和一個列表。該列表包含一個刪除按鈕,用於刪除列表項。主頁分為三個部分:

主主屏幕(Home.js)

列表組件(ItemsList.js)

添加項目組件(ItemAdder.js)

要執行單元測試,我們需要將React Native測試庫安裝到我們的項目中。為此,我們需要在項目終端中運行以下命令:

npm install --save-dev @testing-library/react-native

該庫有一個react-test-renderer的peerDependencies列表。

對於測試人員,我們將在這裡使用 jest。因此,我們需要安裝jest-native庫作為附加的jest匹配器。為此,我們需要在項目終端中運行以下命令:

npm install --save-dev @testing-library/jest-native

現在,我們需要配置我們的jest設置文件,即package.json文件中的模式。為此,我們在package.json文件中存在的jest對象中添加以下配置行:

{  "jest": {    "preset": "react-native",    "setupFilesAfterEnv": ["@testing-library/jest-native/extend-expect"],    "transformIgnorePatterns": ["node_modules/(?!(jest-)?react-native|@?react-navigation)"],    "setupFiles": ["./node_modules/react-native-gesture-handler/jestSetup.js"]  }}

我們已完成配置,但未執行測試。

因此,我們在一個單獨的文件夾中創建一個新的測試文件,我們將在項目的./screens目錄中調用./test。在其中,我們創建一個名為Home.test.js的文件,該文件將包含與主屏幕有關的所有測試,並在運行測試命令後執行。

現在是時候將所需的庫導入Home.test.js文件中以進行測試了:

import React from 'react';import {render, fireEvent} from '@testing-library/react-native';import Home from '../Home';

為了測試基本的主屏幕模板,我們將主屏幕模板代碼渲染到終端中。

如果一切正確呈現,那就太好了!沒有問題。現在使用render()方法並將Home組件傳遞給它。

渲染方法將為我們提供測試主屏幕內部組件所需的方法。

同樣,我們在這裡使用debug方法來呈現主屏幕模板:

test('rendering Home component', async () => {    const {debug} = render(<Home/>);      debug();});

此時,我們可以使用兩個參數來實現測試功能,第一個參數是測試的名稱,第二個參數是在執行測試時觸發的回調函數。在package.json文件中,我們有一個腳本來運行測試:
"scripts": {        "android": "react-native run-android",        "ios": "react-native run-ios",        "start": "react-native start",        "test": "jest",        "lint": "eslint ."}

每次我們要執行測試時,都需要在項目終端中運行以下命令:

因此,我們將獲得主屏幕模板的完整模板渲染:

如果發生任何錯誤,則模板JSX元素的集成可能存在問題,該問題將在錯誤消息本身中指示。

主屏幕中的輸入欄位和按鈕組件是從ItemAdder組件導入的。

要測試TextInput和Button,我們需要為其分配testID屬性。使用這些testID道具,我們將能夠在測試配置中掌握這些元素。

<TextInput  value={input}  onChangeText={setInput}  placeholder="Add Item..."  style={styles.input}  testID={`${testID}-input`}/><Button  color="#000"  testID = "input-button"  title="+ ADD"  style = {styles.button}  onPress={() => {    addItem(input);    setInput('');  }}/>

現在,我們可以使用Home.test.js文件中的getByTestId方法訪問這些輸入和按鈕。然後我們通過提及它們的testID來初始化輸入欄位和按鈕:

test('testing input and button', async () => {    const {getByTestId, getByText} = render(         <Home />,    );  
const input = getByTestId('adder-input'); const button = getByTestId('input-button');
});

接下來,我們使用從測試庫導入的fireEvent對象實例,應用輸入並觸發按鈕單擊。我們可以在輸入中輸入文本值,並以此觸發按鈕的按下:

fireEvent.changeText(input, 'element');fireEvent.press(button);

在這裡,我們使用fireEvent類中的changeText方法將輸入提供給我們應用程式中的TextInput元素。我們提供的輸入值為'element'。按下功能將觸發我們應用中的「添加」按鈕,這將使輸入顯示在列表中。

問題是:如何觸發觸發事件後,輸入值「 element」是否已出現在列表中?

我們可以檢查渲染中是否存在文本值「 element」。

為此,我們可以利用render()提供的getByText方法。如果「元素」在渲染器中可用,則將其分配給元素常量。該代碼在下面的代碼片段中提供:

const element = getByText('element');

現在,我們需要檢查元素是否存在於渲染器中。在其他情況下,我們期望element值出現在render中。

這使我們可以使用Expect函數中的tobeDefined方法,該方法將元素作為參數。如果存在該值,則不會發生錯誤。否則,將發生錯誤。

expect(element).toBeDefined();

檢查以下完整的測試功能:

test('testing input and button', async () => {    const {getByText, getByTestId} = render(        <Home />,    );  
const input = getByTestId('adder-input'); const button = getByTestId('input-button'); fireEvent.changeText(input, 'element'); f ireEvent.press(button); const element = getByText('element'); expect(element).toBeDefined();});

在這裡,我們希望在添加輸入時定義元素並獲得此測試結果:

我們可以看到測試已經通過。

這就是為什麼我們現在也可以檢查多個輸入的原因。為此,我們分配了一個不同的輸入值'element1',並像之前的測試一樣進行了所有操作。函數是這樣的:

test('testing input and button', async () => {    
const {getByText, getByTestId} = render( <Home />, );
const input = getByTestId('adder-input'); const button = getByTestId('input-button'); fireEvent.changeText(input, 'element'); fireEvent.press(button); const element = getByText('element'); expect(element).toBeDefined();
fireEvent.changeText(input, 'element1'); fireEvent.press(button); const element1 = getByText('element1'); expect(element1).toBeDefined();});

如果運行測試命令,則會得到以下結果:

在應用程式演示中,您會注意到,當我們將項目添加到列表中時,我們還會獲得一個刪除按鈕。

當我們按下它時,該項目消失。要測試按鈕,我們需要將testID屬性分配給ItemList.js文件中的delete Button組件:

<Button    title="Delete"    onPress={() => deleteItem(value)}    color="#f12"    testID="delete-list-item"/>

現在在Home.test.js中,我們需要創建一個稱為「 testing delete」的新測試函數。

要測試刪除按鈕,首先我們必須在列表中有一個項目。

因此,我們將使用與以前相同的編碼實現來輸入項目,並檢查其渲染。然後,我們使用getAllByTestID方法,該方法將每個元素以及在其中定義的特定testID定義為數組。

現在,將數組分配給deleteButton常量:我們像以前一樣使用fireEvent類中的press方法觸發按鈕。但是,由於我們僅刪除列表的第一項,因此我們還需要分配數組標識符。這將導致列表中的第一項被刪除。

因此,我們使用queryByText檢查該第一項在渲染中是否可用。然後,通過應用toBeNull從方法期望的功能,我們可以檢查數組的第一個項目是否可用或者不渲染。在這裡獲取功能:

test('testing delete', async () => {    
const {getByText, getByTestId, getAllByTestId, queryByText} = render( <Home />, );
const input = getByTestId('adder-input'); const button = getByTestId('input-button'); fireEvent.changeText(input, 'element'); fireEvent.press(button); const element = getByText('element'); expect(element).toBeDefined();
const deleteButton = getAllByTestId('delete-list-item'); fireEvent.press(deleteButton[0]); expect(queryByText('element')).toBeNull(); });

我們在這裡所做的是,我們使用tobeNull方法將'element'值添加到列表中,然後將其刪除並檢查是否刪除了'element' 。

如果答案是正確的,則該元素將被刪除,並且刪除功能將起作用。測試也應該成功。現在,如果運行測試,我們將得到以下結果:

如我們所見,我們對刪除按鈕的測試也成功。

現在,對於下一個測試,我們在輸入值並單擊「添加」按鈕後檢查列表項是否可用。

test('testing list items', async () => {    
const {getByText, getByTestId} = render( <Home />, );
const input = getByTestId('adder-input'); const button = getByTestId('input-button');
fireEvent.changeText(input, 'element'); fireEvent.press(button); const element = getByText('element'); expect(element).toBeDefined();
fireEvent.changeText(input, 'element1'); fireEvent.press(button); const element1 = getByText('element1'); expect(element1).toBeDefined();
const listElements = getByTestId("list"); expect(listElements).toContainElement(element);});

所有步驟,不同的類似,我們使用toContainElement從期望函數來檢查我們在列表中輸入特定的產品存在。因此,我們應該得到以下結果:

通過準備不同的測試功能並分配測試ID來渲染元素,我們可以測試其他組件。

哇,很長的一段路程。讓我們快速回顧一下我們學到的東西:

最重要的一點是:通過基於組件渲染編寫這些類型的測試,我們可以驗證React Native應用程式的各個組件。如果發生任何錯誤,這將有助於優化應用程式。

測試庫提供了其他API和方法,您可以自由探索。面臨的挑戰是為各個組件設計自己的測試。您甚至可以先創建一個組件,然後按上述步驟對其進行測試,然後再將其集成到核心應用中。這稱為測試驅動開發。我們僅用幾行代碼即可執行測試的簡單性令人驚嘆。

最後希望您能夠使用 React Native Testing 庫在React Native中掌握基於組件的基本測試方法。

以上對單元測試的原理進行了詳細的闡述,並通過 React Native Testing 庫結合具體的案例進行了詳細的代碼輸出 ,如果您認為對您有幫助,請記得 點讚留言分享收藏 哦~~

相關焦點

  • 【譯】使用Enzyme和React Testing Library測試React Hooks
    原文:https://css-tricks.com/testing-react-hooks-with-enzyme-and-react-testing-library/當你開始在應用中使用React Hooks時,你需要確保編寫的代碼是可靠的。確保代碼沒有bug的一種方法就是編寫測試用例。
  • 超強通用的React Native Tab控制器使用詳解-進階篇
    投稿人:hiphonezhu 地址:http://www.jianshu.com/p/b0cfe7f11ee7本文所講知識點在上一篇文章當中,我們學習了react-native-scrollable-tab-view的基本使用方式,包括基本Props的使用介紹等。
  • 可能是最詳細的React組件庫搭建總結
    react-dom @types/react @types/react-dom --dev # 開發時依賴,宿主環境一定存在yarn add prop-types            # 運行時依賴,宿主環境可能不存在 安裝本組件庫時一起安裝此處依舊安裝了prop-types這個庫,因為無法保證宿主環境也使用typescript,從而能夠進行靜態檢查,故使用
  • 推薦幾個 React Native UI 庫
    所以今天推薦幾個 RN 開發者必備的 UI 庫。React Native Elements如果你是一個獨立開發者的話,那麼這個庫可以幫你節省掉不少設計和實現一些炫酷的交互 UI 的時間了。它不但包含多種多樣的組件,而且有開發者在不斷的維護,並且圍繞這個庫形成了自己的開發者社區。
  • ReactNative學習資源大匯集
    由於已經有較好的組件庫網站,這裡就不做總結。可以直接查看如下網站,過後可能精選一部分優質組件出來 :PReact-native組件庫(比較全的組件庫) https://js.coach/React Native Modules http://reactnativemodules.com/最佳輪播類組件 https://github.com/leecade/react-native-swiper
  • 推薦11 款 React Native 開源移動 UI 組件
    React Native 可以使用最近非常流行的 React.js 庫來開發 iOS 和 Android 原生 APP。1. iOS 表單處理控制項 tcomb-form-nativetcomb-form-native 是 React Native 強大的表單處理控制項,支持 JSON 模式,可插拔的外觀和感覺。
  • ReactNative 的組件架構設計
    【編者按】本篇作者 @cnsnake11,寫的是 react native 的架構設計,如果你用 react
  • 沒 2 年 React Native 開發經驗,你都遇不到這些坑
    1.ViewView 組件作為最基礎的組件,撐起了 RN 頁面的半壁江山,在使用的過程中有幾個屬性比較冷門但個人認為挺有用的屬性。2.PermissionsAPP 平臺的權限管理是一件很繁瑣的事情,RN 官方只提供了 PermissionsAndroid,沒有提供跨平臺的權限管理 API,使用時很不方便。這裡我建議使用 react-native-permissions[11] 這個庫,管理權限更便捷。
  • React 測試入門教程
    $ git clone https://github.com/ruanyf/react-testing-demo.git$ cd react-testing-demo然後,打開 http://127.0.0.1:8080/,你會看到一個 Todo 應用。
  • 60+ 實用 React 工具庫,助力你高效開發!
    Material-UIMaterial-UI是一個簡單的、可定製的組件庫,用於構建更快、更漂亮、更易使用的 React 應用程式。官網地址:https://react-bootstrap.github.io/10. react-custom-scrollbarsreact-custom-scrollbars 是一個滾動條組件庫,可以在web和移動端流暢的使用滾動條,並且可以完全自己定製
  • 如何使用 React Native 構建實時 to do 應用程式
    我將在這個案例裡面使用最流行的移動框架之一 React Native 搭建一個待辦事項應用程式。我將使用 ReactiveSearch Native,這是一個提供 React Native UI 組件並幫助你快捷搭建數據驅動應用程式的開源庫。
  • 十大最受歡迎的 React Native 應用開發編輯器
    Atom 常用的包atom-react-native-autocomplete package - 該包針對 React-Native,為 Atom 編輯器提供自動補全功能。atom-react-native-css - 這是一個內置支持 SASS、SCSS 的 React-Native 組件的包。
  • 現有Android項目引入ReactNative--九步大法
    第三步:添加react和react-native 模塊:在根目錄執行如下代碼:npm install --save react react-native第五步:添加ReactNative相關依賴:1.在app的build.gradle文件中添加react-native依賴庫compile
  • Jest 配置與 React Hook 單元測試教程
    我們可以使用 [@testing-library/react-hooks](https://github.com/testing-library/react-hooks-testing-library) 來輔助實現。
  • 怎麼理解React Native的新架構?
    任何當前使用 Bridge 在 JavaScript 和原生端之間進行通信的原生模塊都可以通過用 C++ 編寫一個簡單的層來轉換為 JSI 模塊。標準化的 JS 引擎接口,React Native 可以替換 v8、Hermes 等引擎。
  • 入門 | 從Android到React Native開發
    react-native init 你的項目名字 來創建工程的,創建的工程會從網絡端,同步到你終端所在路徑的本地,生成一個和android project類似的項目,如下圖。其他人在使用React Native項目時,只需要npm install,工程就會根據package.json,去同步下載各個依賴庫到node_module。
  • 最火移動端跨平臺方案盤點:React Native、weex、Flutter
    react native 用了 react 的設計模式,但UI渲染、動畫效果、網絡請求等均由原生端實現。開發者編寫的js代碼,通過 react native 的中間層轉化為原生控制項和操作,比ionic等跨平臺應用,大大提高了的用戶體驗。總結起來其實就是:React Native是利用 JS 來調用 Native 端的組件,從而實現相應的功能。
  • 給所有開發者的React Native詳細入門指南
    比如RN組件庫的安裝,添加一些常用的Live Templates等,下圖是我添加的兩個比較常用的,給大家參考一下,至於如何添加Live Template大家可以自行百度一下,比較簡單,我就不過多贅述了。
  • 那些年錯過的React組件單元測試(上)
    因此單元測試的概念在前端領域應運而生,通過編寫單元測試可以確保得到預期的結果,提高代碼的可讀性,如果依賴的組件有修改,受影響的組件也能在測試中及時發現錯誤。🎮 技術方案針對項目本身使用的是React + Dva + Antd的技術棧,單元測試我們用的是Jest + Enzyme結合的方式。
  • JavaScript 測試系列實戰(三):使用 Mock 模擬模塊並處理組件交互
    打開 TodoList 的測試文件,首先在最前面通過 jest.mock 配置 axios 模塊的 Mock(確保要在 import TodoList 之前),在 Mock 之後,無論在測試還是組件中使用的都將是 Mock 版本的 axios。然後創建一個測試用例,檢查 Mock 模塊是否被正確調用。