您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
javascript单元测试(下)
 
作者:溤淋 来源:博客园 发布于 2015-8-14
   次浏览      
 

toThrow 检验一个函数是否会抛出一个错误


it("toThrow检验一个函数是否会抛出一个错误", function() {

var foo = function() {

return 1 + 2;

};

var bar = function() {

return a + 1;

};

expect(foo).not.toThrow();

expect(bar).toThrow();

});

注:describe可嵌套

xdescribe 和 xit:路过不执行,结果不显示。像display:none。点控制栏中skipped显示

Spy 存储函数的被调用情况和参数(函数监视器,记录被调用情况,但函数并不真执行)


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("测试foo函数是否被调用过", function() {

expect(foo.setBar).toHaveBeenCalled();

});

it("测试foo函数被调用的次数", function() {

expect(foo.setBar.calls.length).toEqual(2);

});

it("测试foo函数被调用时传入的参数", function() {

expect(foo.setBar).toHaveBeenCalledWith(123);

expect(foo.setBar).toHaveBeenCalledWith(456, 'another param');

});

it("上一次被调用的参数", function() {

expect(foo.setBar.mostRecentCall.args[0]).toEqual(456);

});

it("所有被调用的情况存在一个数组里", function() {

expect(foo.setBar.calls[0].args[0]).toEqual(123);

});

it("函数并未真的执行", function() {

expect(bar).toBeNull();

});

});

Spy addCallThrough 函数监视器,但函数真的执行

describe("对spy函数的测试,函数真的执行", function() {

    var foo, bar, fetchedBar;

 

    beforeEach(function() {

        foo = {

            setBar: function(value) {

                bar = value;

            },

            getBar: function() {

                return bar;

            }

        };

 

        //spyOn(foo, "setBar");    //如果加上这句,setBar不真的执行,后两个spec不通过

        spyOn(foo, 'getBar').andCallThrough();

 

        foo.setBar(123);

        fetchedBar = foo.getBar();

    });

 

    it("测试foo中getBar函数是否被调用过", function() {

        expect(foo.getBar).toHaveBeenCalled();

    });

 

    it("foo中setBar函数真的执行了", function() {

        expect(bar).toEqual(123);

    });

 

    it("foo中getBar函数真的执行了", function() {

        expect(fetchedBar).toEqual(123);

    });

});

Spy andReturn 函数监视器,函数不真的执行。指定监视的函数的返回值


describe("A spy, when faking a return value", function() {

var foo, bar, fetchedBar;

beforeEach(function() {

foo = {

setBar: function(value) {

bar = value;

},

getBar: function() {

return bar;

}

};

spyOn(foo, 'getBar').andReturn(745); //指定getBar函数返回745

foo.setBar(123);

fetchedBar = foo.getBar();

});

it("测试foo中getBar函数是否被调用过", function() {

expect(foo.getBar).toHaveBeenCalled();

});

it("不影响未被监视的其它函数", function() {

expect(bar).toEqual(123);

});

it("指定的返回值745", function() {

expect(fetchedBar).toEqual(745);

});

});

Spy addCallFake 替代被监视的函数,原函数不执行


describe("替代被监视的函数,原函数不执行", function() {

var foo, bar, fetchedBar;

beforeEach(function() {

foo = {

setBar: function(value) {

bar = value;

},

getBar: function() {

alert("frostbelt");

return bar;

}

};

spyOn(foo, 'getBar').andCallFake(function() {

return 1001;

});

foo.setBar(123);

fetchedBar = foo.getBar();

});

it("测试foo中getBar函数是否被调用过", function() {

expect(foo.getBar).toHaveBeenCalled();

});

it("不影响未被监视的其它函数", function() {

expect(bar).toEqual(123);

});

it("getBar被addCallFake指定的匿名函数代替,getBar不执行", function() {

expect(fetchedBar).toEqual(1001);

});

});

如果你没有什么可监视的又实在想监视一下,该咋办?自己create一个被监视函数。。

