• javascript单元测试:jasminejs 2.0的烦恼


      前言:

      我属于TDD的拥护者,之前写后端代,都喜欢把一些重要的逻辑代码抽离处理,增加Unit Test。可是最近在接触前端Unit Test时,让自己忍不住想吐槽一下。也顺便实现一下今年的目标(一个月至少一篇技术博客,1月2月我会补上的)。前端测试框架有很多,比较流量的是Qunit和Jasminejs,这两个多单元测试框架的具体区别网上有很多资料,有兴趣大家可以去查一下。我是因为Jasminejs比较丰富的断言、断言扩展、spy、mock这些功能吸引着我。所以首先把jasminejs引入项目中。当时主要引入的是1.3版本。

      最近在学习2.0版本,发现引入2.0版本的jasminejs代码,我的整个Unit Test跑不起来了。尽然不向下兼容?不兼容的问题让我顿时觉得jasminejs有点小儿科的感觉。幸亏做了一些封装,不然我是没办法升级了。

      现在网上关于jasminejs的介绍大多数是针对1.3这个版本,下面是我排查和总结的经验,为自己做个笔记,也和大家分享一下。有错误地方请大家拍砖。

      本文只针对1.3和2.0区别做说明,至于jasminejs详细学习手册建议大家上官网,介绍的很详细。

      jasminejs:http://jasmine.github.io/

      jasminejs github: https://github.com/pivotal/jasmine/

      区别:

      1、calls区别:

      测试代码:

    describe("对spy函数的测试", function() {
    
             var foo, bar = null;
    
     
    
             beforeEach(function() {
    
                  foo = {
    
                       setBar: function(value) {
    
                           bar = value;
    
                       }
    
                  };
    
     
    
                  spyOn(foo, 'setBar'); //foo为spy函数
    
     
    
                  foo.setBar(123);
    
                  foo.setBar(456, 'another param');
    
             });
    
     
    
             it("上一次被调用的参数", function() {
    
                  var most = foo.setBar.calls;
    
                  expect(most).toBeDefined();
    
             });
    
         });

      1.3版本: 

      如图,chrome跟踪结果。

         

         calls是一个数组,返回每次调用的上下文。数组最后一个值和mostRecentCall值相等。

    expect(foo.setBar.calls[foo.setBar.calls.length-1]).toEqual(foo.setBar.mostRecentCall);

         2.0版本:

      如图,chrome跟踪结果。

         

         calls是一个CallTracker的实例对象。这样更规范一些,用类封装了调用相关的信息。类中所有方法说明见下面。

      2、1.3 mostRecentCall和2.0.calls.mostRecent()区别

      (1)、调用方式不同

         前者是:被调用方法.mostRecentCall,例如:foo.setBar.mostRecentCall

         后者是:被调用方法.calls.mostRecent,例如:foo.setBar.calls.mostRecent()

      (2)、值相同

      mostRecentCall是一个对象,有两个属性:args和object,其中args是调用方法是所传的参数,object是调用方法的所属对象。

    describe("对spy函数的测试", function() {
              var foo, bar = null;
    
              beforeEach(function() {
                   foo = {
                        setBar: function(value) {
                             bar = value;
                        }
                   };
    
                   spyOn(foo, 'setBar'); //foo为spy函数
    
                   foo.setBar(123);
                   foo.setBar(456, 'another param');
              });
    
              it("上一次被调用的参数", function() {
                   expect(foo.setBar.mostRecentCall.args[0]).toEqual(456);
              });
    
              it("上一次被调用的参数", function() {
                   expect(foo.setBar.mostRecentCall.object === foo).toEqual(true);
              });
         });

       .calls.mostRecent()是函数,返回一个对象,同上。

      3、2.0中强大的calls对象

      

      .calls.any() 至少一次被调用,返回false/true。

      .calls.count()被调用次数

      .calls.argsFor(index)返回被index+1次调用的参数,返回值为[]

    it("tracks the arguments of each call", function(){
        foo.setBar(123);
        foo.setBar(456, "baz");
        expect(foo.setBar.calls.argsFor(0)).toEqual([123]);    
        expect(foo.setBar.calls.argsFor(1)).toEqual([456, "baz"]);
    });    
    .calls.argsFor(index)

      .calls.allArgs()返回所有被调用的参数,以逗号隔开,每一次调用的参数,以数组[]的形式返回

      .calls.all()同1.3中calls。返回每次调用的上下文context。

      .calls.mostRecent()同1.3的mostRecentCall,返回最近一次调用的上下文信息。等同于.calls.all()[.calls.call().length - 1]

      .calls.first等同于.calls.all()[0]

      .calls.reset()重置spy的所有信息,此时.call.any()返回false。

       4、异步啊异步

      1.3为了实现异步测试,jasminejs使用了一种很初级的方法,循环等待。

    describe("Asynchronous specs", function() {
            var value, flag;
    
            it("should support async execution of test preparation and expectations", function() {
    
                runs(function() {
                    flag = true;
                    value = 0;
    
                    setTimeout(function() {
                        flag = true;
                    }, 500);
                });
    
                waitsFor(function() {
                    value++;
                    return flag;
                }, "The Value should be incremented", 450);
    
                runs(function() {
                    expect(value).toBeGreaterThan(0);
                });
            });
        });

      这里的异步有以下几个问题:

      1、写法太过复杂,需要自己封装;

      2、实现有点初级。

      waitsFor有三个参数:

      第1个参数:校验异步是否完成函数,返回值为bool,返回true,停止循环等待;

      第2个参数:错误提示,如果操作第3个参数指定的毫秒数,第1个参数还是返回false,断言失败。提示信息如下:

      

      第3个参数:循环等待的时间,单位:毫秒。

      异步实现,大多是ajax请求,这个请求受网络、服务器环境等诸多因素影响,所以很难估算需要多长时间。

      2.0对这个async test做了很大的优化,也更合理了。

    describe("Asynchronous specs", function() {
            var value;
    
            beforeEach(function(done) {
                setTimeout(function() {
                    value = 0;
                    done();
                }, 1);
            });
    
            it("should support async execution of test preparation and expectations", function(done) {
                value++;
                expect(value).toBeGreaterThan(0);
                done();
            });
        });

      采用了一种pub/sub订阅模式处理,ajax请求成功,通知it执行。

      5、仅仅写法不同

      下面主要是功能一样,但是写法发生变化。

    1.3和2.0版本对照表
    1.3 2.0 说明
    andCallThrough .and.callThrough 函数监视器,但函数真的执行
    andReturn .and.returnValue 函数监视器,函数不真的执行。指定监视的函数的返回值
    andCallFake .and.callFake 替代被监视的函数,原函数不执行
    calls     .calls.all() 返回每次调用的上下文context
    mostRecentCall .calls.mostRecent() 最近一次被调用的上下文信息           
    jasmine.Clock.useMock jasmine.clock().install 启动模拟时间  
    jasmine.Clock.tick jasmine.clock().tick 模拟向前毫秒
      jasmine.clock().uninstall() 停止模拟时间,1.3无此方法

     

     

     

     

     

      

      

     

      

      先写这些,其他区别如果有必要,我会在后续的文章中补充。没有必要我会加一些jasmine2.0的源码分析文章。

  • 相关阅读:
    常见问题|一起工作 高端互联网人才兼职平台
    一拍即合
    食茶_尼尼龙_美愿作品展示平台
    Cop-Out
    员工宝
    java~使用自己的maven本地仓库
    java~接口的共享实体使用Map后更灵活
    知其所以然~tcp和udp的区别
    知其所以然~mongodb副本集
    java--map容器的hashcode和equals
  • 原文地址:https://www.cnblogs.com/hanyangecho/p/3579321.html
Copyright © 2020-2023  润新知