jiayisheji / blog

没事写写文章,喜欢的话请点star,想订阅点watch,千万别fork!

Home Page:https://jiayisheji.github.io/blog/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Karma+Jasmine+istanbul+webpack自动化单元测试

jiayisheji opened this issue · comments

commented

Karma+Jasmine+istanbul+webpack自动化单元测试

前言

一直用别人配置好的东西,经常看别人写教程来写简单的单元测试,闲来无事自己也来撸个配置玩玩。说干就干,从开始到运行成功差不多5个小时。遇到各种问题,主要是各种模块的配置版本问题。

简单介绍一下要用到东西是什么

Karma的介绍

Karma是Testacular的新名字,在2012年google开源了Testacular,2013年Testacular改名为Karma。Karma是一个让人感到非常神秘的名字,表示佛教中的缘分,因果报应,比Cassandra这种名字更让人猜不透!

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

Jasmine的介绍

Jasmine是单元测试框架,我将用Karma让Jasmine测试自动化完成。jasmine提出行为驱动【BDD(Behavior Driven Development)】,测试先行理念,Jasmine的官网

istanbul的介绍

istanbul是一个单元测试代码覆盖率检查工具,可以很直观地告诉我们,单元测试对代码的控制程度。(ps:这个玩意浪费我好久时间,后面详细说怎么配置)

webpack的介绍

webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成少量的 bundle - 通常只有一个,由浏览器加载。(引用webpack中文网介绍

构建Test工程,开始新生上路

  1. 创建一个文件test-demo

  2. 进入test-demo,在当前文件夹里打开命令行,输入npm init -y;
    image

  3. 自动生成package.json文件。
    image

ps: 我的环境:nodejs v8.2.1 npm v5.3.0

commented

安装相关依赖

安装Karma

npm install karma -g

并且还有安装项目中使用

npm install karma  --save-dev

需要全局安装,可以使用命令行。
安装完成以后,命令行输入 karma start
image

在浏览器输入http://localhost:9876/
image

如果出现以上信息,表示karma已经安装成功。

Karma配置

初始化karma配置文件karma.conf.js

ctrl+c 结束刚才启动的Karma

在命令行输入karma init

image

接下就是一段询问关于配置的问题。(ps:karma.conf.js配置可以自己修改,这里是快速生成配置)

  1. Which testing framework do you want to use ?(你想要使用哪个测试框架?)
    默认是jasmine。(如果你想用其他可以自己修改),直接回车下一步

  2. Do you want to use Require.js ? (你要使用Require.js吗?)
    This will add Require.js plugin. (这将添加Require.js插件。)
    Press tab to list possible options. Enter to move to the next question. (按选项卡列出可能的选项。 输入转到下一个问题。)
    默认是no。(现在都在使用webpack打包,这也是为什么你肯定奇怪的地方,单元测试为什么要用webpack) ,直接回车下一步

  3. Do you want to capture any browsers automatically ? (你想要在哪些浏览器里面运行)
    Press tab to list possible options. Enter empty string to move to the next question.(和上面一样)
    默认是Chrome。(你可以添加更多浏览器回车就是填写下一个浏览器名称,必须是你电脑安装的浏览器,最好还是去karma.conf.js添加直观一些),直接按2次回车下一步

  4. What is the location of your source and test files ?(测试文件的位置是什么?)
    You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".(你可以使用glob模式,例如。 “js / *.js”或“test / ** / * Spec.js”)
    Enter empty string to move to the next question.(输入空字符串移动到下一个问题。)
    默认是空,这个是配置你的单元测试用例的文件,根据自己项目和喜好,你可以把测试用例文件和当前被文件放在一起,例如angular-cli就是这样的。也可以单独分离放到test文件下,github大量的npm包都是这样的。我这里就学angular-cli做法,填写:src/**/*.spec.js,就是说scr文件夹下的所有.spec.js后缀都是t测试用例文件。回车下一步
    image
    你写了这样一定会跟我报错,
    image
    需要去如图新建随意.spec.js后缀文件,

如果不想建,可以直接下一步,等会到karma.conf.js修改。

  1. Should any of the files included by the previous patterns be excluded ?(是否应排除某些包含的任何文件?)
    You can use glob patterns, eg. "/*.swp". (您可以使用glob模式,例如。“/*.SWP”。)
    这是为了性能优化,排除那些文件不需要去监听,加快运行速度。如果你不确定要排除哪些文件,可以去karma.conf.js修改。我就直接直接下一步了。

  2. Do you want Karma to watch all the files and run the tests on change ? (你想要Karma来监听所有的文件,并在变化中运行测试吗?)
    Press tab to list possible options. (按选项卡列出可能的选项。)
    默认yes,它的意思你写完了.spec.js后缀文件会自动运行测试,等我们把Karma跑起来,在自动运行。
    这里no。

image
这就生成出来了配置
找一款你顺手的编辑器打开它,(我的用vscode)
image
一大堆看不懂的东西,我给它们一一注释一下;
image

接下来就说关于依赖插件plugins

  1. 需要可以打开Chrome浏览器的插件 npm install karma-chrome-launcher --save-dev
  2. 需要可以运行jasmine的插件 npm install karma-jasmine --save-dev
  3. 需要可以运行webpack的插件 npm install karma-webpack --save-dev
  4. 需要可以显示sourcemap的插件 npm install karma-sourcemap-loader --save-dev
  5. 需要可以显示测试代码覆盖率的插件 npm install karma-coverage-istanbul-reporter --save-dev

插件就先安装这么多,后面需要在安装,可以这样一起安装:

npm install karma-chrome-launcher karma-jasmine karma-webpack karma-sourcemap-loader karma-coverage-istanbul-reporter  --save-dev

把插件写到配置里面去
image

我们先只需要前2个,后面注释起来,让karma能随时跑起来。
image
然后去package.json 配置一个npm命令,编辑器或者ide可以直接运行npm命令。
image
我们karma可以运行起来,karma配置先就到这里。

commented

安装Jasmine

并且还有安装项目中使用

npm install jasmine-core  --save-dev

在安装的过程我们可以去看看jasmine文档

jasmine 5个核心

  1. describe块称为"测试套件"(test suite),表示一组相关的测试。它是一个函数,第一个参数是测试套件的名称("index.js的测试"),第二个参数是一个实际执行的函数。

  2. it块称为"测试用例"(test case),表示一个单独的测试,是测试的最小单位。它也是一个函数,第一个参数是测试用例的名称("1应该是数字"),第二个参数是一个实际执行的函数。

  3. expect是解析一段代码,返回解析后的值。

  4. 匹配器,jasmine内置了很多匹配器,例如:toBe 、not.toBe等,也可以自定义匹配器。

  5. 钩子函数,为了减少重复性的代码,jasmine提供了beforeEach、afterEach、beforeAll、afterAll方法。

  • beforeEach() :在describe函数中每个Spec执行之前执行;
  • afterEach() :在describe函数中每个Spec执行之后执行;
  • beforeAll() :在describe函数中所有的Specs执行之前执行,且只执行一次
  • afterAll () : 在describe函数中所有的Specs执行之后执行,且只执行一次

看了文档我们去写一个简单测试用例。
image

这个例子非常简单,1+1===2;
image

因为我们的测试示例写的是对的,所以没有任何错误提示。

怎么看运行结果,karma会自动打开一个谷歌浏览器
image
点击后一片空白
image
打开控制台(F12)
image
可以看到输出结果。非常ok

接下来我们加一个1+1===3,这个按正常来说是错的,
image

你会发现没有任何提示,因为我们没有安装一些东西,后面来说。现在只能去看karma打开的谷歌浏览器的控制台了。
image

有一个错误提示,说预期2,和匹配结果3不对应。ok没毛病。

简陋版测试已经跑起来了,接下来我们要写自己代码add相加函数

commented

安装Webpack

npm install webpack  --save-dev

注意:Webpack有3个版本,1,2,3每个版本某些写法都有些差别,注意看官方文档,最新版3.5.5。

安装需要时间,这个我们去写个简单的例子,一个简单的add函数。
image

这里用的es6,模块导出,浏览器还不认识,需要用到babel转换。

  1. babel核心文件 npm install babel-core --save-dev
  2. webpack的Loader处理器 npm install babel-loader --save-dev
  3. babel的istanbul覆盖率插件 npm install babel-plugin-istanbul --save-dev
  4. babel转换到哪个版本这里是ES2015 npm install babel-preset-es2015 --save-dev
    插件就先安装这么多,后面需要在安装,可以这样一起安装:
npm install babel-core babel-loader install babel-plugin-istanbul babel-loader babel-preset-es2015  --save-dev

这时候我们代码还是那样,需要去配置karma.conf.js
image

webpack配置就不多做介绍,这里不是webpack教程,也不是一两句可以说完,看教程

因为这里配置比较简单,就直接放在里面。如果复杂就需要单独抽出去做一个配置文件。

ps:它和我们一般项目的配置是有点区别的,webpack有四个核心概念:入口(entry)、输出(output)、loader、插件(plugins)。这里不需要入口(entry)和输出(output)配置。这点需要注意。

还需要打开注释的插件
image

运行一下npm run unit, 没错误继续。一步一个脚印,不要到最后全是错误,放弃了。边写边测试。

测试add函数

  1. add.spec.js引入add.js
import add from './add';
  1. 新增一个测试套件
    image

  2. 运行npm run unit
    image

  3. karma打开的浏览器查看
    image

出问题了,现在浏览器都还不识别import。我们需要用babel转换成ES5显示。
image

我们需要配置preprocessors

我们在运行,打开控制台查看:
image

完美运行

接着继续,我们还需要生成源文件映射的map文件,
修改配置:
image

image

注意:每次修改完karma.conf.js 都需要重新运行npm run unit。运行没有问题,我们接着继续最后一个话题istanbul 代码覆盖率显示。

commented

安装Istanbul

还需要安装Istanbul相关的依赖

  1. webpack的Loader处理器 npm install istanbul-instrumenter-loader --save-dev
  2. 测试覆盖率显示插件 npm install karma-coverage-istanbul-reporter --save-dev

我们先安装他们,然后去修改karma.conf.js
image

先给babel加上插件plugins: ['istanbul']
image

在写上istanbul-instrumenter-loader的配置。
image

注意:这是webpack官方给的例子,注意画红线的,官方给的有问题,这个配置是决定Loader的优先级。
image

添加完成以后,重新运行npm run unit。没问题继续。

image
我们使用coverage-istanbul显示测试结果
image
打开所有插件注释。

image
覆盖率显示配置,看注释说明

image

注意:一定要打开自动监听才有覆盖率显示,

运行以后,就会生成

image

命令行显示

image

文件夹里面显示

怎么测覆盖率(code coverage)

它有四个测量维度。

  • 行覆盖率(line coverage):是否每一行都执行了?
  • 函数覆盖率(function coverage):是否每个函数都调用了?
  • 分支覆盖率(branch coverage):是否每个if代码块都执行了?
  • 语句覆盖率(statement coverage):是否每个语句都执行了?
export default function add(num1, num2) {
    return num1 + num2;
}

我们将这个函数变得复杂点,如果不写num2,就默认是0。

export default function add(num1, num2) {
    if (num2 === undefined) num2 = 0;
    return num1 + num2;
}

image
命令行显示结果

image
浏览器打开 coverage/html/index.html

注意:命令行显示合计测试覆盖率,详细需在浏览器看。

测试结果分析:
1个语句覆盖率(statement coverage)没有覆盖到,1个分支覆盖率(branch coverage)没有覆盖到,1个函数覆盖率(function coverage)已经调用,3行行覆盖率(line coverage)全部覆盖

我们再来个复杂的栗子:

export default function add(num1, num2) {
    if (num1 === undefined) num1 = 0;
    if (num2 === undefined) num2 = 0;
    return num1 + num2;
}

image
命令行显示结果

image
浏览器打开 coverage/html/index.html

测试结果分析:
2个语句覆盖率(statement coverage)没有覆盖到,2个分支覆盖率(branch coverage)没有覆盖到,1个函数覆盖率(function coverage)已经调用,3行行覆盖率(line coverage)全部覆盖

image
增加测试用例

image

全部覆盖,ok完工。demo

跟着一路走下来,run的很好,大神有没有计划写一下有关 e2e测试的呢?

跟 react / vue 搭配,会更好,或者说大神有没有相关的博客推荐?

commented

@liuxsen 没有计划,angular有 传送门