手摸手,打造屬於本身的 React 組件庫02 — 測試篇

第二部分 - 測試篇:給組件加上單元測試css

原文連接html

引言

在第一部分,咱們基於 create-react-app 構建了項目的基礎結構。對於一個組件庫來講,不只要有簡單,實用的組件,每個組件的質量也是相當重要。而單元測試,正是提高軟件質量的一種有效的手段。在本文中,不只會在以前的項目中完成單元測試的配置,還會帶着你們一塊兒走進單元測試的世界~node

教程部分

本篇文章,是這個系列的第二篇 - 單元測試react

2020到了,我還須要單元測試嗎?

首先,告訴你們一個小祕密,就是我不太喜歡單元測試。它很費時,重構項目會變得很吃力。並且,單元測試沒有一個明確的邊界,有時總會以爲本身的單元測試寫的不夠。並且,代碼也並不會由於單元測試就不會出現 BUG,即便你的測試覆蓋率達到了💯%。git

值得幸運的是,對於 React 應用來講,單元測試的成本正在逐步下降。github

優秀的 TypeScript

首先,在 TypeScript 出現以後,咱們不須要去寫大部分的單元測試。npm

舉個簡單的例子,這是 TypeScript 的實現:json

type Props = {
  name: string;
};
複製代碼

而下面的這段代碼,是單元測試的版本:api

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 的類型系統的出現,已經再也不須要這部分的單元測試了。bash

ESLint 和 Prettier

Eslint 會分析代碼,並根據一組規則對其進行檢查。這聽起來也很像測試。而 Prettier 能夠根據一組規則來約束代碼風格。而且,在編寫代碼的時候,配合編輯器就能夠獲得即時的反饋了。

像用戶同樣編寫測試

上面所提到的技術,更可能是從語言,代碼質量,代碼風格的角度來提高軟件的質量,但卻沒有像一個用戶同樣來使用咱們的軟件。畢竟,軟件怎麼使用,只有開發者清楚。

除了編寫文檔、註釋、編寫 Demo。單元測試也更像是軟件的一種說明書,爲軟件的使用提供了保障。

React 文檔 中所描述的同樣,本文也只是討論:渲染組件樹,在一個簡化的測試環境中渲染組件樹並對它們的輸出作斷言檢查。

技術棧

  • Jest:JavaScript 測試框架。
  • @testing-library/react:將 React 組件轉化成 Dom 節點來測試,而不是渲染的 React 組件的實例,能夠當作是 Enzyme 的替代。
  • ts-jest:是一個 TypeScript 預處理器,它支持 Jest 的源映射,容許你使用 Jest 測試用 TypeScript 編寫的項目。
  • jest-html-reporter:一個生成測試報告的庫。

項目配置

由於以前使用的是 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,增長測試用例。

empty-line/index.tsx
import './style/index.less';
import EmptyLine from './EmptyLine';

export default EmptyLine;
複製代碼
empty-line/EmptyLine.tsx
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;
複製代碼
empty-line/__test__/index.test.tsx
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 就能夠看到結果:

image

當咱們提交代碼,commit 的時候,也會在根目錄生成一個測試報告:

image

結束語

到這裏,咱們給組件庫增長了測試的功能。使咱們的組件庫也變得更加有保障,高大上了起來。最後,在第三章中,咱們會聊聊如何打包,並上傳至 NPM 的事情,敬請期待吧。

相關文章
相關標籤/搜索