Karma和Jasmine自动化单元测试

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-karma-jasmine/

karma

前言

在Java领域,Apache, Spring, JBoss 三大社区的开源库,包罗万象,但每个库都在其领域中都鹤立鸡群。而Nodejs中各种各样的开源库,却让人眼花缭乱,不知从何下手。

Nodejs领域: Jasmine做单元测试Karma自动化完成单元测试Grunt启动Karma统一项目管理Yeoman最后封装成一个项目原型模板,npm做nodejs的包依赖管理,bower做javascript的包依赖管理。Java领域:JUnit做单元测试, Maven自动化单元测试,统一项目管理,构建项目原型模板,包依赖管理。

Nodejs让组合变得更丰富,却又在加重我们的学习门槛。我还说不清楚,也看不透!

上面写的有点远了,回到文章的主题,Jasmine+Karma自动化单元测试。

目录

  1. Karma的介绍
  2. Karma的安装
  3. Karma + Jasmine配置
  4. 自动化单元测试
  5. Karma和istanbul代码覆盖率
  6. Karma第一次启动时出现的问题

1. 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是单元测试框架,本单将介绍用Karma让Jasmine测试自动化完成。Jasmine的介绍,请参考文章:jasmine行为驱动,测试先行

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

2. Karma的安装

系统环境:

win7 64bit, node v0.10.5, npm 1.2.19

安装Karma


~ D:\workspace\javascript>mkdir karma
~ D:\workspace\javascript>cd karma
~ D:\workspace\javascript\karma>npm install -g karma

# 测试是否安装成功
~ D:\workspace\javascript\karma>karma start
INFO [karma]: Karma v0.10.2 server started at http://localhost:9876/
INFO [Chrome 28.0.1500 (Windows 7)]: Connected on socket nIlM1yUy6ELMp5ZTN9Ek

从浏览器看到karam界面。

karma1

下面我们要开始配置karam。

3. Karma + Jasmine配置

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


~ D:\workspace\javascript\karma>karma init

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine

Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no

Do you want to capture a browser automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
>

What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
>

Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>

Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes

Config file generated at "D:\workspace\javascript\karma\karma.conf.js".

安装集成包karma-jasmine


~ D:\workspace\javascript\karma>npm install karma-jasmine

4. 自动化单元测试

3步准备工作:

  • 1. 创建源文件:用于实现某种业务逻辑的文件,就是我们平时写的js脚本
  • 2. 创建测试文件:符合jasmineAPI的测试js脚本
  • 3. 修改karma.conf.js配置文件

1). 创建源文件:用于实现某种业务逻辑的文件,就是我们平时写的js脚本
有一个需求,要实现单词倒写的功能。如:”ABCD” ==> “DCBA”


~ vi src.js

function reverse(name){
    return name.split("").reverse().join("");
}

2). 创建测试文件:符合jasmineAPI的测试js脚本


describe("A suite of basic functions", function() {
    it("reverse word",function(){
        expect("DCBA").toEqual(reverse("ABCD"));
    });
});

3). 修改karma.conf.js配置文件
我们这里需要修改:files和exclude变量


