敬請指正-我進行單元測試的分享
單元測試的好處是啥?
- 重構、重構、重構,重要的事情說三遍
TDD(測試驅動開發)的具體實現就是通過紅燈->綠燈->重構不斷重複,一步一步去健壯我們的程式碼,保證今後重構程式碼的時候測試的準確,可以在重構中準確的定位到問題。同時也為以後的開發提供支援,在測試的基礎上我們可以重構結構和業務功能。 - 單元測試是最好的註釋
測試會提示你哪些步驟是可以通過、如何使用的最好文件。更詳細的規範了測試目標的邊界值與非法值。 - 定位bug,減少bug
單元測試可以通過不同的條件來發現問題在哪裡,在一些弱型別的語言中也避免了一些型別檢查的低階錯誤,當然這個現在我們都用TypeScript做到了。 - 被迫的規範組織結構
可能平時我們會把一個方法寫的很複雜、一個類寫的很大,沒有想過如何去組織結構,但如果你想到你即將的測試要如何寫的時候,那可能你在開發前必須要想想哪些部分可以提出來了。這樣會慢慢養成很好的思維。
好了,不多BB,看看怎麼用吧!!!
我用的是jest測試哦!!!
1.看一下我的jest.config.js中testMatch
,告訴我需要在lib資料夾中建立個目錄__tests__
,__tests__
的目錄裡面xxxx.unit.(js|jsx|ts|tsx)
這樣的檔案就是測試檔案
加入我們642830685,領取最新軟體測試大廠面試資料和Python自動化、介面、框架搭建學習資料!
那就建立個資料夾和檔案唄
2.我要測試啥呢?我先測試我ui輪子裡面的一個函式,試一下
這是我之前寫的一個函式,就測試他,他會接受一個className
3.在classes.unit.jsx裡面寫一個,單元測試
// 先將測試檔案匯入進來 import classes from "./helpers/classes"; // 要在describe裡面進行測試 describe('classes', () => { // it是宣告,第一個引數是對測試的描述,第二個引數是函式,裡面是對測試的執行 it('他接受 className', () => { // 我給classes函式傳了一個字串a const result = classes('a') // 我斷言result會是一個字串a expect(result).toEqual('a') }) })
4.哈哈哈,興高采烈的執行一下,如果你是yarn並且用的我得配置,就用yarn test
報錯了,說我少了一個配置'babel-preset-react-app',安裝一下唄
yarn add --dev babel-preset-react-app
5.安裝成功了,再來一下看看yarn test
,哎,成功!
6.每次改寫測試檔案,都要我yarn test
,好煩....,試試這個操作yarn test --watch
,每次更改都會自動測試啦!
7.我要是想測試一個icon元件怎麼辦?來,我們繼續搞起來
看下面這段程式碼
import * as renderer from 'react-test-renderer'
import React from "react";
import Icon from '../icon'
describe("icon",()=>{
it("ICON 是 SVG",()=>{
// 首先用renderer建立一個Icon,然後把Icon轉成json
const json = renderer.create(<Icon/>).toJSON();
// 這個json進行快照
expect(json).toMatchSnapshot()
})
})
8.當我執行到這裡以為可以進行測試的時候,意外出現了....bug了,原因是我測試的Icon元件中有用到scss沒有配置,無法識別
首先在test目錄下建立新的目錄,並建立下面的兩個檔案
然後在file-mock.js中加入這段程式碼module.exports = 'test-file-stub';
在object-mock.js中加入這段程式碼module.exports = {};
最外層找到jest.config.js檔案,替換這段
moduleNameMapper: {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test/__mocks__/file-mock.js",
"\\.(css|less|sass|scss)$": "<rootDir>/test/__mocks__/object-mock.js",
},
上面這段程式碼這裡來解釋一下:
/test/__mocks__/file-mock.js
/test/__mocks__/object-mock.js
9.再跑一下,嗯.....,本以為解決了,唉!!!新問題出現了,來源於這個檔案的報錯
嗯?我測試的時候也不需要測試svg啊,果斷的刪除console.log(error)
,這樣子就不報錯了
10.我們來看一下這段程式碼expect(json).toMatchSnapshot()
,他做了什麼樣的事情,我們看一下.snap
<svg
className="fui-icon"
>
<use
xlinkHref="#undefined"
/>
</svg>
他會幫我們生成一個svg,為什麼use會是undefined???因為我還沒有給他傳name值,給name傳遞一個值,重新執行yarn test之後,報錯了
他說我們修改了內容,但是快照沒有修改,與快照不同,這時候需要重新執行,修改快照裡面的內容,重新執行yarn test -u
意味著儲存我們最新的正確的快照
11.我們來測試一下onClick,首先下載兩個庫enzyme
和enzyme-adapter-react-16
,執行
yarn add --dev enzyme
yarn add --dev enzyme-adapter-react-16
配置test目錄下的setupTests.js檔案
const enzyme = require('enzyme')
const Adapter = require('enzyme-adapter-react-16')
enzyme.configure({adapter: new Adapter()})
接下來我們onClick進行測試,一點一點看他表達了什麼意思
我們是要測試一個點選事件函式,匯入了這個庫之後,這個庫幫我們生成了一個假的頁面,並將測試的函式傳入Icon元件,找到svg模擬點選svg,我們自己建立一個fn測試看看對不對,我們期待n等於2,如果不確定是否測試成功,將n改成1試一試
import {mount} from 'enzyme'
describe("icon", () => {
it("onClick", () => {
let n = 1;
const fn = () => {
n = 2
}
// 生成假想頁面
const comonent = mount(<Icon name="baidu" onClick={fn}/>)
// 找到svg模擬點選svg
comonent.find('svg').simulate('click')
// 我們期待n等於2
expect(n).toEqual(2)
})
})
但是我們這個方法有點笨,每次測試都要自己寫個fn,傻乎乎的!!!
能不能讓jest幫我們寫一個fn呢
const fn = jest.fn();
這段程式碼是讓jest建立一個fn()
expect(fn).toBeCalled();
我們期待fn會被呼叫
it("onClick", () => {
const fn = jest.fn();
const component = mount(<Icon name="baidu" onClick={fn}/>)
component.find('svg').simulate('click')
expect(fn).toBeCalled();
})
執行yarn test,測試通過了,但是我們不知道是不是真的進行測試了,建立一個fn2,這個fn2我們並不會傳,看看報錯了沒有,報錯了,就是真的測試了,說明onClick被呼叫了,測試通過了
總結
- 這篇文章是本人在寫Icon元件中,學習jest單元測試進行的配置,以及語法
- 我們瞭解到了,單元測試的好處,為什麼要學他....
- 我們學習到了配置,以及語法表示的含義
這便是本人的分享,一遍遍踩坑,一遍遍爬過來會有許多成長,相信大家也一定有這種感受,一起努力吧!!!
加入我們642830685,領取最新軟體測試大廠面試資料和Python自動化、介面、框架搭建學習資料!