Jasmine

作者: 只是无情绪 | 来源:发表于2016-10-25 17:54 被阅读0次

    基本概念


    suites

    suites表示一个测试集,以函数describe封装

    describe

    describe 是 Jasmine 的全局函数,作为一个 Test Suite 的开始
    它通常有 2 个参数:字符串和方法
    字符串 -> 特定 Suite 的名字和标题
    方法 -> 实现 Suite 的代码

    describe("This is an exmaple suite", function() {
      it("contains spec with an expectation", function() {
        //测试true是否等于true
        expect(true).toBe(true);
        expect(false).toBe(false);
        expect(false).not.toBe(true);
      });
    });
    

    Specs

    Specs 通过调用 it 的全局函数来定义
    it和describe的参数相同
    每个 Spec 包含一个或多个 expectations 来测试需要测试代码

    Expectations

    Expectations 是由方法 expect 来定义
    一值代表实际值,二值代表期望值

    Matchers

    Matcher实现了断言的比较操作
    可以在expect调用Matcher前加上not来实现一个否定的断言(expect(a).not.toBe(false);)
    常见的matchers:
    toBe():相当于===比较
    toNotBe()
    toBeDefined():检查变量或属性是否已声明且赋值
    toBeUndefined()
    toBeNull():是否是null
    toBeTruthy():如果转换为布尔值,是否为true
    toBeFalsy()
    toBeLessThan():数值比较,小于
    toBeGreaterThan():数值比较,大于
    toEqual():相当于==

    注意与toBe()的区别:
    一个新建的Object不是(not to be)另一个新建的Object,但是它们是相等(to equal)的
    

    toNotEqual()
    toContain():数组中是否包含元素(值)只能用于数组,不能用于对象
    toBeCloseTo():数值比较时定义精度,先四舍五入后再比较

    //true
    it("The 'toBeCloseTo' matcher is for precision math comparison", function() {  
      var pi = 3.1415926,     
        e = 2.78;  
      expect(pi).not.toBeCloseTo(e, 2);  //第一个参数为比较数,第二个参数定义精度
      expect(pi).toBeCloseTo(e, 0);
    });
    

    toHaveBeenCalled()
    toHaveBeenCalledWith()
    toMatch():按正则表达式匹配
    toNotMatch()
    toThrow():检验一个函数是否会抛出一个错误

    Setup and Teardown

    Jasmine 提供了全局的方法实现清理操作
    在describe函数中,
    beforeEach():每个Spec执行之前执行
    afterEach(): 每个Spec执行之后执行。
    beforeAll():所有的Specs执行之前执行,但只执行一次
    afterAll():所有的Specs执行之后执行,但只执行一次

    嵌套代码块

    describe 可以嵌套, Specs 可以定义在任何一层
    一个 suite 可以由一组树状的方法组成
    在每个 spec 执行前,Jasmine 遍历树结构,按顺序执行每个 beforeEach 方法,Spec 执行后,Jasmine 同样执行相应的 afterEach

    跳过测试代码块

    Suites 和 Specs 分别可以用 xdescribe 和 xit 方法来禁用和挂起
    被Disabled的Suites在执行中会被跳过,该Suite的结果也不会显示在结果集中
    被Pending的Spec不会被执行,但是Spec的名字会在结果集中显示,只是标记为Pending

    xdescribe("An example of xdescribe.", function() {
      var gVar;
    
      beforeEach(function() {
        gVar = 3.6;
        gVar += 1;
      });
    
      xit(" and xit", function() {
        expect(gVar).toEqual(4.6);
      });
    });
    

    一个没有定义函数体的Sepc也会在结果集中被标记为Pending
    如果在Spec的函数体中调用pending()函数,那么该Spec也会被标记为Pending。pending()函数接受一个字符串参数,该参数会在结果集中显示在PENDING WITH MESSAGE:之后,作为为何被Pending的原因

    describe("Pending specs", function() {
    
      xit("can be declared 'xit'", function() {
        expect(true).toBe(false);
      });
    
      it("can be declared with 'it' but without a function");
      
      it("can be declared by calling 'pending' in the spec body", function() {
        expect(true).toBe(false);
        pending('this is why it is pending');
      });
    });
    

    Spy

    Spy能监测任何function的调用和方法参数的调用痕迹。需使用2个特殊的Matcher:

    • toHaveBeenCalled:可以检查function是否被调用过
    • toHaveBeenCalledWith: 可以检查传入参数是否被作为参数调用过

    spyOn
    使用 spyOn(obj,'function') 来为 obj 的 function 方法声明一个Spy
    对Spy函数的调用并不会影响真实的值

    describe("A spy", function() {
        var foo, bar = null; 
        beforeEach(function() { 
          foo = { 
            setBar: function(value) { 
              bar = value; 
            } 
          }; 
    
          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() { 
          // Spy的调用并不会影响真实的值,所以bar仍然是null
          expect(bar).toBeNull(); 
        });
    });
    

    and.callThrough
    如果在spyOn之后链式调用and.callThrough,那么Spy除了跟踪所有的函数调用外,还会直接调用函数额真实实现,因此Spy返回的值就是函数调用后实际的值了

      ... 
      spyOn(foo, 'getBar').and.callThrough(); 
      foo.setBar(123); 
      fetchedBar = foo.getBar(); 
      it("tracks that the spy was called", function() { 
        expect(foo.getBar).toHaveBeenCalled(); 
      }); 
      it("should not effect other functions", function() { 
        expect(bar).toEqual(123); 
      }); 
      it("when called returns the requested value", function() { 
        expect(fetchedBar).toEqual(123); 
      });
    });
    

    and.stub
    在调用and.callThrough后,如果你想阻止spi继续对实际值产生影响,你可以调用and.stub。也就是说,and.stub是将spi对实际实现的影响还原到最终的状态——不影响实际值

    spyOn(foo, 'setBar').and.callThrough();
    foo.setBar(123);
    // 实际的bar=123
    expect(bar).toEqual(123);
    // 调用and.stub()后,之后调用foo.setBar将不会影响bar的值。
    foo.setBar.and.stub();
    foo.setBar(456);
    expect(bar).toBe(123);
    bar = null;
    foo.setBar(123);
    expect(bar).toBe(null);
    

    全局匹配谓词


    jasime.any
    参数为一个构造函数,用于检测该参数是否与实际值所对应的构造函数相匹配

    describe("jasmine.any", function() { 
      it("matches any value", function() { 
        expect({}).toEqual(jasmine.any(Object)); 
        expect(12).toEqual(jasmine.any(Number)); 
      }); 
      describe("when used with a spy", function() { 
        it("is useful for comparing arguments", function() { 
          var foo = jasmine.createSpy('foo'); 
          foo(12, function() { return true; }); 
          expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function)); 
        }); 
      });
    });
    

    jasime.anything
    用于检测实际值是否为 null 或 undefined ,如果不为 null 或 undefined,则返回true

    it("matches anything", function() { 
      expect(1).toEqual(jasmine.anything());
    });
    

    jasmine.objectContaining
    用于检测实际Object值中是否存在特定key/value对。

    var foo;
    beforeEach(function() {
      foo = {
        a: 1,
        b: 2,
        bar: "baz"
      };
     });
    it("matches objects with the expect key/value pairs", function() {
      expect(foo).toEqual(jasmine.objectContaining({ bar: "baz" }));
      expect(foo).not.toEqual(jasmine.objectContaining({ c: 37 }));
    });
    

    jasmine.arrayContaining
    用于检测实际Array值中是否存在特定值。


    this值

    除了在describe函数开始定义变量,用于各it函数共享数据外,还可以通过this关键字来共享数据。
    在在每一个Spec的生命周期(beforeEach->it->afterEach)的开始,都将有一个空的this对象(在开始下一个Spec周期时,this会被重置为空对象)。

    参考目录


    JavaScript 单元测试框架:Jasmine 初探
    JavaScript单元测试框架-Jasmine
    web前端开发七武器—Jasmine入门教程(上)

    相关文章

      网友评论

          本文标题:Jasmine

          本文链接:https://www.haomeiwen.com/subject/ppgejttx.html