目的
使用karma和jasmine来配置自动化的js单元测试。
Karma和Jasmine
Karma是由Angular团队所开发的一种自动化测试工具。链接:http://karma-runner.github.io/
Karma会启动PhantomJS实例来运行测试,可以在其上使用Jasmine、Mocha等测试框架,也可以和Jenkins、Travis等CI(Continuous Integration,持续集成)进行整合。
Jasmine是一个按照BDD(behavior-driven development,行为驱动开发)思想开发的js测试框架,很适合做单元测试。链接:http://jasmine.github.io/
Karma为Jasmine提供了真实的浏览器环境,两者结合来做js单元测试非常方便。
安装和配置Karma
使用npm安装Karma:
npm install karma --save-dev
创建config文件:
node_modules/karma/bin/karma init [karma.config.js]
创建过程中需要进行各种配置,我们直接来看看生成的karma.config.js文件中的一些字段:
frameworks: ['jasmine'], // 单元测试框架,这里我们使用jasmine files: [ './src/*.js', './client-tests/*.js'], // 需要包含的文件,包括测试的目标代码和测试代码 preprocessors: {'./static/src/*.js': 'coverage',}, // 预处理器,包括eslint、browserify、babel等等,这里我们使用了karma-coverage来生成代码覆盖率报告 reporters: ['progress', 'coverage'], // 报告,除了默认的progress报告测试进度,这里我们添加了karma-coverage port: 9876, // 端口,karma会在localhost:[端口]启动一个测试服务器,这样我们可以用其他设备访问这个页面,得到更真实的设备测试结果 browsers: ['Chrome'], // 目标浏览器 singleRun: true, // 当singleRun为true时,测试完成后测试服务器和浏览器即被关闭 coverageReporter: {type : 'html',dir : 'coverage/'} // 这边是karma-coverage的配置
测试服务器使用了socket,Karma会监视目标js,当文件发生改变时后会实时更新浏览器端刷新测试结果。
启动karma:
node_modules/karma/bin/karma start karma.config.js
除了Karma之外,可能还需要用npm安装以下包:
测试框架相关:jasmine-core,karma-jasmine... 浏览器相关:karma-chrome-launcher... 其他插件(代码覆盖率等等):karma-coverage...
使用jasmine:
首先简单介绍几个概念:
bdd:行为驱动开发是一种敏捷开发的思维,其特点是在实际开发前先用语义化的测试案例来描述代码的作用、行为,再编写代码实现目标。 suits:测试套件。一个或多个测试案例组成一个测试套件,来测试一系列相关的行为。测试套件也可以嵌套测试套件。 specs:测试案例。测试的基本单位,一个测试案例通常用以测试一个行为。一个测试案例应当包含一个或多个期望。
用jasmine来编写就是:
describe("A suite", function() { // describe定义一个测试套件 it("contains spec with an expectation", function() { // it定义一个测试案例 expect(true).toBe(true); // expect定义一个期望 }); });
将以上内容保存到karma.config指定的测试代码文件夹中,运行Karma,会报告我们定义了一个测试,通过了一个测试。
我们还可以在一个测试套件中使用beforeEach、afterEach、beforeAll和afterAll来指定每个测试案例或测试套件的前后所执行的代码来重置测试上下文:
describe("A spec using beforeEach and afterEach", function() { var foo = 0; beforeEach(function() { foo += 1; }); afterEach(function() { foo = 0; }); it("is just a function, so it can contain any code", function() { expect(foo).toEqual(1); }); it("can have more than one expectation", function() { expect(foo).toEqual(1); expect(true).toEqual(true); }); });
jasmine同时提供了spies的功能。spy是对函数调用的跟踪记录。
describe("A spy", function() { var foo, bar = null; beforeEach(function() { foo = { setBar: function(value) { bar = value; } }; // 使用spies spyOn(foo, 'setBar'); foo.setBar(123); foo.setBar(456, 'another param'); }); it("tracks that the spy was called", function() { expect(foo.setBar).toHaveBeenCalled(); }); it("tracks all the arguments of its calls", function() { expect(foo.setBar).toHaveBeenCalledWith(123); expect(foo.setBar).toHaveBeenCalledWith(456, 'another param'); }); it("stops all execution on a function", function() { expect(bar).toBeNull(); }); });
当然还有对异步的支持:
// 使用done来支持异步describe("long asynchronous specs", function() { beforeEach(function(done) { done(); }, 1000); it("takes a long time", function(done) { setTimeout(function() { done(); }, 9000); }, 10000); afterEach(function(done) { done(); }, 1000); });
小结
使用Karma+jasmine可以方便的进行单元测试、BDD开发和持续集成。正确的应用这些开发理念,可以加快开发,减少错误,让我们在开发过程中更自信、更愉快。