<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用React Native Testing庫(kù)進(jìn)行組件測(cè)試(案例詳解)

          共 7970字,需瀏覽 16分鐘

           ·

          2021-06-01 04:55

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

          譯者:明月


          在本篇文章中,我們將探討 React Native 應(yīng)用程序開(kāi)發(fā)生態(tài)系統(tǒng)中的單元測(cè)試基礎(chǔ)知識(shí)。首先,讓我們了解一下什么是單元測(cè)試以及為什么在任何軟件開(kāi)發(fā)生命周期中都需要用到它。

          簡(jiǎn)介:?jiǎn)卧獪y(cè)試


          在單元測(cè)試中,項(xiàng)目中的每個(gè)組件都作為一個(gè)單元進(jìn)行單獨(dú)測(cè)試。這樣就可以測(cè)試獨(dú)立的組件,直到它們滿足設(shè)計(jì)和功能規(guī)范要求。

          主要思想是弄清楚該軟件的每個(gè)組件是否按照預(yù)期工作。僅當(dāng)軟件的每個(gè)單元正常工作時(shí),環(huán)境才能有效地工作并按預(yù)期運(yùn)行。

          作為開(kāi)發(fā)人員,您可以進(jìn)行單元測(cè)試,也可以由獨(dú)立的測(cè)試人員執(zhí)行。

          測(cè)試初學(xué)者的注意事項(xiàng):?jiǎn)卧獪y(cè)試可以是手動(dòng)的也可以是自動(dòng)的。整個(gè)過(guò)程涉及創(chuàng)建測(cè)試用例,對(duì)這些用例進(jìn)行審查,重新處理然后執(zhí)行。


          為什么單元測(cè)試必不可少


          簡(jiǎn)而言之,它是關(guān)于采用測(cè)試驅(qū)動(dòng)的開(kāi)發(fā)方法。測(cè)試驅(qū)動(dòng)的開(kāi)發(fā)涉及在將組件的每個(gè)模塊引入主系統(tǒng)之前對(duì)其進(jìn)行開(kāi)發(fā)和測(cè)試,這是構(gòu)建系統(tǒng)的一種更為精簡(jiǎn)的方法。

          通過(guò)使用單元測(cè)試,您可以獲得:
          • 單元測(cè)試作為功能實(shí)現(xiàn)。通過(guò)引用各種輸入值來(lái)檢查功能的輸出。這使調(diào)試過(guò)程變得更加容易。

          • 整個(gè)軟件開(kāi)發(fā)過(guò)程變得敏捷:引入任何新的修改后,就可以單獨(dú)測(cè)試組件并將其集成到系統(tǒng)中,從而節(jié)省大量時(shí)間和成本。

          • 由于可以在早期階段檢測(cè)和管理漏洞,因此減少了最后獲得煩人bug的機(jī)會(huì)。整體重構(gòu)和更新變得更加方便

          • 由于您已經(jīng)進(jìn)行了單元測(cè)試,可以為每個(gè)模塊及其功能提供深入的概述,因此文檔將變得不再那么繁瑣。

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

          • 它有助于從統(tǒng)計(jì)角度衡量每個(gè)組件和整個(gè)系統(tǒng)的性能,同時(shí)還能確定組件在系統(tǒng)中覆蓋的區(qū)域。

          • 您避免交付容易出錯(cuò)的產(chǎn)品。另外,您可以在降低復(fù)雜性的同時(shí)提高代碼質(zhì)量。

          總體而言,單元測(cè)試是交付成功產(chǎn)品的最安全方法之一。


          React Native中的單元測(cè)試入門(mén)


          React Native測(cè)試庫(kù) 提供了簡(jiǎn)單而完整的 React Native測(cè)試實(shí)現(xiàn)程序。

          https://github.com/callstack/react-native-testing-library

          這是用于測(cè)試React Native組件的輕量級(jí)解決方案,它在react-test-renderer之上促進(jìn)了實(shí)用方法。這將鼓勵(lì)更好的測(cè)試實(shí)踐。該庫(kù)與Jest并駕齊驅(qū),但也可以與其他測(cè)試運(yùn)行者合作。


          入門(mén)項(xiàng)目


          為為了在React Native 項(xiàng)目中進(jìn)行測(cè)試,我們首先需要一個(gè)入門(mén)項(xiàng)目,您可以繼續(xù)從snack項(xiàng)目中下載并啟動(dòng)項(xiàng)目。
          https://snack.expo.io/59ZFgP9Dn

          下載后,我們需要通過(guò)執(zhí)行以下命令在仿真器或連接的設(shè)備上運(yùn)行項(xiàng)目:

          Expo start

          在應(yīng)用程序中,我們有一個(gè)輸入字段,一個(gè)用于添加項(xiàng)目的按鈕和一個(gè)列表。該列表包含一個(gè)刪除按鈕,用于刪除列表項(xiàng)。主頁(yè)分為三個(gè)部分:

          • 主主屏幕(Home.js)

          • 列表組件(ItemsList.js)

          • 添加項(xiàng)目組件(ItemAdder.js)

          要執(zhí)行單元測(cè)試,我們需要將React Native測(cè)試庫(kù)安裝到我們的項(xiàng)目中。為此,我們需要在項(xiàng)目終端中運(yùn)行以下命令:

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


          該庫(kù)有一個(gè)react-test-rendererpeerDependencies列表。

          對(duì)于測(cè)試人員,我們將在這里使用 jest。因此,我們需要安裝jest-native庫(kù)作為附加的jest匹配器。為此,我們需要在項(xiàng)目終端中運(yùn)行以下命令:

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


          現(xiàn)在,我們需要配置我們的jest設(shè)置文件,即package.json文件中的模式。為此,我們?cè)?/span>package.json文件中存在的jest對(duì)象中添加以下配置行:

          {  "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"]  }}

          我們已完成配置,但未執(zhí)行測(cè)試。


          因此,我們?cè)谝粋€(gè)單獨(dú)的文件夾中創(chuàng)建一個(gè)新的測(cè)試文件,我們將在項(xiàng)目的./screens目錄中調(diào)用./test。在其中,我們創(chuàng)建一個(gè)名為Home.test.js的文件,該文件將包含與主屏幕有關(guān)的所有測(cè)試,并在運(yùn)行測(cè)試命令后執(zhí)行。


          現(xiàn)在是時(shí)候?qū)⑺璧膸?kù)導(dǎo)入Home.test.js文件中以進(jìn)行測(cè)試了:

          import React from 'react';import {render, fireEvent} from '@testing-library/react-native';import Home from '../Home';
          測(cè)試主屏幕的渲染


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


          如果一切正確呈現(xiàn),那就太好了!沒(méi)有問(wèn)題。現(xiàn)在使用render()方法并將Home組件傳遞給它。

          渲染方法將為我們提供測(cè)試主屏幕內(nèi)部組件所需的方法。

          同樣,我們?cè)谶@里使用debug方法來(lái)呈現(xiàn)主屏幕模板:

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


          此時(shí),我們可以使用兩個(gè)參數(shù)來(lái)實(shí)現(xiàn)測(cè)試功能,第一個(gè)參數(shù)是測(cè)試的名稱,第二個(gè)參數(shù)是在執(zhí)行測(cè)試時(shí)觸發(fā)的回調(diào)函數(shù)。
          在回調(diào)函數(shù)中,我們可以測(cè)試任何組件中的每個(gè)元素。
          在package.json文件中,我們有一個(gè)腳本來(lái)運(yùn)行測(cè)試:
          "scripts": {        "android": "react-native run-android",        "ios": "react-native run-ios",        "start": "react-native start",        "test": "jest",        "lint": "eslint ."}

          每次我們要執(zhí)行測(cè)試時(shí),都需要在項(xiàng)目終端中運(yùn)行以下命令:

          npm run test -watch


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

          如果發(fā)生任何錯(cuò)誤,則模板JSX元素的集成可能存在問(wèn)題,該問(wèn)題將在錯(cuò)誤消息本身中指示。

          測(cè)試輸入字段和按鈕組件的工作情況


          主屏幕中的輸入字段和按鈕組件是從ItemAdder組件導(dǎo)入的。

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

          <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('');  }}/>

          現(xiàn)在,我們可以使用Home.test.js文件中的getByTestId方法訪問(wèn)這些輸入和按鈕。然后我們通過(guò)提及它們的testID來(lái)初始化輸入字段和按鈕:

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

          接下來(lái),我們使用從測(cè)試庫(kù)導(dǎo)入的fireEvent對(duì)象實(shí)例,應(yīng)用輸入并觸發(fā)按鈕單擊。我們可以在輸入中輸入文本值,并以此觸發(fā)按鈕的按下:

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

          在這里,我們使用fireEvent類(lèi)中的changeText方法將輸入提供給我們應(yīng)用程序中的TextInput元素。我們提供的輸入值為'element'。按下功能將觸發(fā)我們應(yīng)用中的“添加”按鈕,這將使輸入顯示在列表中。

          問(wèn)題是:如何觸發(fā)觸發(fā)事件后,輸入值“ element”是否已出現(xiàn)在列表中?

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

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

          const element = getByText('element');

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

          這使我們可以使用Expect函數(shù)中的tobeDefined方法,該方法將元素作為參數(shù)。如果存在該值,則不會(huì)發(fā)生錯(cuò)誤。否則,將發(fā)生錯(cuò)誤。

          expect(element).toBeDefined();

          檢查以下完整的測(cè)試功能:

          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();});


          在這里,我們希望在添加輸入時(shí)定義元素并獲得此測(cè)試結(jié)果:

          我們可以看到測(cè)試已經(jīng)通過(guò)。


          這就是為什么我們現(xiàn)在也可以檢查多個(gè)輸入的原因。為此,我們分配了一個(gè)不同的輸入值'element1',并像之前的測(cè)試一樣進(jìn)行了所有操作。函數(shù)是這樣的:

          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();});

          如果運(yùn)行測(cè)試命令,則會(huì)得到以下結(jié)果:


          測(cè)試刪除按鈕


          在應(yīng)用程序演示中,您會(huì)注意到,當(dāng)我們將項(xiàng)目添加到列表中時(shí),我們還會(huì)獲得一個(gè)刪除按鈕。

          當(dāng)我們按下它時(shí),該項(xiàng)目消失。要測(cè)試按鈕,我們需要將testID屬性分配給ItemList.js文件中的delete Button組件:

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


          現(xiàn)在在Home.test.js中,我們需要?jiǎng)?chuàng)建一個(gè)稱為“ testing delete”的新測(cè)試函數(shù)。

          要測(cè)試刪除按鈕,首先我們必須在列表中有一個(gè)項(xiàng)目。

          因此,我們將使用與以前相同的編碼實(shí)現(xiàn)來(lái)輸入項(xiàng)目,并檢查其渲染。然后,我們使用getAllByTestID方法,該方法將每個(gè)元素以及在其中定義的特定testID定義為數(shù)組。

          現(xiàn)在,將數(shù)組分配給deleteButton常量:我們像以前一樣使用fireEvent類(lèi)中的press方法觸發(fā)按鈕。但是,由于我們僅刪除列表的第一項(xiàng),因此我們還需要分配數(shù)組標(biāo)識(shí)符。這將導(dǎo)致列表中的第一項(xiàng)被刪除。

          因此,我們使用queryByText檢查該第一項(xiàng)在渲染中是否可用。然后,通過(guò)應(yīng)用toBeNull從方法期望的功能,我們可以檢查數(shù)組的第一個(gè)項(xiàng)目是否可用或者不渲染。在這里獲取功能:

          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(); });


          我們?cè)谶@里所做的是,我們使用tobeNull方法將'element'值添加到列表中,然后將其刪除并檢查是否刪除了'element' 。

          如果答案是正確的,則該元素將被刪除,并且刪除功能將起作用。測(cè)試也應(yīng)該成功。現(xiàn)在,如果運(yùn)行測(cè)試,我們將得到以下結(jié)果:

          如我們所見(jiàn),我們對(duì)刪除按鈕的測(cè)試也成功。


          測(cè)試輸入后是否存在項(xiàng)目列表


          現(xiàn)在,對(duì)于下一個(gè)測(cè)試,我們?cè)谳斎胫挡螕簟疤砑印卑粹o后檢查列表項(xiàng)是否可用。

          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);});

          所有步驟,不同的類(lèi)似,我們使用toContainElement從期望函數(shù)來(lái)檢查我們?cè)诹斜碇休斎胩囟ǖ漠a(chǎn)品存在。因此,我們應(yīng)該得到以下結(jié)果:

          通過(guò)準(zhǔn)備不同的測(cè)試功能并分配測(cè)試ID來(lái)渲染元素,我們可以測(cè)試其他組件。



          結(jié)論


          哇,很長(zhǎng)的一段路程。讓我們快速回顧一下我們學(xué)到的東西:

          • 什么是單元測(cè)試

          • 為什么它是必不可少的

          • 如何使用React Native Testing庫(kù)在React Native生態(tài)系統(tǒng)中執(zhí)行它。

          最重要的一點(diǎn)是:通過(guò)基于組件渲染編寫(xiě)這些類(lèi)型的測(cè)試,我們可以驗(yàn)證React Native應(yīng)用程序的各個(gè)組件。如果發(fā)生任何錯(cuò)誤,這將有助于優(yōu)化應(yīng)用程序。

          測(cè)試庫(kù)提供了其他API和方法,您可以自由探索。面臨的挑戰(zhàn)是為各個(gè)組件設(shè)計(jì)自己的測(cè)試。您甚至可以先創(chuàng)建一個(gè)組件,然后按上述步驟對(duì)其進(jìn)行測(cè)試,然后再將其集成到核心應(yīng)用中。這稱為測(cè)試驅(qū)動(dòng)開(kāi)發(fā)。我們僅用幾行代碼即可執(zhí)行測(cè)試的簡(jiǎn)單性令人驚嘆。


          最后希望您能夠使用 React Native Testing 庫(kù)在React Native中掌握基于組件的基本測(cè)試方法。


          以上對(duì)單元測(cè)試的原理進(jìn)行了詳細(xì)的闡述,并通過(guò) React Native Testing 庫(kù)結(jié)合具體的案例進(jìn)行了詳細(xì)的代碼輸出 ,如果您認(rèn)為對(duì)您有幫助,請(qǐng)記得 點(diǎn)贊留言、分享收藏 哦~~


          最后

          面試交流群持續(xù)開(kāi)放,分享了近 許多 個(gè)面經(jīng)。
          加我微信: DayDay2021,備注面試,拉你進(jìn)群。

          我是 TianTian,我們下篇見(jiàn)~

          如何使用GPU改善JavaScript性能

          2021-05-28

          編譯的速度與激情:從10mins到1s

          2021-05-26

          使用React 360創(chuàng)建虛擬現(xiàn)實(shí)體驗(yàn)

          2021-05-24


          在看點(diǎn)這里
          瀏覽 169
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美成人18禁 | 免费黄色片子 | 欧美一级欧美一级在线播放 | www插插插无码视频 | 国产在线观看一区 |