第二部分 - 测试篇:给组件加上单元测试
原文连接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
的事情,敬请期待吧。