Karma + Jasmine 构建 Web 测试环境

Karma-Jasmine-构建-Web-测试环境

Posted by cl9000 on March 18, 2018

Karma + Jasmine 构建 Web 测试环境

Jasmine 简介


Jasmine 是一款 JavaScript BDD(行为驱动开发)测试框架,它不依赖于其他任何 JavaScript 组件。它有干净清晰的语法,让您可以很简单的写出测试代码。
它的主要特点:

Karma 简介

  • Karma是Testacular的新名字,在2012年google开源了Testacular,2013年Testacular改名为Karma。
  • Karma是一个基于Node.js的JavaScript测试执行过程管理工具(Test Runner)。该工具可用于测试所有主流 Web 浏览器,也可以集成到 CI(Continuous integration)工具,还可以和其他代码编辑器一起使用。
  • Karma的主要目的是使您的测试驱动开发变得容易,快速和有趣。
  • Karma不是测试框架,也不是断言库。Karma只是启动HTTP服务器,并生成您可能已经从最喜欢的测试框架中了解的测试运行器HTML文件。因此,出于测试目的,您可以使用几乎任何您喜欢的东西。大多数常见测试框架已经有插件:

Karma 安装

在项目中建议使用项目独立的 node_modules,包括上面的安装其它的依赖,这有利于迁移。
Mac安装命令(i 是 install 命令的缩写,-D 是 --save-dev 的缩写。)
// 局部(单项目)安装。安装 Karma 命令到当前 node_modules 目录下,此时,如果需要执行 karma 命令,就需要这样 $ ./node_modules/.bin/karma
$ npm install karma --save-dev
// 全局安装 - Mac安装路径:/usr/local/bin/node
$ nom install karma -g
测试是否安装成功 $ karma start ,成功会出现提示打开浏览器 http://localhost:9876/ 访问成功页面。

Karma 初始化配置

安装完成之后,切换到目标项目根目录,运行:
$ karma init or $ karma init **.conf.js
执行命令后,会被问到一系列的问题

  • What testing framework do you want to use?
    默认情况下 Jasmine, Mocha, QUnit 都已经被安装了,这里我们可以直接使用它们的名称。如果在应用中用到了其它的测试框架,那就需要我们安装它们所对应的插件,并在配置文件中标注它们(详见 karma.conf.js 中的 plugins 项)
  • Do you want to use Require.js?
    This will add Require.js plugin.
    Require.js 是异步加载规范(AMD)的实现。常被作为基础代码库,应用在了很多的项目与框架之中,例如 Dojo, AngularJs 等、
  • Do you want to capture a browser automatically?
    选择需要运行测试用例的浏览器。需要注意的就是,必须保证所对应的浏览器插件已经安装成功。
  • What is the location of your source and test files?
    You can use glob patterns, eg. js/*.js" or "test/**/*Spec.js.
    选择测试用例所在的目录位置。Karma 支持通配符的方式配置文件或目录,例如 js/*.js" or "test/**/*Spec.js 等。如果目录或文件使用相对位置,要清楚地是,此时的路径是相对于当前运行 karma 命令时所在的目录。
  • Should any of the files included by the previous patterns be excluded?
    You can use glob patterns, eg. **/*.swp.
    目录中不包括的那些文件。
  • Do you want Karma to watch all the files and run tests on change?
    是否需要 Karma 自动监听文件?并且文件一旦被修改,就重新运行测试用例?

最终 Karma 生成如下的配置文件 karma.conf.js,如下:

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
94
95
96
97
98
99
100
101
102
// Karma configuration
// Generated on Wed Mar 18 2018 14:36:01 GMT+0800 (GMT+08:00)

module.exports = function(config) {
config.set({

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',


// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],


// list of files / patterns to load in the browser
files: [
"test/**/*.js",
"test/**/*Spec.js",
// {
// pattern: 'test/**/*.js',
// // false 表示初始化的时候不会使用 script 标签直接将相关 js 引入到浏览器,需要自己写代码加载
// included: false
// },
// {
// pattern: 'test/**/*Spec.js',
// included: false
// }
],


// list of files / patterns to exclude
exclude: [
],


// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {'test/**/*.js': 'coverage' },


// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],


// 覆盖率报告器配置
coverageReporter: {
type: 'html',
dir: 'coverage/'
},


// web server port
port: 9876,


// enable / disable colors in the output (reporters and logs)
colors: true,


// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,


// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,


// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
// - Chrome, ChromeCanary, Firefox, Opera, Safari (only Mac), PhantomJS,
// IE (only Windows)
browsers: ['Chrome'],


// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,

// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity


// 参考其他配置
// will be resolved to basePath (in the same way as files/exclude patterns)
junitReporter: {outputFile: 'test-results.xml'},

// If browser does not capture in given timeout [ms], kill it
captureTimeout: 20000,

// report which specs are slower than 500ms
reportSlowerThan: 500,

plugins: [
'karma-jasmine'
]
})
}

Karma + Jasminae 自动化单元测试

测试项目 Karma-test 目录为:

1
2
3
4
5
6
7
Karma-test
- corverage (此目录会在后面覆盖率自动生成,暂忽略)
- ...
- test
- index.js
- indexSpec.js
- karma.conf.js
  1. 创建源文件(**.js 例:index.js):用于实现某种业务逻辑的文件,平时写的js脚本;
    index.js 实现一个求和运算:
1
2
3
function add(number) {
return number + 1;
}
  1. 创建测试文件(**Spec.js 例:indexSpec.js):符合 JasmineAPI 的测试JS脚本;
    indexSpec.js 中实现测试结果:
1
2
3
4
5
describe("test add function", function () {
it("test function", function () {
expect(add(1)).toBe(2);    // add(1)是index.js中的方法,toBe(2)是期望的结果。
});
});
  1. 修改 karma.conf.js 配置文件;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 基本片段,以初始化生成为准
module.exports = function (config) {
config.set({

preprocessors: {'test/**/*.js': 'coverage' },
reporters: ['progress', 'coverage'],
// 覆盖率报告器配置
coverageReporter: {
type: 'html',
dir: 'coverage/'
},

});
};
  1. 启动karma 单元测试全自动执行
    $ karma start karma.conf.js OR $ karma start karma.conf.js --log-level debug --single-run // 此时,Karma 会自动打开浏览器,并运行相应的测试用例,而执行结果会输出到控制台。
    输出如下:
1
2
3
4
5
6
7
8
9
*****deMacBook-Pro:Karma-test *****$ karma start karma.conf.js
18 03 16:55:08.978:WARN [filelist]: All files matched by "/Users/weichanglu/Desktop/Karma-test/test/**/*Spec.js" were excluded or matched by prior matchers.
18 03 16:55:09.111:WARN [karma]: No captured browser, open http://localhost:9876/
18 03 16:55:09.167:INFO [karma-server]: Karma v4.4.1 server started at http://0.0.0.0:9876/
18 03 16:55:09.167:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
18 03 16:55:09.181:INFO [launcher]: Starting browser Chrome
18 03 16:55:12.770:INFO [Chrome 79.0.3945 (Mac OS X 10.15.1)]: Connected on socket fNwvZpUHRXSnHHXsAAAA with id 33904973
Chrome 79.0.3945 (Mac OS X 10.15.1): Executed 1 of 1 SUCCESS (0.005 secs / 0.001 secs)
TOTAL: 1 SUCCESS

浏览器会自动打开页面,内容如下;

1
2
3
Karma v4.4.1 - connected                                              DEBUG

Chrome 79.0.3945 (Mac OS X 10.15.1) is idle
  1. 调试及其他
    很多时候,我们只想要运行某一个suite中的所有测试用例,而不是整个工程,比如在Jasmine中:
1
2
3
4
5
describe("test sum function", function () {
it("test function", function () {
expect(sum(1)).toBe(2);    //sum(1)是index.js中的方法,toBe(2)是期望的结果。
});
});

只需要将 describe 修改为 ddescribe 即可,类似的,如果只需要运行某一个测试用例,只需要将 it 修改为 iit 即可。
另外,Karma还提供了debugger功能,在测试用例中加入: debugger;
由于在运行时,karma实际上会启动一个真实地浏览器,所以可以在浏览器的developer-tool中进行实际的调试。需要注意的是,当进入调试模式时,需要启动developer-tool(在Karma启动的那个浏览器窗口中)。

通过修改验证测试结果文件 indexSpec.js 进行测试即可,由于karma.conf.js配置文件中 autoWatch: true , indexSpec.js 文件保存后,会自动执行单元测试。
查看执行日志,验证测试结果:

  1. 终端日志
  2. 浏览器F12开发者模式

Karma 代码覆盖率

  1. 需要安装依赖 karma-coverage 命令:$ npm install karma-coverage --save-dev,还是建议安装到项目目录中,以便于迁移。
  2. 修改karma.conf.js配置文件
1
2
3
4
5
6
7
8
9
reporters: ['progress', 'coverage'],

preprocessors: {'test/**/*.js': 'coverage' },

// 覆盖率报告器配置
coverageReporter: {
type: 'html',
dir: 'coverage/'
},
  1. 启动 karma start karma.conf.js ,会在项目根目录下生成 coverage 目录,在其下面找到index.html文件(coverage/chrome/index.html),浏览器打开,便看到代码测试覆盖绿报告。
    通过修改业务代码(index.js),来观测覆盖率变化。
    为了产品的质量要尽量达到更多的覆盖率,一般对于JAVA项目来说,能达到80%就是相当高的标准了。
1
2
3
4
5
6
7
8
9
All files
100% Statements 4/4100% Branches 0/0100% Functions 3/3100% Lines 4/4
Press n or j to go to the next uncovered block, b, p or k for the previous block.

File Statements Branches Functions Lines
index.js
100% 1/1 100% 0/0 100% 1/1 100% 1/1
indexSpec.js
100% 3/3 100% 0/0 100% 2/2 100% 3/3

测试代码git地址

参考资源

Karma 官网
Jasmine 官网
Karma 官网 plugins 部分
使用 Karma + Jasmine 构建 Web 测试环境
使用Karma运行JavaScript测试
Karma和Jasmine自动化单元测试
karma 测试框架的前世今生
Karma+Jasmine实现自动化单元测试
Karma:1. 集成 Karma 和 Jasmine 进行单元测试
karma 入门
JS测试工具karma及应用
前端单元测试工具——karma安装使用



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!