module.exports = function (config) {
    config.set({
        basePath: '',
        frameworks: ['jasmine'],
        files: ['*.js'],
        exclude: ['karma.conf.js'],
        reporters: ['progress'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['Chrome'],
        captureTimeout: 60000,
        singleRun: false
    });
};

启动karma
单元测试全自动执行


~ D:\workspace\javascript\karma>karma start karma.conf.js
INFO [karma]: Karma v0.10.2 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
WARN [launcher]: The path should not be quoted.
  Normalized the path to C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
INFO [Chrome 28.0.1500 (Windows 7)]: Connected on socket bVGffDWpc1c7QNdYye_6
INFO [Chrome 28.0.1500 (Windows 7)]: Connected on socket DtTdVbd4ZsgnMQrgye_7
Chrome 28.0.1500 (Windows 7): Executed 1 of 1 SUCCESS (3.473 secs / 0.431 secs)
Chrome 28.0.1500 (Windows 7): Executed 1 of 1 SUCCESS (0.068 secs / 0.021 secs)
TOTAL: 2 SUCCESS

浏览器会自动打开
karma2

我们修改test.js


~ vi test.js

describe("A suite of basic functions", function() {
    it("reverse word",function(){
        expect("DCBA").toEqual(reverse("ABCD"));
        expect("Conan").toEqual(reverse("nano"));
    });
});

由于karma.conf.js配置文件中autoWatch: true, 所以test.js文件保存后,会自动执行单元测试。

执行日志如下:提示我们单元测试出错了。


INFO [watcher]: Changed file "D:/workspace/javascript/karma/test.js".
Chrome 28.0.1500 (Windows 7) A suite of basic functions reverse word FAILED
        Expected 'Conan' to equal 'onan'.
        Error: Expected 'Conan' to equal 'onan'.
            at null. (D:/workspace/javascript/karma/test.js:4:25)
Chrome 28.0.1500 (Windows 7): Executed 1 of 1 (1 FAILED) ERROR (0.3 secs / 0.006 secs)

5. Karma和istanbul代码覆盖率

增加代码覆盖率检查和报告,增加istanbul依赖


~ D:\workspace\javascript\karma>npm install karma-coverage

修改karma.conf.js配置文件


~ vi karma.conf.js

reporters: ['progress','coverage'],
preprocessors : {'src.js': 'coverage'},
coverageReporter: {
    type : 'html',
    dir : 'coverage/'
}

启动karma start,在工程目录下面找到index.html文件,coverage/chrome/index.html

打开后,我们看到代码测试覆盖绿报告
karma3

覆盖率是100%,说明我们完整了测试了src.js的功能。

接下来,我们修改src.js,增加一个if分支


function reverse(name){
    if(name=='AAA') return "BBB";
    return name.split("").reverse().join("");
}

再看覆盖率报告,
karma4

Statements:75%覆盖,Branches:50%覆盖。

为了产品的质量我们要尽量达到更多的覆盖率,一般对于JAVA项目来说,能达到80%就是相当高的标准了。对于Javascript的代码测试及覆盖率研究,我还要做更多的验证。

6. Karma第一次启动时出现的问题

CHROME_BIN的环境变量问题


~ D:\workspace\javascript\karma>karma start karma.conf.js
INFO [karma]: Karma v0.10.2 server started at http://localhost:9876/
INFO [launcher]: Starting browser Chrome
ERROR [launcher]: Cannot start Chrome
        Can not find the binary C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe
        Please set env variable CHROME_BIN

设置方法:找到系统中chrome的安装位置,找到chrome.exe文件


~ D:\workspace\javascript\karma>set CHROME_BIN="C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"

转载请注明出处:
http://blog.fens.me/nodejs-karma-jasmine/

打赏作者

This entry was posted in Javascript语言实践

  • ss

    配置文件中需要引入一个外部的js ‘http://apis.mapabc.com/webapi/auth.json?t=javascriptmap&v=3.1.1&key=ef3bd020f702312e591e771627c57b807ba4c04085c0159d67d8fdcc0f61bb129f3d2a973dfae9a6’, 这种样子的 怎么写呢 发现karma压根没找到

  • 好文!Conan有没有配过karma+jasmine+phantomJs的测试?

  • yangchao

    为什么我在win7下npm install -g karma,但是使用karma命令时 ,即使我使用全路径D:fekarma>D:nodejsnode_moduleskarmabinkarma start 都不行,报不是内部或外部命令,也不是可运行的程序或批处理文件,请指导一下

    • karma包已经升级了,这篇文章有些地方已经不能运行,查官方网站解决吧。

    • coocon

      sudo npm install -g karma-cli, 需要安装它的命令行包

  • Pingback: Nodejs学习路线图 | 粉丝日志()

  • Zimo Zeng

    Hello

    为什么 在karma start karma.conf.js 提示 错误

    ERROR [launcher]: No binary for Chrome browser on your platform.

    Please, set “CHROME_BIN” env variable.

    后 设置了 CHROME_BIN 再重启 依旧报那个错误
    WIN7 系统

    • 我不清楚是不是karma新版本所造成的问题,去查一下官方文档吧。

      • Zimo Zeng

        谢谢 搞定了 配置后 需要 再次重启一下 CMD

  • jsers

    karma可以测试浏览器的多版本吗

    • 浏览器的多版,用js就可以测试,Karma只是一个自动化测试的框架。

      • coder

        安装karma的时候为什么老报这个错:npm WARN optional dep failed, continuing fsevents@0.3.0?

  • coder

    如果要用requireJS 的话 在karma的配置文件里面frameworks: [‘jasmine’, ‘requirejs’],,但是UT 会报这个错误”mismatched anonymous define() module”为什么呢???

    • 文章中Karma和jasmine都是基于node的npm进行模块管理的,不需要requirejs。

      • coder
        • 是你的个人网站l吗?

          • coder

            以前的一个同事的

          • 博客作者出了本JS的书,还是挺牛的!!

          • coder

            嗯嗯,请问下 我现在想写jquery代码的UT,用karma+jasmine+require ,不知道karma-jquery这个东西你有没有了解,可否给点建议。

          • coder

            我用require是想在写UT的时候,处理文件之间的依赖关系。

          • coder

            $(function(){}) 这种方式的UT 不管我如何将jquery引入进去,都会报错:$ is not defined,我该怎么办???

          • 先用传统的方式,整个加载js文件,第二步再使用require重新实现加载器。

          • coder

            我想再问下
            1.在karma的配置文件中 file 这个参数 pattern 的方式引用文件和字符串直接引用有什么不同?
            例如:{pattern: ‘tested/libs/jquery.js’, included: false, served: true},
            和’tested/libs/jquery.js’,
            我还发现这个里面的文件加载还必须按照依赖关系来加载.

          • 1. pattern是通过正则表达式进行匹配,支持?*,|,[]等语法,这样就不用列出所有的文件了。
            2. js在html中加载是有顺序的,如果你用了加载器,它会自动按顺序加载的。
            3. 我没有用过karma-coverage,估计应该差不多。

          • coder

            1.karma配置文件中:
            preprocessors: {
            ‘tested/modules/**/script/*.js’: [‘coverage’]
            },
            不用pattern我这种写法也可以啊,
            2.我这块说的加载是kama配置文件里面files:[]的文件加载
            3.看你本文 5. Karma和istanbul代码覆盖率 汗~~~

          • 1. 你的方式是可以,pattern为了不同人的需求,如果需要排除目录里面的a.js和b.js你怎么写?

            2. 我不确定是否有严格的顺序,如果有依赖关系,按顺序加载是很正常的要求。

            3. 不知道你的“汗”,是好还是不好。文章只是一个用例,不代表项目中就是100%或者50%。越真实的环境,代码往往也会越复杂,而复杂的JS闭包写法,覆盖就会越低。

          • coder

            1.排除不是可以写在 exclude: [],这个参数底下
            3.我的意思是 在本文5 你用了karma-coverage 你却说你没用过,可能是因为时间过去太久了,我’汗’ 只是表示惊讶,并无它意,如有冒犯,I’m so sorry

          • 15个月之前的文章了,确实是太久了。当时网上还没有几个写node程序的做自动化测试或持续集成的。

            不好意思,我也忘的差不多了。

          • coder

            没事,从接触nodeJs开始,您的很多文章对我很有帮助,希望你早日出本书,我一定会买本正版的>.<

          • 多谢支持,Nodejs的书已经提到日程了,希望明年4-5月时可以出版。

          • coder

            上面您提到了闭包对UT的影响,我现在也遇到了这个问题,不知道对于这种问题有什么好的解决方式?

          • 1. 匿名闭包,无法测试。
            2. 闭包运行时scope不确定,写测试有难度。
            3. 通过架构或框架,标准化代码结构,禁止在功能代码中用闭包。

          • coder

            收到,谢谢您的建议,希望和你有更多的交流,谢谢。
            预祝你的nodeJs能顺利上市,大获成功

          • 🙂

          • coder

            丹哥,我还有个问题想请教下,既然nodeJS是javascript的执行环境,为什么karma执行jasmine的测试用例和监控网文件变化的时候借助浏览器,直接在node的环境下不行吗?

          • 1. nodejs和浏览器是两个不同的运行环境

            2. Nodejs代码的自动测试在nodejs环境中,浏览器中js代码的自动测试在浏览器环境中。

            3. 如果你的代码,需要同时支持两种环境,需要分别在两个环境中都进行测试。

          • coder

            那karma+jasmine的测试代码为什么不直接跑在nodeJS中,而要拉上浏览器。

          • 本文给的例子是基于浏览器的,你同样可以在nodejs中运行,看你自己的需求是什么了。

          • coder

            grunt-contrib-jasmine+ phantomJS

          • 不清楚karma-jquery,我已经放弃jquery转向angularjs了。

  • ice cream

    请问,测试结果能够保存吗?保存成文档或者HTML方式。

  • damon

    安照你说的步骤:在第2部 (2. Karma的安装)
    这是打开 http://localhost:9876/
    会报错:
    You need to include some adapter that implements __karma__.start method。

    如果将第3步(3. Karma + Jasmine配置)提前到
    # 测试是否安装成功
    ~ D:workspacejavascriptkarma>karma start
    INFO [karma]: Karma v0.10.2 server started at http://localhost:9876/
    INFO [Chrome 28.0.1500 (Windows 7)]: Connected on socket nIlM1yUy6ELMp5ZTN9Ek

    之前就不会报错了。

  • damon

    在第4步:
    4. 自动化单元测试
    3). 修改karma.conf.js配置文件

    应加上
    plugins: [
    ‘karma-chrome-launcher’,
    ‘karma-jasmine’
    ],
    否则会出现这样的 warn
    WARN [launcher]: Can not load “Chrome”, it is not registered!
    Perhaps you are missing some plugin?
    而且 chrome浏览器也不会自动打开

    • 估计是karma升级的原因吧,文章是1年半之前写的了,需要对应查看官方文档。

  • lioff

    karma 启动的浏览器窗口 只是用来运行 浏览器端 js … 其实可以像jasmine 那样直接把测试结果输出在同一运行窗口里面这样 又直观又避免另外安装html report 插件

    • 是的,只是有些情况要在浏览器里运行。

  • joker

    你好,想请教一下,当我用jasmine测试我的前端代码的时候是否真正生成了这个界面?举例解释一下:如果我的方法的结果是弹出了一个弹出框,那我的测试案例中可以通过 document.getElementById(“xxx”) 这种方法来获取节点并断言吗?

    • jasmine只是测试框架,你自己定义好input,output就可以使用。dom节点,只有在浏览器中才有。