• Jasmine入门(上)


    什么是Jasmine

     Jasmine是一个Javascript的BDD(Behavior-Driven Development)测试框架,不依赖任何其他框架。

    如何使用Jasmine

    从Github上(https://github.com/pivotal/jasmine/releases)下载所需的Jasmine版本。下载完成之后,直接打开SpecRunner.html即为Demo,除了引入Jasmine框架之外,只需引用自己所需测试的js文件以及Jasmine测试脚本引可。

    图1:

     

    基本语法介绍

    describe(string, function):可以理解为是一个测试集或者测试包(为了便于称呼,我们本文中统一叫测试集,官方称之为suite),主要功能是用来划分单元测试的,describe是可以嵌套使用的

    • 参数string:描述测试包的信息
    • 参数function:测试集的具体实现

    it(string, function):测试用例(官方称之为spec)

    • 参数string:描述测试用例的信息
    • 参数function:测试用例的具体实现

    expect:断言表达式

    第一个Jasmine例子

    Step 1:

    我们先创建一个名为myFirstJasmineTest.js的文件。

    Step 2:

    在Html页面中同时引用jasmine的框架文件与myFirstJasmineTest.js文件,可参考上面的图1。

    Step 3:

    在myFirstJasmineTest.js文件中添加如下内容:

     1 describe("My first Jasmine test", function() {
     2   it("a spec with an expectation", function() {
     3     expect(1).toBe(1);
     4     expect(1===1).toBe(true);
     5     expect('a').not.toBe('b');
     6   });
     7   
     8   it("an other spec in current suite", function() {
     9       expect(true).toBe(true);
    10   });
    11 });
    12 
    13 describe("My first Jasmine test", function() {
    14   it("nothing", function() {
    15   });
    16 });

    打开Html页面,Jasmine将自动执行用例:

    图2:

    从上述例子中我们可以看出:

    • 每个测试文件中可以包含多个describe
    • 每个describe中可以包含多个it
    • 每个it中可以包含多个expect

     当然实际上,Jasmine还允许describe的嵌套使用,大家可以自行试试。

    expect的使用

    首先说一下,所有的expect都可以使用not表示否定的断言。

    toBe:基本类型判断

      it("toBe and not.toBe", function() {
        expect(1).toBe(1);
        expect('a').not.toBe('b');
      });

    toEqual: toEqual有两种用法,对于基本的类型,toEqual相当于toBe

      it("toEqual and not.toEqual for basic types", function(){
        expect(1).toEqual(1);
        expect('a').not.toEqual('b');
      })

    toEqual还可以用来判断对象:

      it("toEqual and not.toEqual for objects", function(){
        var o1 = {
            name: "Jack",
            age: 12
        };
        
        var o2 = {
            name: "Jack",
            age: 12
        };
        
        var o3 = {
            name: "Tom",
            age: 13
        };
          
        expect(o1).toEqual(o2);
        expect(o1).not.toEqual(o3);
      })

    toMatch: 使用正则表达式判断

      it("toMatch and not.toMatch", function(){
        var str = "Michael Jackson";
        
        expect(str).toMatch(/michael/i);
        expect(str).not.toMatch(/tom/i);
      })

    toBeDefine: 判断是否是undefined

      it("toBeDefined and not.toBeDefined", function(){
        var student = {
            name: "Jack",
            age: 12
        };
        
        expect(student.name).toBeDefined();
        expect(student.gender).not.toBeDefined();
      })

    toBeUndefined: 判断是否是undefined,与toBeDefine相反

      it("toBeUndefined and not.toBeUndefined", function(){
        var student = {
            name: "Jack",
            age: 12
        };
        
        expect(student.gender).toBeUndefined();
        expect(student.name).not.toBeUndefined();
      })

    toBeNull:判断是否是null

      it("toBeNull and not.toBeNull", function(){
        var student = {
            name: "Jack",
            age: 12,
            deskmate: null
        };
        
        expect(student.deskmate).toBeNull();
        expect(student.name).not.toBeNull();
      });

    toBeTruthy:判断是否能转换成bool型,判断的是否是True

      it("toBeTruthy and not.toBeTruthy", function(){
        var stu1;
        var stu2 = "Tom";
        
        expect(true).toBeTruthy();
        expect(stu2).toBeTruthy();
        expect(stu1).not.toBeTruthy();
        expect(undefined).not.toBeTruthy();
      });

     toBeTruthy:判断是否能转换成bool型,判断的是否是False

      it("toBeFalsy and not.toBeFalsy", function(){
        var stu1;
        var stu2 = "Tom";
        
        expect(true).not.toBeFalsy();
        expect(stu1).toBeFalsy();
        expect(stu2).not.toBeFalsy();
        expect(undefined).toBeFalsy();
      });

    toContain: 判断集合是否包含(可以是普通类型,和可以是对象)

      it("toContain and not.toContain", function(){
        var arrStr = ["Jack", "Tom", "Mary"];
        var arrObj = [{name:"Jack",age:21}, {name:"Tom",age:22}];
    
        expect(arrStr).toContain("Jack");
        expect(arrStr).not.toContain("jack");
        
        expect(arrObj).toContain({name:"Jack",age:21});
        expect(arrObj).not.toContain({name:"jack",age:21});
      });

    toBeLessThan: 判断值类型的大小,结果若小则为True(也可以判断字符及字符串,以ascii码的大小为判断依据)

      it("toBeLessThan and not.toBeLessThan", function(){
        expect(1).toBeLessThan(1.1);
        expect("b").not.toBeLessThan("a");
      });

     toBeGreaterThan: 判断值类型的大小,结果若大则为True,与toBeLessThan相反(也可以判断字符及字符串,以ascii码的大小为判断依据)

      it("toBeGreaterThan and not.toBeGreaterThan", function(){
        expect(1).not.toBeGreaterThan(1.1);
        expect("b").toBeGreaterThan("a");
      });

    toBeCloseTo:判断数字是否相似(第二个参数为小数精度,默认为2位)

      it("toBeCloseTo and not.toBeCloseTo", function(){
        var a = 1.1;
        var b = 1.5;
        var c = 1.455;
        var d = 1.459;
        
        expect(a).toBeCloseTo(b, 0);
        expect(a).not.toBeCloseTo(c, 1);
        expect(c).toBeCloseTo(d);
      });

    toThrow: 判断是否抛出异常

      it("toThrow and not.toThrow", function(){
        var foo = function() {
          return 1 + 2;
        };
        var bar = function() {
          return a + 1;
        };
    
        expect(foo).not.toThrow();
        expect(bar).toThrow();
      });

    toThrowError: 判断是否抛出了指定的错误

      it("toThrowError and not.toThrowError", function() {
        var foo = function() {
          throw new TypeError("foo bar baz");
        };
    
        expect(foo).toThrowError("foo bar baz");
        expect(foo).toThrowError(/bar/);
        expect(foo).toThrowError(TypeError);
        expect(foo).toThrowError(TypeError, "foo bar baz");
      });

    Setup和Teardown

    Jasmine允许在执行测试集/测试用例的开始前/结束后做一些初始化/销毁的操作。

    Setup方法:

    • beforeAll:每个suite(即describe)中所有spec(即it)运行之前运行
    • beforeEach:每个spec(即it)运行之前运行

    Teardown方法:

    • afterAll:每个suite(即describe)中所有spec(即it)运行之后运行
    • afterEach:每个spec(即it)运行之后运行

    示例代码:

     1 (function(){
     2     var globalCount;
     3     describe("Setup and Teardown suite 1", function() {
     4       var suiteGlobalCount;
     5       var eachTestCount;
     6       
     7       beforeAll(function() {
     8         globalCount = 0; // 试试注释这行代码,看看对运行结果的影响
     9         suiteGlobalCount = 0;
    10         eachTestCount = 0;
    11       });
    12 
    13       afterAll(function() {
    14         //globalCount = 0; // 试试取消这行代码的注释,看看对运行结果的影响
    15         suiteGlobalCount = 0;
    16       });
    17 
    18       beforeEach(function() {
    19         globalCount++;
    20         suiteGlobalCount++;
    21         eachTestCount++;
    22       });
    23 
    24       afterEach(function() {
    25         eachTestCount = 0;
    26       });
    27         
    28       it("Spec 1", function() {
    29         expect(globalCount).toBe(1);
    30         expect(suiteGlobalCount).toBe(1);
    31         expect(eachTestCount).toBe(1);
    32       });
    33       
    34       it("Spec 2", function() {
    35         expect(globalCount).toBe(2);
    36         expect(suiteGlobalCount).toBe(2);
    37         expect(eachTestCount).toBe(1);
    38       });
    39     });
    40 
    41     describe("Setup and Teardown suite 2", function() {
    42       beforeEach(function() {
    43         globalCount += 2;
    44       });
    45       
    46       it("Spec 1", function() {
    47         expect(globalCount).toBe(4);
    48       });
    49     });
    50 })();

    示例中的第一个describe,在beforeAll中初始化了各个计数变量,在beforeEach中设置每次执行it后,各个计数变量自增1,在afterAll中,重置了全局性的计数变量(尝试取消afterAll中对globalCount的注释,看看运行结果的变化),在afterEach中,重置了局部计数变量。

    第二个describe,在beforeEach中对全局变量globalCount自增2,上述代码中,第一个describe中afterAll中没有对globalCount进行重置,因此执行完第一个describe后,globalCount的值为2,因此第二个describe的globalCount的初始值即为2。

    在beforeEach/it/afterEach中,还可以使用this关键字定义变量,需要注意的是,使用this关键字声明的变量,仅在beforeEach/it/afterEach这个过程中传递:

     1 (function(){
     2     describe("Test 'this'", function() {
     3       beforeEach(function() {
     4         this.testCount = this.testCount || 0;
     5         this.testCount++;
     6       });
     7 
     8       afterEach(function() {
     9         //this.testCount = 0; //无论是否有这行,结果是一样的,因为this指定的变量只能在每个spec的beforeEach/it/afterEach过程中传递
    10       });
    11         
    12       it("Spec 1", function() {
    13         expect(this.testCount).toBe(1);
    14       });
    15       
    16       it("Spec 2", function() {
    17         expect(this.testCount).toBe(1);
    18       });
    19     });
    20 })();

    xdescribe/xit的使用

    在实际项目中,需要由于发布的版本需要选择测试用例包,xdescribe和xit能很方便的将不包含在版本中的测试用例排除在外。不过xdescribe和xit略有不同:

    • xdescribe:该describe下的所有it将被忽略,Jasmine将直接忽略这些it,因此不会被运行
    • xit:运行到该it时,挂起它不执行
     1 (function(){
     2     xdescribe("Test xdescribe", function() {
     3       it("Spec 1", function() {
     4         expect(1).toBe(1);
     5       });
     6       
     7       it("Spec 2", function() {
     8         expect(2).toBe(2);
     9       });
    10     });
    11     
    12     describe("Test xit", function() {
    13       it("Spec 1", function() {
    14         expect(1).toBe(1);
    15       });
    16       
    17       xit("Spec 2", function() {
    18         expect(2).toBe(1);
    19       });
    20       
    21       xit("Spec 3", function() {
    22         expect(3).toBe(3);
    23       });
    24     });
    25 })();

    运行结果:

    篇幅和精力原因,关于Jasmine的入门学习,我们将在下一篇中继续。

    这里随便扯几句,最近由于新项目开始了,我在项目中同时需要担任PM、BA、开发的角色(哦,对了,我忘了告诉你们,其实我是.net的程序员),确实非常累, 很多东西要学、要做。不过对于技术的热爱(虽然技术不咋滴),我希望不管多忙多累,还是能在技术的道路上继续走下去。大家如果觉得我写的文章还可以,甚至能给你们带来一些小小的收获,希望大家顶一下,给我加加油。 好了,又到凌晨一点半了,我赶紧去睡了,明天还要去客户现场呢。

    参考资料

    Jasmine: http://jasmine.github.io/

    粉丝日志:http://blog.fens.me/nodejs-jasmine-bdd/

  • 相关阅读:
    Java基础学习笔记类的静态属性和静态方法待继续补充
    Java基础学习笔记常量与变量♪(^∇^*)
    从01超详细教你实现前端读取excel表格并渲染到界面
    Java基础学习笔记Java数据类型转换(~ ̄▽ ̄)~
    umi项目打包优化 广东靓仔
    快速构建前端错误监控系统 广东靓仔
    用canvas给背景添加音符 广东靓仔
    JS实现继承 广东靓仔
    vscode 好用插件 广东靓仔
    前端手写代码题库 广东靓仔
  • 原文地址:https://www.cnblogs.com/wushangjue/p/4541209.html
Copyright © 2020-2023  润新知