前言

单元测试和 E2E 测试作为 前端项目健壮性的保障,在许多团队可能并没有足够的能力和资源去实现很好的自动化测试,但基本的了解还是必不可少的。

最近在上手并集成单元测试到已有的 Next.js 项目中,网上的文档虽然很多,但实际使用的时候遇到的问题可谓五花八门,这篇文章可以帮助你快速的在 Next.js + TS 的环境中构建单元测试环境及进行单测的编写。

框架搭建

Jest 是目前最主流的前端测试框架,仅通过 Jest 没办法完成前端的所有单元测试,因为前端的单元测试涉及到 Dom 和事件的模拟。因此我们还需要一些测试辅助库来为我们模拟相关的场景。DOM Testing Library 适用于任何提供 DOM API 的环境,这个库提供了包含 React,Vue, Angular 这三个主流框架的 API,使用这些 API 我们可以在执行单测时实现 类似于用户在页面上查找元素 的方式查询 DOM 中的节点的操作,帮助我们实现更加符合真实环境的测试。

下面我们在已有的 Next.js 项目的基础上引入 Jest,React testing library 以及相关的一些依赖,执行以下命令:

yarn add jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom -D

接下来我们需要创建一下一下 Jest 的配置文件,在项目根目录下创建 jest.config.ts ,写入以下配置:

const nextJest = require('next/jest');

const createJestConfig = nextJest({

// Provide the path to your Next.js app to load next.config.js and .env files in your test environment

dir: './',

});

// Add any custom config to be passed to Jest

const customJestConfig = {

// Add more setup options before each test is run

// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work

moduleDirectories: ['node_modules', '/'],

testEnvironment: 'jest-environment-jsdom',

testPathIgnorePatterns: ['/cypress/'],

setupFilesAfterEnv: ['/jest.setup.ts'],

moduleNameMapper: {

'^@/(.*)$': '/src/$1',

},

};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async

module.exports = createJestConfig(customJestConfig);

export {};

然后再创建 jest.setup.ts 文件,暂时先写入以下配置:

import '@testing-library/jest-dom/extend-expect';

这个配置文件是根据 Next.js 文档中提供的配置进行修改的,我们先看看文档中对于这段配置的描述:

在后台,next/jest 会自动为我们配置 Jest,包括以下步骤:

使用 SWC 设置 transform自动 mock 样式(包括.css、.module.css 和它们的 scss 变量)、图片 import 以及 @next/font加载.env(所有的环境变量)到process.env在解析及编译测试时忽略 node_modules 目录在解析测试时忽略 .next 目录加载next.config.js用于启用 SWC transform 的配置

而我单独加的配置有如下几个:

testPathIgnorePatterns: ['/cypress/']: 需要忽略的测试目录,这里我忽略了 cypres 目录,因为我们的 E2E 测试使用的是 Cypress ,如果不忽略的话,在执行 jest 的测试命令时会把 E2E 的测试也给跑起来。setupFilesAfterEnv: ['/jest.setup.ts']:配置 Jest 的 setup 文件位置,Jest 的 setup 文件用于在 执行测试时先执行一些固定的初始化操作,例如执行一些 import 等操作,这样就不需要在每一个测试中单独引入某些依赖了。moduleNameMapper: { '^@/(.*)$': '/src/$1', }:这一步是为了配置一下测试文件中 引入依赖时的别名,就像 webpack 或 vite 中 alias 配置的功能,当在引入依赖的目录中开头为 @ 时,会指向根目录下的 src 目录。在配置文件的最后有一个 export {} ,这一步是为了解决当 tsconfig.json 中的 isolatedModules 设置为 true 时,如果 ts 文件中不存在 import 或 export 时,ts 认为这个文件不是一个 ES Module,而是一个全局脚本,导致编译时报错。

接下来我们在 package.json 中新增一个指令:

"scripts": {

//...

"test": "jest"

}

当我们执行例如 yarn test 时,Jest 会去识别我们目录中的所有测试文件并执行。此时如果我们执行运行测试,会打印如下错误:

Error: Jest: Failed to parse the TypeScript config file

这个错误的原因是我们的配置文件是由 Node.js 去直接执行的,而 Node.js 并不能直接执行 ts 文件,我们也没有将配置文件进行编译,所以我们需要安装一下 ts-node,执行以下命令进行安装:

yarn add ts-node -D

安装后再次执行 yarn test 就不会报错了,ts-node 的作用就是让 Node.js 可以直接运行 ts 脚本,在执行的过程中自动进行编译,不需要我们自己提前编译为 js 脚本,更多详情可以参考 ts-node 官网

测试 Demo 编写

在框架搭建完成后,我们来实现一个简单的 demo 上手一下,首先我们需要设计一下测试的文件要放在哪个目录,这里我是将组件的测试目录与组件放在同一个目录中的,例如我们有一个 返回上一级的按钮组件 Back ,它的目录为 src/components/Back/index.tsx,这里我们再创建一个 src/components/Back/__test__ 目录用于放置测试文件,然后我们在目录中创建 index.test.tsx 文件,写入以下代码:

import { render, screen } from '@testing-library/react';

import Back from '../index';

describe('Back', () => {

it('should render with default text', () => {

render();

const element = screen.getByText(/back/i);

expect(element).toBeInTheDocument();

});

it('should render with right test', () => {

render();

const element = screen.getByText(/Back to home/i);

expect(element).toBeInTheDocument();

});

});

describe 用于定义一个 测试用例组,it 则用于定义一个 单独的测试用例,这两个 API 是全局定义的,并不需要引入。

代码中我们创建了一个测试用例组,其中包含了两个测试,it 的第一个参数用于描述测试的作用,这里就简单测试下 默认情况 与 传入参数的情况 下组件是否能正确渲染。render 用于渲染组件,screen 大家可以理解为测试环境的 document,可以用于获取渲染的 dom 节点,expect 则是用于检查值是否满足特定条件。

因此这里的测试流程也就是:

引入并渲染组件根据某些条件获取 dom 节点判断组件是否正确渲染

后续更复杂的测试大致也是根据这种测试思路进行延伸,关于 API 的具体作用请参考 React-testing-library 文档 与 Jest API 文档

配置 Github Action

在我们的测试可以顺利执行后,我们可以实现一下单测的自动化,这里以 Github Action 为例,基础的实现还是非常简单的,首先创建一个新的 workfolw 配置文件 your_project/.github/workflows/frontend-unit.yml

然后写入以下配置:

name: CI

on: push

jobs:

build:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v2

- name: Install modules

run: yarn

- name: Run tests

run: yarn test

这个配置文件就是在 ubuntu 环境中执行 yarn test 开始测试,当然在实际的项目中肯定不止这么简单,但根据实际情况进行触发时机的修改或增加执行流程即可,当然你也可以增加测试覆盖率的打印等命令,这个会在后面我实践后单独出文章介绍。

总结

这篇文章介绍了下如何在 Next.js 搭建组件测试的环境以及最基本的测试实现,关于更多的踩坑以及一些最佳实践会在后续摸索后继续出文章,如果大家对于 E2E 测试想要了解也可以评论区留言,在 E2E 测试方面我们已经有了比较丰富的实践经验,可以期待下后续的文章。如果这篇文章对你有帮助欢迎点赞或关注。

查看原文