使用 Jasmine 测试 Node 项目

在上一篇文章(Jasmine Introdunction)中,我们已经介绍了如何在浏览器中运行 Jasmine 测试框架。对于浏览器端的 JS 代码来说,这无疑是很方便的。那么 Jasmine 能否用来对服务端的代码进行测试呢?答案当然是可以。本文中,我们就将介绍如何在基于 Node 的项目中,方便快捷地运行 Jasmine 测试。
 
同上篇文章一样,我们依旧新建一个待测试的 JS 文件 js/Hello.js
function Hello() {};

Hello.prototype.foo = "foo";
Hello.prototype.bar = null    ;

Hello.prototype.helloWorld = function() {
    return "Hello World!";
}

Hello.prototype.helloSomeone = function(toGreet) {
    return this.sayHello() + " " + toGreet;
}

Hello.prototype.sayHello = function() {
    return "Hello";
}

module.exports = Hello;
View Code

 

 
安装 Jasmine Module
首先,使用 npm 全局安装 jasmine 模块:
npm install -g jasmine
 
进行全局安装后,我们就可以直接在终端执行 jasmine 命令了。执行:
jasmine -v
就可以看到当前安装的 jasmine 版本。这里我安装的版本为 jasmine v2.4.1。
 
初始化
接下来,我们就需要对测试项目进行初始化了。我们可以手动进行初始化,但更简单的方式是直接在项目目录下运行命令:
jasmine init
  
jasmine 会在当前目录下生成一个配置文件 spec/support/jasmine.json
{
  "spec_dir": "spec",
  "spec_files": [
    "**/*[sS]pec.js"
  ],
  "helpers": [
    "helpers/**/*.js"
  ],
  "stopSpecOnExpectationFailure": false,
  "random": false
}
其中    spec_dir: 指定扫描测试文件的根目录
          spec_files: 匹配测试文件的表达式
          helpers: Helper 文件会在所有的 spec 之前预先执行
          stopSpecOnExpectationFailure: 当有错误出现时是否终止所有测试
          random: 是否打乱测试顺序
 
 
添加测试代码
接下来,就该添加我们的测试代码了。分别添加 spec/Hello.spec.js
describe("Hello", function () {
    var Hello = require("../js/Hello");
    var hello;

    beforeEach(function () {
        hello = new Hello();
    });

    it("a newly created Hello instance should not be the same instance with the origin one", function () {
        expect(hello).not.toBe(new Hello());
        expect(hello).toEqual(new Hello());
    });

    describe("helloWorld function", function () {
        it("should return hello statement", function () {
            expect(hello.helloWorld()).toBe("Hello World!");
        });

        it("should contain word 'World'", function () {
            expect(hello.helloWorld()).toContainWord("World!");
        });

        it("an undefined variable should pass 'toBeUndefined' matcher", function () {
            expect(hello.a).toBeUndefined();
        });

        it("a null variable should pass 'toBeNull' matcher", function () {
            expect(hello.bar).toBeNull();
        });

        it("variable after boolean casting should pass 'toBeTruthy' 'toBeFalsy' matcher", function () {
            expect(hello.foo).toBeTruthy();
            expect(hello.bar).toBeFalsy();
        });
        it("should pass the 'toMatch' matcher for regular expressions", function (){
            expect(hello.helloWorld()).toMatch(/^\w*\s\w*!$/);
        });
    });

    describe("helloSomeone function", function () {
        it("should calls the sayHello() function", function () {
            spyOn(hello, "sayHello");
            hello.helloSomeone("Chou");
            expect(hello.sayHello).toHaveBeenCalled();
            expect(hello.sayHello).toHaveBeenCalledTimes(1);
        });
        it("should greet the 'World'", function () {
            spyOn(hello, "helloSomeone");
            hello.helloSomeone("World");
            expect(hello.helloSomeone).toHaveBeenCalledWith("World");
            expect(hello.helloSomeone).not.toHaveBeenCalledWith("world");
        });
        it("should calls the fake sayHello()", function () {
            hello.sayHello = jasmine.createSpy("'sayHello' spy");
            hello.helloSomeone("world");
            expect(hello.sayHello).toHaveBeenCalled();
        });
    });
});
View Code
spec/helpers/SpecHelper.js
beforeEach(function () {
    jasmine.addMatchers({
        toContainWord: function () {
            return {
                compare: function (actual, expected) {
                    var result = {};
                    result.pass = (actual.indexOf(expected) !== -1);
                    if( result.pass ) {
                        result.message = "Expected " + actual + " to contain " + expected + ".";
                    } else {
                        result.message = "Expected " + actual + " to contain " + expected + ", but it does not.";
                    }
                    return result;
                }
            }
        }
    });
});
View Code
(若对测试代码有疑问,请移步 Jasmine Introdunction)
 
 
运行测试
当我们添加了测试代码,并且配置好了配置文件 jasmine.json ,就可以回到根目录下,直接执行命令:
jasmine
 
就可以看到我们的 10 个测试用例全部顺利通过了。不过每个通过的测试,只是由一个绿色的点表示。很多时候,我们都希望能够看到全部的测试用例,以及不同测试用例之间的层级关系,仅是一个绿色的小点并不利于我们进行调试。这里我们再介绍一个模块: jasmine-spec-reporter 能够很好地解决这个问题。
 
首先,执行如下命令在本地安装 jasmine 和 jasmine-spec-reporter
npm install jasmine --save-dev
npm install jasmine-spec-reporter --save-dev
 
然后在项目根目录,添加 jasmine-runner.js
var Jasmine = require('jasmine');
var SpecReporter = require('jasmine-spec-reporter');
var noop = function() {};

var jrunner = new Jasmine();
jrunner.configureDefaultReporter({print: noop});    // remove default reporter logs
jasmine.getEnv().addReporter(new SpecReporter());   // add jasmine-spec-reporter
jrunner.loadConfigFile();                           // load jasmine.json configuration
jrunner.execute();
View Code
这段代码展示了在没有全局安装 jasmine 时,如何通过调用 library 来使用 jasmine 测试框架测试我们的代码。
运行命令:
node jasmine-runner.js
  
现在的输出是否更清晰明了了呢~
 
到目前为止,我们已经介绍了如何使用 Jasmine 测试框架来对 Node 项目进行测试。希望本文能对你有所帮助。如果你觉得本文有任何问题,还望不吝赐教。
 
 
 
 
posted @ 2016-03-30 18:39  赵小吉  阅读(3566)  评论(1编辑  收藏  举报