如何進(jìn)行react的組件測試?

背景

在平時開發(fā)過程中,可能大部分開發(fā)同學(xué)是忽略對react組件進(jìn)行一些自動化測試工作的,更多可能是以實現(xiàn)功能為目標(biāo),測試就交給測試同學(xué)。如果能做一些單元測試,短期看可能會增加工作量,長期來看,實際上能夠避免一些低級錯誤,提高開發(fā)效率,降低故障率。本文基于create-react-app搭建前端項目,使用Jest@testing-library/react進(jìn)行組件測試。

最簡單的react組件測試方式就是做快照測試,能夠獨立的測試每一個組件,有點類似于單元測試中對classes進(jìn)行測試。

準(zhǔn)備前端項目

我們通過create-react-app創(chuàng)建一個前端測試項目

npx create-react-app react-components-test

耐心等待項目創(chuàng)建完成。項目創(chuàng)建完成后,我們通過cd react-components-test指令進(jìn)入到項目目錄下,我們可以看到已經(jīng)有一個測試的js——App.test.js

項目目錄內(nèi)容

之后執(zhí)行npm test,就可以看到一個測試結(jié)果:

測試結(jié)果

在這個結(jié)果中,我們可以看到測試文件幾個,然后測試用例通過數(shù)量是多少,測試花費的時間等等信息。

難度上升了

接下來,我們做一些有實際用處的測試工作。我們先簡單創(chuàng)建一個小的前端應(yīng)用,添加一些方法功能,讓測試顯的更真實一點。
首先,讓我們添加一個Button組件,這個組件的功能就是點擊之后,就會加上button上設(shè)置的數(shù)值。這個組件有兩個傳參increment(設(shè)置+多少數(shù)值)和onClickFunction(點擊事件)

// Button.js
import React from 'react'

const Button = ({ increment, onClickFunction }) => {
  const handleClick = () => {
    onClickFunction(increment)
  }
  return <button onClick={handleClick}>+{increment}</button>
}

export default Button

修改App.js

import React, { useState } from 'react'
import Button from './Button'

const App = () => {
  const [count, setCount] = useState(0)

  const incrementCount = increment => {
    setCount(count + increment)
  }

  return (
    <div>
      <div>learn react</div>
      <Button increment={1} onClickFunction={incrementCount} />
      <Button increment={10} onClickFunction={incrementCount} />
      <Button increment={100} onClickFunction={incrementCount} />
      <Button increment={1000} onClickFunction={incrementCount} />
      <span>{count}</span>
    </div>
  )
}

export default App

接下來,我們將用 @testing-library/react幫助我們測試按鈕點擊后的結(jié)果是不是正常。
首先讓我們測試Button組件。在Button組件中創(chuàng)建一個Button.test.js文件。

//Button.test.js
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import Button from './Button'

我們從react-testing-library引入render和fireEvent工具方法,render能夠幫助我們渲染JSX,fireEvent能讓我們在組件上觸發(fā)一個事件。
由于Button組件通過接收一個方法綁定到click事件上,我們添加一個count變量,同時創(chuàng)建一個增加它的方法

//Button.test.js
let count

const incrementCount = increment => {
  count += increment
}

現(xiàn)在,我們開始寫一個測試用例。首先我們初始化一個count值為0,然后在我們Button組件上increment傳值為1,onClickFunction傳我們定義的方法incrementCount,緊接著我們?nèi)カ@取組件第一個子元素的值,檢查它是不是顯示+1
我們通過代碼去觸發(fā)點擊事件,查看count值是不是從0變成了1。

//Button.test.js
test('+1 Button works', () => {
  count = 0
  const { container } = render(
    <Button increment={1} onClickFunction={incrementCount} />
  )
  const button = container.firstChild
  expect(button.textContent).toBe('+1')
  expect(count).toBe(0)
  fireEvent.click(button)
  expect(count).toBe(1)
})

同樣的,我們試試+100的按鈕點擊之后是不是也功能正常:

//Button.test.js
test('+100 Button works', () => {
  count = 0
  const { container } = render(
    <Button increment={100} onClickFunction={incrementCount} />
  )
  const button = container.firstChild
  expect(button.textContent).toBe('+100')
  expect(count).toBe(0)
  fireEvent.click(button)
  expect(count).toBe(100)
})

然后,我們試試去測試App組件功能是不是正常。在頁面上,我們顯示了4個按鈕組件,我們可以測試每個按鈕在點擊事件之后,是不是加上了對應(yīng)的數(shù)值,我們可以盡可能多的測試幾次。

// App.test.js
import React from 'react'
import {render, screen, fireEvent} from '@testing-library/react'
import App from './App'

test('renders learn react link', () => {
    render(<App />)
    const linkElement = screen.getByText(/learn react/i)
    expect(linkElement).toBeInTheDocument()
})

test('App works', () => {
    const {container} = render(<App />)
    // console.log(container)
    const buttons = container.querySelectorAll('button')

    expect(buttons[0].textContent).toBe('+1')
    expect(buttons[1].textContent).toBe('+10')
    expect(buttons[2].textContent).toBe('+100')
    expect(buttons[3].textContent).toBe('+1000')

    const result = container.querySelector('span')
    expect(result.textContent).toBe('0')
    fireEvent.click(buttons[0])
    expect(result.textContent).toBe('1')
    fireEvent.click(buttons[1])
    expect(result.textContent).toBe('11')
    fireEvent.click(buttons[2])
    expect(result.textContent).toBe('111')
    fireEvent.click(buttons[3])
    expect(result.textContent).toBe('1111')
    fireEvent.click(buttons[2])
    expect(result.textContent).toBe('1211')
    fireEvent.click(buttons[1])
    expect(result.textContent).toBe('1221')
    fireEvent.click(buttons[0])
    expect(result.textContent).toBe('1222')
})

我們就可以看到下面的測試結(jié)果:


完整測試結(jié)果

結(jié)語

好了,到此為止,react組件測試流程就完整的跑過了一遍。在真實的開發(fā)場景中,功能和邏輯會更復(fù)雜,本篇文章的目的在于拋磚引玉,如果對自動化測試感興趣的同學(xué),可以參考jest@testing-library/react官方文檔,在自己的項目中應(yīng)用上去。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容