jasmine.createSpy(functionId)


describe("自己造一个被监视函数。啊,我凌乱了。。", function() {

var whatAmI;

beforeEach(function() {

whatAmI = jasmine.createSpy('whatAmI');

whatAmI("I", "am", "a", "spy");

});

it("有个id,是createSpy的传入函数,用于报错", function() {

expect(whatAmI.identity).toEqual('whatAmI')

});

it("是否被调用", function() {

expect(whatAmI).toHaveBeenCalled();

});

it("被调用的次数", function() {

expect(whatAmI.calls.length).toEqual(1);

});

it("被调用的参数", function() {

expect(whatAmI).toHaveBeenCalledWith("I", "am", "a", "spy");

});

it("最近一次被调用", function() {

expect(whatAmI.mostRecentCall.args[0]).toEqual("I");

});

});

有时需要监视一个对象的很多方法,用createSpyObj添加方法数组

jasmine.createSpyObj(obj, methodArray)


describe("有时需要监视一个对象的很多个方法,用createSpyObj添加数组", function() {

var tape;

beforeEach(function() {

tape = jasmine.createSpyObj('tape', ['play', 'pause', 'stop', 'rewind']);

tape.play();

tape.pause();

tape.rewind(0);

});

it("tape对象的这四个方法已被定义", function() {

expect(tape.play).toBeDefined();

expect(tape.pause).toBeDefined();

expect(tape.stop).toBeDefined();

expect(tape.rewind).toBeDefined();

});

it("四个方法是否被调用", function() {

expect(tape.play).toHaveBeenCalled();

expect(tape.pause).toHaveBeenCalled();

expect(tape.rewind).toHaveBeenCalled();

expect(tape.stop).not.toHaveBeenCalled();

});

it("被调用时传入的参数", function() {

expect(tape.rewind).toHaveBeenCalledWith(0);

});

});

jasmine.any 类型判断。instanceof


describe("类型匹配", function() {

it("相当于instanceof", function() {

expect({}).toEqual(jasmine.any(Object));

expect(12).toEqual(jasmine.any(Number));

});

it("也可以用于spy", function() {

var foo = jasmine.createSpy('foo');

foo(12, function() {

return true

});

expect(foo).toHaveBeenCalledWith(jasmine.any(Number), jasmine.any(Function));

//foo被调用时的参数 类型判断

});

});

jasmine.Clock.useMock() jasmine自己控制时间,实现异步调试,减少等待

jasmine.Clock.tick(n:uint) 向前n毫秒


describe("jasmine自己控制时间,实现异步调试,减少等待", function() {

var timerCallback;

beforeEach(function() {

timerCallback = jasmine.createSpy('timerCallback');

jasmine.Clock.useMock();

});

it("setTimeout", function() {

setTimeout(function() {

timerCallback();

}, 100);

expect(timerCallback).not.toHaveBeenCalled();

jasmine.Clock.tick(101);

expect(timerCallback).toHaveBeenCalled();

});

it("setInterval", function() {

setInterval(function() {

timerCallback();

}, 100);

expect(timerCallback).not.toHaveBeenCalled();

jasmine.Clock.tick(101);

expect(timerCallback.callCount).toEqual(1);

jasmine.Clock.tick(50);

expect(timerCallback.callCount).toEqual(1);

jasmine.Clock.tick(50);

expect(timerCallback.callCount).toEqual(2);

});

});

注:在这种环境下setTimeout和setInterval的callback为同步的,系统时间不再影响执行

runs(function) waitsFor(function, message, millisec) Jasmine异步调试 按自己的理解写个例子


describe("jasmine异步调试,对ajax结果的断言", function(){

var data, flag = false;

it("ajax是否按时返回了正确结果", function(){

runs(function(){

$.post(

url,

{},

function(data){

flag = true;

data = data.someAttr;

}

);

});

waitsFor(function(){ //flag为true或到2秒时执行 2秒内返回true则执行最后一个runs,到时未返回则本spec出错,返回第二个参数错误信息

return flag;

}, "ajax在指定时间2秒内未返回", 2000);

runs(function(){ //直到waitsFor返回true时执行

expect(data).toEqual("someThing");

})

});

});

