Javascript 测试框架 Jasmine(三):Setup、Teardown、嵌套 describe 等
2014-06-20 · 891 chars · 5 min read
上一篇把 Matcher 说了说,本来该说自定义 Matcher 的,但是发现有些七七八八的细节没讲,那就今天先把这些基础说了。
Setup and Teardown#
Setup 和 Teardown 可以帮助 Suite 执行一些重复的代码,Jasmine 提供了beforeEach 和afterEach 函数。很显然,beforeEach 在 describe 中的任何 spec 执行之前运行,afterEach 在任何 spec 执行之后运行。具体的逻辑看 Demo 就一目了然了:
describe('Setup和Teardown示例', function () {
var foo
beforeEach(function () {
foo = 0
foo += 1
})
afterEach(function () {
foo = 0
})
it('测试1', function () {
expect(foo).toEqual(1)
})
it('测试2', function () {
expect(foo).toEqual(1)
expect(true).toEqual(true)
})
})
前面说过 javascript 的作用域规则在 Jasmine 中是适用的,但是这里可以通过this 在beforeEach ,it ,afterEach 中间共享变量。每个 spec 的this 默认指向空的 object。
describe('this用法示例', function () {
beforeEach(function () {
this.foo = 0
})
it('使用this共享状态', function () {
expect(this.foo).toEqual(0)
this.bar = 'test pollution?'
})
it('下个Spec执行前this会被重置为空Object', function () {
expect(this.foo).toEqual(0)
expect(this.bar).toBe(undefined)
})
})
嵌套 describe#
可以嵌套使用 describe,形成一个 Suite 树,在一个 spec 执行之前,Jasmine 会顺序执行这颗树上的所有beforeEach 。同样的,执行完 spec 后,也会顺序执行树上的所有afterEach
describe('测试嵌套describe:level1', function () {
var foo
beforeEach(function () {
alert('level1:Setup')
})
afterEach(function () {
alert('level1:Teardown')
})
it('level1:测试', function () {
alert('level1:测试')
})
describe('测试嵌套describe:level2', function () {
beforeEach(function () {
alert('level2:Setup')
})
afterEach(function () {
alert('level2:Teardown')
})
it('level2:测试', function () {
alert('level2:测试')
})
})
})
具体的执行顺序,点击这里查看上例的效果,你就全明白了。
禁用 Suites 和挂起 Specs#
可以使用xdescribe 和xit 函数禁用 Suites 和 specs。当 Suites 被禁用后,将不显示在报表中。
xdescribe('A spec', function () {
var foo
beforeEach(function () {
foo = 0
foo += 1
})
it('is just a function, so it can contain any code', function () {
expect(foo).toEqual(1)
})
})
另外可以使用pending 函数将 specs 挂起,挂起 specs 和使用xit 函数定义的 spec 一样,spec 不会被执行,但是名字会出现在报表中。另外只有名字,没有实际代码的 spec 也会在结果中显示为挂起的状态。pending 可以在 spec 函数体的任何地方调用,不管函数体内有没有 expectations,还是看个例子:
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()
})
})
jasmine.any#
jasmine.any 接受构造函数或者“Class”名作为期望值,如果这个构造函数(Class)和实际值的构造函数(Class)匹配,则返回true 。继续看例子:
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))
})
})
})
jasmine.objectContaining#
当一个你只关心实际值是否包含某个键值对的时候,可以使用jasmine.objectContaining:
describe('jasmine.objectContaining', function () {
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,
}),
)
})
describe('when used with a spy', function () {
it('is useful for comparing arguments', function () {
var callback = jasmine.createSpy('callback')
callback({
bar: 'baz',
})
expect(callback).toHaveBeenCalledWith(
jasmine.objectContaining({
bar: 'baz',
}),
)
expect(callback).not.toHaveBeenCalledWith(
jasmine.objectContaining({
c: 37,
}),
)
})
})
})
– 下一篇讲一下自定义 Matcher –


