var should = require('should');
(5).should.be.exactly(5).and.be.a.Number();
var a = null
a.should.not.be.ok() // 报错
* 使用方法2:
若是undefined或者null,并没有继承Object的原型链,没有should属性可用,可采用如下方法:
```javascript
var should = require('should/as-function');
var a = null
should(a).not.be.ok() // pass
should(10).be.exactly(5).and.be.a.Number();
var should = require('chai').should() //actually call the function
var foo = 'bar'
foo.should.be.a('string')
foo.should.equal('bar')
foo.should.have.lengthOf(3)
定义:A simple tool that allows you to execute JavaScript code in multiple real browsers.
The main purpose of Karma is to make your test-driven development easy, fast, and fun.
学习单元测试的时候接触了很多概念karma、mocha、Jesmine、chai、expect、assert、should、sinon等,容易混乱,在此做个梳理。
1. 测试框架 Mocha、Jesmine
1.1 Mocha
Mocha是一个常用的JS测试框架,可以在浏览器和Nodejs环境使用。Mocha不带断言需要和断言库结合使用。ND项目中使用的也是Mocha+chai+sinon的结合。例如给ndfront组件写的单元测试,详情查看github仓库:https://github.com/xinbaihui/ndfront-testcase
特点:灵活,可扩展性好,可配合不同的断言库使用,但是自身集成度不高
1.2 Jesmine
Jesmine也是常用的测试框架,项目中没有用这个。
特点:内置断言库,集成度高,方便支持异步测试,但是灵活性差,断言风格单一
2. 断言库
2.1 assert
assert模块是Node的内置模块,用于断言。
官方API
常用API
eg:
2.2 should.js
github 仓库
API docs
should.js是个第三方断言库,常和Mocha联合使用。
requier('should'): 扩展Object.prototype,增加should属性,所有Object可以直接获取should使用,eg:
var a = null a.should.not.be.ok() // 报错
2.3 Chai
官网API: 安装方法等查看官网
Chai是个断言库,常和Mocha结合使用。他有多种断言风格(assertion style):assert, expect, should
assert断言风格:和nodejs的assert模块类似(多了写语法糖),是一种非链式语言风格 eg:
expect断言风格:expect和should都是BDD风格,是一种链式语言风格, 连接词有 to,be,been,is等自然语言, eg:
should断言风格:should()扩展了Object.prototype,增加了should属性,使用方法如下。eg:
(注意should对IE兼容性不好)
3. 测试运行工具:karma
Github 仓库
Karma不是测试框架,也不是断言库,他会开启一个HTTP服务,将测试文件生成一个Html文件,在浏览器内运行、调试。Karma不指定测试框架,通过插件和Mocha、Jesmine、QUnit都可以结合使用。
配置项较多,根据官网说明配置,并不难。
测试覆盖率:根据提示安装、配置即可生成覆盖率报告
4. 测试辅助工具:Sinon
Github 仓库
官网
入门参考(侵删)
为什么需要Sinon?在做单元测试的时候,我们会发现我们要测试的方法会引用很多外部依赖的对象,比如:(发送邮件,网络通讯,记录Log, 文件系统之类的),而我们没法控制这些外部依赖的对象。例如:前端项目通常是用Ajax去服务端请求数据,得到数据之后做进一步的处理。但是做单元测试的时候通常不真的去服务端请求数据,不仅麻烦,可能服务端接口还没做好,这种不确定的依赖使得测试变得复杂。所以我们需要模拟这个请求数据的过程,Sinon用来解决这个问题。
Sinon的工作本质是“测试替身”,测试替身用来替换测试中的部分代码,使得测试复杂代码变得简单。
Sinon提供了三个功能:示例讲解看入门文章,不再赘述
eg:admin/misc/user.js: user.getUser() (看不懂的随便看看,这是实际的项目代码单元测试)
user.getUser函数用来获取用户信息,用户输入工号后向服务端请求数据,我们的测试用例重点在前端代码,不应依赖服务端才可测试,so 应该模拟ajax请求。
(1)nd-spa中ajax.js请求代码如下:实际的请求函数为:request.get, so应该mock request的get函数
(2)测试用例代码如下:
5. 多步骤测试用例(实际项目记录,可不看,估计看不明白)
用户在前端页面中通常是通过点击鼠标期待某种效果,这个过程通常不做单元测试,因为复杂度较高,且页面变动较快,性价比很低。但是项目中某些公共的业务组件,需求变动小,步骤相对简单,但使用又非常多,例如social管理后台中的搜索用户admin/misc/user.js:user.autoComplete(),完整的过程是:用户输入用户信息,然后选择搜索到的匹配用户,再点击搜索到的用户,该输入框的值变为选择的用户。这个过程如何编写单元测试。
这里涉及到多步骤的模拟。
(1)util.js 封装多步执行函数
(2)使用 L116:给input设置值
L117:触发input的change事件,执行nd-autocomplete/src/input.js中change事件,如何调用的看autocomplete组件 L122:点击搜索列表的item,将值设置到input,然后验证input的值
过程中遇到一个额外的问题,在此记录下,备忘
(1)user中getUsers函数用到ucOrgId,查看代码(var ucOrgId = auth.getAuth('uc_org_id') 且仅仅在登录代码中有auth.setAuth())可知该组织id信息必须有,但是测试页面中没有登录,获取不到该信息,so,造登录数据,并设置到auth中。
(2)造登录数据并设置到auth中时遇到一个问题:若在user.spec.js中 引入auth,then auth.setAuth(...), 结果不对
原因:user.js中在开头就执行了获取ucOrgId的函数,我们在测试代码中先引入auth和user,这时ucOrgId已经获取了,且是空值,即使假造登录数据的函数写在import user之前也是没用,因为es6有提升的功能,总是先执行import,导致函数执行在后面,解决方法是:将设置登录数据的函数写在单独的文件中,使用import的方法,且在user之前inport,就会达到先执行设置登录数据的效果。(具体看代码更清晰)
(import的提升再复习下)
Jest TODO