Fork me on GitHub
秋染蒹葭

前端工程化之一:常见的单元测试工具

前端单元测试的好处是显而易见的,比如别人的代码我怎么改,新功能添加上了怎么保证旧功能没问题。而且现在都有测试驱动开发的概念了。但是呢,前端的单元测试究竟该怎么做?

假如我们是团队合作,我写的代码可能被其他人修改,即使是自己的代码也有可能在改动的时候出问题,我们需要测试,而且还需要将这些测试固化为代码。测试需要覆盖所有的逻辑,使得我们的代码质量得到保障,这也是单元测试的意义,并且测试用例需要小而精,覆盖率高,稳定。

怎么开始

测试需要测试框架+断言库,常用的测试框架是karma,moca。常用的断言库为assert,jasmine,expect,chai等

使用karma+jasmine+coverage

Karma是Testacular的新名字,在2012年google开源了Testacular,2013年Testacular改名为Karma。

Karma是一个基于Node.js的JavaScript测试执行过程管理工具(Test Runner)。该工具可用于测试所有主流Web浏览器,也可集成到CI(Continuous integration)工具,也可和其他代码编辑器一起使用。这个测试工具的一个强大特性就是,它可以监控(Watch)文件的变化,然后自行执行,通过console.log显示测试结果。

使用初始化命令,设置配置文件

1
karma init

开始测试

1
karma start

可以在chrome的控制台查看信息:

coverage

一般的测试我们需要查看测试覆盖率,在Karma中,可以通过karma-coverage查看覆盖率,修改配置文件如下:

1
2
3
4
5
6
7
8
9
preprocessors: {
'src/*.js': ['coverage']
},
coverageReporter: {
type: 'html',
dir: 'coverage/'
},
reporters: ['progress','coverage'],

可以查看测试覆盖率,一共有4个维度的测量数据:

注意测试要对每一个逻辑分支进行测试,才能保证测试覆盖率。

Jasmine

Jasmine是一个Javascript的BDD(Behavior-Driven Development)测试框架,不依赖任何其他框架。

基本语法介绍

describe(string, function)(测试套件,test suite)
可以理解为是一个测试集或者测试包(为了便于称呼,我们本文中统一叫测试集,官方称之为suite),主要功能是用来划分单元测试的,describe是可以嵌套使用的。

  • 参数string:描述测试包的信息
  • 参数function:测试集的具体实现

it(string, function)(测试用例,test case)
测试用例(官方称之为spec)

  • 参数string:描述测试用例的信息
  • 参数function:测试用例的具体实现

expect:断言表达式

每个测试文件中可以包含多个describe,每个describe中可以包含多个it,每个it中可以包含多个expect。

expect的使用

所有的expect都可以使用not表示否定的断言。下面是匹配器

  • toBe:基本类型判断
  • toEqual: toEqual有两种用法,对于基本的类型,toEqual相当于toBe,还可以用来判断对象。
  • toMatch: 使用正则表达式判断
  • toBeDefine: 判断是否是undefined
  • toBeUndefined: 判断是否是undefined,与toBeDefine相反
  • toBeNull:判断是否是null
  • toBeTruthy:判断是否能转换成bool型,判断的是否是True
  • toBeFalsy:判断是否能转换成bool型,判断的是否是False
  • toContain: 判断集合是否包含(可以是普通类型,和可以是对象)
  • toBeLessThan: 判断值类型的大小,结果若小则为True(也可以判断字符及字符串,以ascii码的大小为判断依据)
  • toBeGreaterThan: 判断值类型的大小,结果若大则为True,与toBeLessThan相反(也可以判断字符及字符串,以ascii码的大小为判断依据)
  • toBeCloseTo:判断数字是否相似(第二个参数为小数精度,默认为2位)
  • toThrow: 判断是否抛出异常
  • toThrowError: 判断是否抛出了指定的错误,判断是否是指定的错误

Setup和Teardown(钩子函数)

Jasmine允许在执行测试集/测试用例的开始前/结束后做一些初始化/销毁的操作,以下是提供的钩子函数:
Setup方法:

  • beforeAll:每个suite(即describe)中所有spec(即it)运行之前运行
  • beforeEach:每个spec(即it)运行之前运行

Teardown方法:

  • afterAll:每个suite(即describe)中所有spec(即it)运行之后运行
  • afterEach:每个spec(即it)运行之后运行

在beforeEach/it/afterEach中,还可以使用this关键字定义变量,需要注意的是,使用this关键字声明的变量,仅在beforeEach/it/afterEach这个过程中传递。

xdescribe/xit的使用

在实际项目中,需要由于发布的版本需要选择测试用例包,xdescribe和xit能很方便的将不包含在版本中的测试用例排除在外。不过xdescribe和xit略有不同:两者一个根本不会运行,另一个it会运行但是被挂起

  • xdescribe:该describe下的所有it将被忽略,Jasmine将直接忽略这些it,因此不会被运行
  • xit:运行到该it时,挂起它不执行

