第二部分 - 測試篇:給組件加上單元測試
原文連接css
在第一部分,咱們基於 create-react-app
構建了項目的基礎結構。對於一個組件庫來講,不只要有簡單,實用的組件,每個組件的質量也是相當重要。而單元測試,正是提高軟件質量的一種有效的手段。在本文中,不只會在以前的項目中完成單元測試的配置,還會帶着你們一塊兒走進單元測試的世界~html
本篇文章,是這個系列的第二篇 - 單元測試node
首先,告訴你們一個小祕密,就是我不太喜歡單元測試。它很費時,重構項目會變得很吃力。並且,單元測試沒有一個明確的邊界,有時總會以爲本身的單元測試寫的不夠。並且,代碼也並不會由於單元測試就不會出現 BUG
,即便你的測試覆蓋率達到了💯%。react
值得幸運的是,對於 React
應用來講,單元測試的成本正在逐步下降。git
首先,在 TypeScript
出現以後,咱們不須要去寫大部分的單元測試。github
舉個簡單的例子,這是 TypeScript
的實現:npm
type Props = { name: string; };
而下面的這段代碼,是單元測試的版本:json
import React from 'react'; import Component from './Component'; test('does not do something completely embarassing if I forgot to pass a name', () => { const { getByText } = render(<Component />); expect(getByText('Name: ')).not.toBeInTheDocument(); });
因此,TypeScript
的類型系統的出現,已經再也不須要這部分的單元測試了。api
Eslint
會分析代碼,並根據一組規則對其進行檢查。這聽起來也很像測試。而 Prettier
能夠根據一組規則來約束代碼風格。而且,在編寫代碼的時候,配合編輯器就能夠獲得即時的反饋了。babel
上面所提到的技術,更可能是從語言,代碼質量,代碼風格的角度來提高軟件的質量,但卻沒有像一個用戶同樣來使用咱們的軟件。畢竟,軟件怎麼使用,只有開發者清楚。
除了編寫文檔、註釋、編寫 Demo。單元測試也更像是軟件的一種說明書,爲軟件的使用提供了保障。
和 React 文檔 中所描述的同樣,本文也只是討論:渲染組件樹,在一個簡化的測試環境中渲染組件樹並對它們的輸出作斷言檢查。
由於以前使用的是 react-app-rewired
做爲 Cli 工具,它會對 Jest
的版本有所限制。因此,下面安裝依賴時,有些庫會鎖住版本。
npm i -D ts-jest@24.1.0 @types/jest jest@24.9.0 jest-html-reporter @testing-library/react @babel/preset-env @babel/preset-react
爲了使用安裝的這些依賴,接下來須要修改下 package.json
,增長測試,以及提交以前的校驗。
... "scripts": { + "test": "jest --no-cache", } ... "lint-staged": { "*.{js,ts,tsx}": [ "eslint --fix src/**/*.{ts,tsx}", + "jest --bail --coverage --findRelatedTests", "git add ." ], "*.{md,css,html,less}": [ "prettier --write", "git add ." ] }
最後,還須要給 Jest
增長一個配置文件:jest.config.js
module.exports = { preset: 'ts-jest', transform: { '^.+\\.tsx?$': 'ts-jest', }, globals: { 'ts-jest': { babelConfig: { presets: ['@babel/preset-env', '@babel/preset-react'], }, }, }, testEnvironment: 'jsdom', testMatch: [ '<rootDir>/src/**/__tests__/**/*.{ts,tsx,js,jsx,mjs}', '<rootDir>/src/**/?(*.)(spec|test).{ts,tsx,js,jsx,mjs}', ], reporters: [ 'default', [ './node_modules/jest-html-reporter', { pageTitle: '測試報告', }, ], ], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], collectCoverage: true, collectCoverageFrom: ['app/react/**/*.{ts,tsx}', '!app/react/__tests__/api/api-test-helpers.ts'], };
這裏,我須要給以前添加的 EmptyLine
,增長測試用例。
import './style/index.less'; import EmptyLine from './EmptyLine'; export default EmptyLine;
import React from 'react'; export interface IEmptyLineProps { height?: number; } const EmptyLine = ({ height = 20 }: IEmptyLineProps) => { return <div className="d-empty-line" style={{ height }} />; }; export default EmptyLine;
import React from 'react'; import { create, act } from 'react-test-renderer'; import EmptyLine from '../EmptyLine'; test('默認高度渲染正常', () => { const emptyLine = create(<EmptyLine />).toJSON(); expect(emptyLine?.props.style).toEqual( expect.objectContaining({ height: 20, }), ); }); test('自定義高度渲染正常', () => { let emptyLine: any; act(() => { emptyLine = create(<EmptyLine height={30} />); }); expect(emptyLine.toJSON()?.props.style).toEqual( expect.objectContaining({ height: 30, }), ); });
下面,就是兩個 EmptyLine
常見的使用場景,已經在咱們的單元測試中都覆蓋到了。
須要注意的是,這裏的 EmptyLine.tsx
組件中並無引入樣式,而是在同級的 index.tsx
中引入了樣式。由於,這裏樣式在測試的時候是不支持引入的,會出問題。
運行 npm run test
就能夠看到結果:
當咱們提交代碼,commit
的時候,也會在根目錄生成一個測試報告:
到這裏,咱們給組件庫增長了測試的功能。使咱們的組件庫也變得更加有保障,高大上了起來。最後,在第三章中,咱們會聊聊如何打包,並上傳至 NPM
的事情,敬請期待吧。