17
2013
06

Javascript单元测试框架Jasmine的扩展封装

Jasmine是一个很好的前端单元测试框架,之前也用Jasmine和Qunit进行了一个比较。但Jasmine的异步测试虽然比较灵活,但还是多少有些麻烦,如果我们的这类异步测试比较多,那么重复代码也就上升了,为了代码的质量我们选择封装一下,让它拥有和Qunit一样方便的异步测试调用。先看啊可能整个代码需要这样:

describe("Asynchronous specs", function() {
  var value, flag;
                          
  it("should support async execution of test preparation and exepectations", function() {
                          
    /**
     Specs are written by defining a set of blocks with calls to `runs`, which usually finish with an asynchronous call.
     */
    runs(function() {
      flag = false;
      value = 0;
                          
      setTimeout(function() {
        flag = true;
      }, 500);
    });
                          
    /**
     The `waitsFor` block takes a latch function, a failure message, and a timeout.
                          
     The latch function polls until it returns true or the timeout expires, whichever comes first. If the timeout expires, the spec fails with the error message.
     */
    waitsFor(function() {
      value++;
      return flag;
    }, "The Value should be incremented", 750);
                          
    /**
     Once the asynchronous conditions have been met, another `runs` block defines final test behavior. This is usually expectations based on state after the asynch call returns.
     */
    runs(function() {
      expect(value).toBeGreaterThan(0);
    });
  });
});

对方法封装后我们需要的是这样:

describe("Asynchronous specs", function () {
    var value;
              
    it("should support async execution of test preparation and exepectations", function () {
        value = 0;
        stop();
        setTimeout(function () {
            start();
            expect(value).toBeGreaterThan(0);
        }, 500);
    });
                  
    //或者这样
    asyncTest("should support async execution of test preparation and exepectations", function () {
        value = 0;
        setTimeout(function () {
            start();
            expect(value).toBeGreaterThan(0);
        }, 500);
    });
});

这样看上去整洁很多,那么看看我们如何封装这个异步测试方法吧。

jasmine.extendAsync = (function (){
    var _flag = true;
    return {
        start: function() {
            _flag = true;
        },
        stop: function(optionalTimeoutMessage, optionalTimeout) {
            var timeoutMessage = null,
                timeout = null;
            
            _flag = false;
            
            for (var i = 0; i < arguments.length; i++) {
                var arg = arguments[i];
                switch (typeof arg) {
                case 'string':
                    timeoutMessage = arg;
                    break;
                case 'number':
                    timeout = arg;
                    break;
                }
            }
            
            waitsFor(function() {
                return _flag;
            }, timeoutMessage || 'execute timeout.', timeout || jasmine.getEnv().defaultTimeoutInterval);
        },
        asyncTest: function(desc, func) {
            var _this = this;
            jasmine.getEnv().it(desc, function () {
                _this.stop(desc);
                func.call();
            });
        }
    };
}());
            
jasmine.extendExecute = (function (){
    var _flag= false;
    return {
        isExecuted: function () {
            return _flag;
        },
        execute: function() {
            if (!_flag) {
                jasmine.getEnv().execute();
                _flag = true;
            }
        }
    };
}());
            
var stop = jasmine.extendAsync.stop;
jasmine.stop = stop;
            
var start = function() {
    if(jasmine.extendExecute.isExecuted()) {
        jasmine.extendAsync.start(); 
    }else {
        jasmine.extendExecute.execute();
    }
};
jasmine.start = start;
            
var asyncTest = jasmine.extendAsync.asyncTest;
jasmine.asyncTest = asyncTest;

jasmine.extendExecute赋予到start方法是为了初始化Jasmine的时候直接用start(); 例如我们如果用RequireJs,那么他的测试如何就应该这样开始。

require(testModules.URLs, jasmine.start)。

当然这里的异步封装主要还是用来测试RequireJS模块之间调用的,而对于真正Ajax的测试我觉得需要要到它。这个后面我以后再分享。

« 上一篇下一篇 »

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。