自动化单元测试

Karma+Jasmine+istanbul+webpack自动化单元测试,需要一个karma-webpack库,这是让karma可以去调用webpack,相当于一个桥梁。

1
npm i karma-webpack -g

具体配置可以参考如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Karma configuration
// Generated on Sat Aug 26 2017 20:31:19 GMT+0800 (中国标准时间)
module.exports = function(config) {
config.set({
// 将用于解析所有模式的基本路径(例如,文件,排除)ps: 修改它会影响files和exclude路径,没有特殊需求默认就行。
basePath: '',
// 选择测试框架我们选的‘jasmine’ 可以在这里去找更多相关的框架 https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// 在浏览器中加载的匹配的文件列表 就是我们的第4步
files: [
'src/**/*.spec.js'
],
// 要排除的文件列表 就是我们的第5步
exclude: [],
// 在将其提供给浏览器之前,预处理匹配的文件, 可用的预处理器 https://npmjs.org/browse/keyword/karma-preprocessor
// 测试文件需要处理一下,各框架和库都不一样,可以在链接中找到你对应的框架的处理器
// key是文件夹路径,也是就files的路径,value是一个数组,也就是预处理器集合
preprocessors: {
'src/**/*.spec.js': ['webpack', 'sourcemap']
},
// webpack配置 不需要入口(entry)和输出(output)配置
webpack: {
devtool: 'inline-source-map',
module: {
rules: [{
test: /\.js$/,
use: {
loader: 'istanbul-instrumenter-loader',
options: { esModules: true }
},
enforce: 'pre',
exclude: /node_modules|\.spec\.js$/,
}, {
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'],
plugins: ['istanbul']
}
},
exclude: /node_modules/
}]
}
},
// 依赖插件
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-webpack',
'karma-sourcemap-loader',
'karma-coverage-istanbul-reporter'
],
// 怎么显示测试结果 测试结果显示插件https://npmjs.org/browse/keyword/karma-reporter
reporters: ['coverage-istanbul'],
// 配置覆盖率报告的查看方式配置
coverageIstanbulReporter: {
// 可以用什么形式展示 支持以下格式:clover、cobertura、html、json-summary、json、lcov、lcovonly、none、teamcity、text-lcov、text-summary、text
// 可以看连接 : https://github.com/istanbuljs/istanbul-reports/tree/590e6b0089f67b723a1fdf57bc7ccc080ff189d7/lib
reports: ['html', 'text-summary'],
// 结果存放的位置
dir: 'coverage/',
// 如果使用webpack和预加载器,可以绕过webpack打破源路径
fixWebpackSourcePaths: true,
// 停止输出消息,如`File [$ {filename}]忽略,没有任何东西可以映射
skipFilesWithNoCoverage: true,
// 大多数记录接受额外的配置选项。 你可以通过`report-config`选项传递这些
'report-config': {
// 配置html
html: {
// 输出到 ./coverage/html
subdir: 'html'
}
}
},
// 运行的服务端口,可以自己修改
port: 9876,
// 在输出中启用/禁用颜色(记录(reporters)和日志(logs)) 肯定需要看到运行的结果,不然出错了也不好调试
colors: true,
// 显示日志记录的级别 (默认就好)
// 可能的值: config.LOG_DISABLE (禁用) || config.LOG_ERROR (错误) || config.LOG_WARN (警告)|| config.LOG_INFO (信息)|| config.LOG_DEBUG (调试)
logLevel: config.LOG_INFO,
// 每当任何测试文件更改时,启用/禁用监听文件并执行测试 这就是第6步
autoWatch: true,
// 可以启动的浏览器列表 需要去下载对应的启动插件 https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// 持续集成模式 如果是,Karma启动浏览器,运行测试并退出 默认就好,设true你会后悔的。
singleRun: false,
// 并发级别 可以同时启动多少浏览器 默认无限大
concurrency: Infinity
})
}

istanbul的介绍

istanbul是一个单元测试代码覆盖率检查工具,可以很直观地告诉我们,单元测试对代码的控制程度。

覆盖率收集工具 nyc,是覆盖率收集工具 istanbul 的命令行版本,istanbul 支持生成各种格式的覆盖率报告。在 package.json 增加 nyc 的配置,告诉 nyc 该忽略哪些文件。

DOM交互单元测试

参考资料
Karma+Jasmine+istanbul+webpack自动化单元测试
《浏览器端测试:mocha,chai,phantomjs》
《测试用例:supertest》

javascript CI篇
测试框架 Mocha 实例教程
karma 测试框架的前世今生
Mocha+Chai+Istanbul单元测试
TypeScript 教程 单元测试

本文标题:前端工程化之一:常见的单元测试工具

文章作者:zhyjor

发布时间:2017年11月09日 - 17:11

最后更新:2023年10月11日 - 02:10

原始链接:https://zhyjor.github.io/2017/11/09/前端工程化之一:常见的单元测试工具/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

🐶 您的支持将鼓励我继续创作 🐶

热评文章