注:it是一个spec,包含

runs(function)

waitsFor(function, message, millsec)

runs(function)

第一个runs里有一些异步的代码

waitsFor中的funciton如果在millsec内返回true,执行最后一个runs

如果在millsec内不能返回true,spec不通过,显示错误信息message

e) 使用

在测试的页面里加入以下代码:


<script type="text/javascript">

(function() {

var jasmineEnv = jasmine.getEnv();

jasmineEnv.updateInterval = 1000;

var trivialReporter = new jasmine.TrivialReporter();

jasmineEnv.addReporter(trivialReporter);

jasmineEnv.specFilter = function(spec) {

return trivialReporter.specFilter(spec);

};

var currentWindowOnload = window.onload;

window.onload = function() {

if (currentWindowOnload) {

currentWindowOnload();

}

execJasmine();

};

function execJasmine() {

jasmineEnv.execute();

}

})();

</script>

导入jasmine.css jasmine.js jasmine-html.js

src.js(源代码) test.js(存放describes)

JsTestDriver

a) 简介

JsTestDriver是一个JavaScript单元测试工具,易于与持续构建系统相集成并能够在多个浏览器上运行测试轻松实现TDD风格的开发。当在项目中配置好JsTestDriver以后,如同junit测试java文件一般,JsTestDriver可以直接通过运行js文件来进行单元测试。JsTestDriver框架本身就是JAVA的jar包,需要在本地运行并监听一个端口。

b) 优点

可以一次测试多个浏览器,使用方法是在启动服务时可以将多个浏览器的路径作为参数传进去。可以在多台机器上的浏览器中运行,包括移动设备。

测试运行得很快,因为不需要将结果添加到DOM中呈现出来,它们能够同时在任意多的浏览器中运行,未修改的文件浏览器会从缓存提取。

不需要HTML配件文件,仅仅只需提供一个或多个脚本和测试脚本,测试运行器运行时会创建一个空文件。

能很方便的和Ant、Maven等进行集成进行自动化测试,也可以方便和Jekins等持续集成工具进行集成,可以生成测试结果的XML文档。

有Eclipse和IntelliJ插件,可以很方便的在这两个IDE中进行测试,和JUnit很像。

支持其它测试框架,可以测试其它测试框架写的测试代码,比如有对应的插件可以将QUnit和Jasmine测试代码转换成JsTestDriver的测试代码。

c) 不足

不能在浏览器中测试,只能通过自动化工具或控制台运行。生成的结果不够直观。

安装使用稍微有点麻烦,依赖于JAVA环境。

d) API

assert(msg, value) 

assertTrue(msg, value)

assertFalse(msg, value)

assertEquals(msg, expected, actual)

assertNotEquals(msg, expected, actual)

assertSame(msg, expected, actual)

assertNotSame(msg, expected, actual)

assertNull(msg, value)

assertNotNull(msg, value)

assertUndefined(msg, value)

assertNotUndefined(msg, value)

assertNaN(msg, number)

assertNotNaN(msg, number)

assertException(msg, callback, type)

assertNoException(msg, callback)

assertArray(msg, arrayLike)

assertTypeOf(msg, type, object)

assertBoolean(msg, value)

assertFunction(msg, value)

assertNumber(msg, value)

assertObject(msg, value)

assertString(msg, value)

assertMatch(msg, pattern, string)

assertNoMatch(msg, pattern, string)

assertTagName(msg, tagName, element)

assertClassName(msg, className, element)

assertElementId(msg, id, element)

assertInstanceOf(msg, constructor, object)

assertNotInstanceOf(msg, constructor, object)

API按字面意思理解即可,不一一标注

e) 使用

前提:

安装java环境

下载JsTestDriver.jar

目录:

JsTestDriver.jar

jsTestDriver.conf //配置文件,默认名称,如果用其它名称,需要指定config参数

src

----src.js

test

----test.js

jsTestDriver.conf:

src.js:

test.js:

像java的JUnit一样,测试方法名要以”test”开头,如:”testXXXX”

测试步骤:

1.cmd 进入目录

2.运行命令”java –jar JsTestDriver.jar –port 9876”

3.打开页面http://localhost:9876,点击“捕获浏览器”。

4.新打开一个终端,运行命令”java –jar JsTestDriver.jar –tests all”,运行所有测试用例

5.也可以单独运行某一个用例,如运行命令” java –jar JsTestDriver.jar –tests addTest.testA”

FireUnit

a) 简介

FireUnit是一个基于Firebug的Javascript的单元测试框架。简单说来,FireUnit给Firebug增加了一个标签面板,并提供了一些简单的JavaScript API来记录和查看测试。

b) 优点

简单易用

c) 不足

功能不多,测试代码常常写在源码里,虽然可以实时地看到效果,但耦合太强,不易清理

只运行在Firefox下

d) API

常用:

fireunit.ok(condition, message) true/false

fireunit.compare(actual, expect, message) 是否相等

fireunit.reCompare(regexp, string, message) 字符串是否与正则式匹配

fireunit.testDone(); 执行以上的测试,在Firebug的新标签test中显示结果

其它:

fireunit.runTests(“test2.html”, “test3.html”) 一起运行多个页面的测试(每个文件都含有一些独立的测试)

fireunit.log(message) 打印log,但似乎不管用

fireunit.id(id) 相当与document.getElementById

fireunit.click(element) 模拟触发element的click事件

fireunit.focus(element) 模拟触发element的focus事件

fireunit.mouseDown(element) 模拟触发element的mouseDown事件

但看代码明明是click事件

在FF下,只是执行了node.click();不会触发onmousedown,只会触发onclick。已验证

fireunit.value(element) 修改element的value

fireunit.key(element, key) 模拟触发element的key事件

例:

var input = document.getElementsByTagName(“input”)[0];

fireunit.key(input, “a”);

没用过:

fireunit.browser

fireunit.test

fireunit.forceHTTP

fireunit.registerPathHandler

fireunit.panel

fireunit.privilege

e) 使用

在FF下装Firebug和FireUnit

直接在代码里写测试,就像console.log();

4. 小结

QUnit框架简单方便,测试界面直观详细,Jasmine功能强大,风格也简单明了,符合前端开发者的编程习惯,推荐JsTestDriver可以和QUnit等框架结合,可以同时测多个浏览器。但安装复杂,只能在控制台显示,不友好,不够清晰。FireUnit小巧灵活,加上Firebug的人气应该很受欢迎。如果需要进行自动化测试, 多了解一下Jasmine和JsTestDriver,本文未深入。

   
次浏览       
相关文章

微服务测试之单元测试
一篇图文带你了解白盒测试用例设计方法
全面的质量保障体系之回归测试策略
人工智能自动化测试探索
相关文档

自动化接口测试实践之路
jenkins持续集成测试
性能测试诊断分析与优化
性能测试实例
相关课程

持续集成测试最佳实践
自动化测试体系建设与最佳实践
测试架构的构建与应用实践
DevOps时代的测试技术与最佳实践
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

LoadRunner性能测试基础
软件测试结果分析和质量报告
面向对象软件测试技术研究
设计测试用例的四条原则
功能测试中故障模型的建立
性能测试综述
更多...   

性能测试方法与技术
测试过程与团队管理
LoadRunner进行性能测试
WEB应用的软件测试
手机软件测试
白盒测试方法与技术

某博彩行业 数据库自动化测试
IT服务商 Web安全测试
IT服务商 自动化测试框架
海航股份 单元测试、重构
测试需求分析与测试用例分析
互联网web测试方法与实践
基于Selenium的Web自动化测试
更多...