前端自动化测试框架Jest中的钩子函数及作用域
更新时间:2022-06-08 09:21:03 作者:多测师 浏览:131
Jest 中的钩子函数
通常,在编写测试时,你需要在测试运行之前进行一些初始化工作,并且需要在测试运行之后进行一些完成工作。Jest提供了钩子函数来处理这个问题。我们通过一个计数器来学习钩子函数相关的知识。
首先在index.js里面定义一个类,并且导出:
// index.js
class Counter {
constructor() {
this.number = 0;
}
add() {
this.number++;
}
minus() {
this.number--;
}
}
export default Counter;
可以看到,这是一个使用 ES6 语法定义的 class:
在实例化的时候定义了number,初始值是0
定义了静态方法add,执行结果为number加1
定义了静态方法minus,执行结果为number减1
然后在index.test.js里面引入这个类,测试add方法:
// index.test.js
import Counter from "./index";
const counter = new Counter();
test("测试 Counter 的 add 方法", () => {
expect(counter.number).toBe(0);
counter.add();
expect(counter.number).toBe(1);
});
然后运行测试用例,完美通过。
然后继续添加minus方法的测试用例:
// index.test.js
import Counter from "./index";
const counter = new Counter();
test("测试 Counter 的 add 方法", () => {
expect(counter.number).toBe(0);
counter.add();
expect(counter.number).toBe(1);
});
test("测试 Counter 的 minus 方法", () => {
expect(counter.number).toBe(0);
counter.minus();
expect(counter.number).toBe(-1);
});
然后运行测试用例,结果为:
测试 add 方法:通过
测试 minus 方法:不通过
出现这个情况的原因是:
我们的实例化过程写在了测试用例外面,所有的测试用例公用一个counter 实例,所以在测试 add 方法的时候,我们已经对实例的number属性做出了修改。导致minus方法的测试用例没用通过。
解决办法是:
我们可以把实例化写在每一个测试用例里面,每次测试都创建一个新的counter 实例。这样就不会公用一个counter了,也不会影响到其它实例了。
但是一般情况下,我们不会这样做,因为测试用例很多的话,每次都创建一个 counter实例 是一件很麻烦的事情,假如当前文件中有1000个和counter有关的测试用例,那么就要创建1000次counter实例。
这个时候!钩子函数派上用场了!
// index.test.js
import Counter from "./index";
let counter = null;
beforeEach(() => {
counter = new Counter();
});
test("测试 counter 的 add 方法", () => {
expect(counter.number).toBe(0);
counter.add();
expect(counter.number).toBe(1);
});
test("测试 counter 的 minus 方法", () => {
expect(counter.number).toBe(0);
counter.minus();
expect(counter.number).toBe(-1);
});
然后运行测试用例,结果通过。
beforeEach() 的作用是在每个测试用例执行之前执行里面的回调函数,如果你需要在测试开始之前对很多个测试做一些重复的工作,比如要初始化状态,你就可以使用它。
实际上,Jest 一共有四个钩子函数:
beforeAll:在所有测试用例执行之前调用(调用一次)
afterAll:在所有测试用例执行之后调用(调用一次)
beforeEach:在每个测试用例执行之前调用(调用多次)
afterEach:在每个测试用例执行之后调用(调用多次)
钩子函数的作用域
在了解作用域之前,需要先了解一个小知识点:Scoping
默认情况下,beforeAll和afterAll应用于文件中的每个测试用例。
实际上,还可以使用describe方法将测试用例进行分组。当它们位于describe中时,beforeAll和afterAll只应用于当前分组中的测试用例。
// index.test.js
describe("测试分组1", () => {
beforeAll(() => {
console.log("测试分组1 - beforeAll");
});
afterAll(() => {
console.log("测试分组1 - afterAll");
});
test("测试", () => {
console.log("测试分组1 测试");
expect(1 + 1).toBe(2);
});
});
describe("测试分组2", () => {
beforeAll(() => {
console.log("测试分组2 - beforeAll");
});
afterAll(() => {
console.log("测试分组2 - afterAll");
});
test("测试", () => {
console.log("测试分组2 测试");
expect(1 + 1).toBe(2);
});
});
在默认情况下,Jest将按照describe的顺序连续运行所有测试分组,等待每个测试完成后再继续。
需要注意的是:
如果我们不进行分组,相当于在最外面写了一层describe。
除此之外,实际上,在describe里面还能嵌套describe,就像下面这样:
// index.test.js
describe("第一层", () => {
beforeAll(() => console.log("第一层 - beforeAll"));
describe("第二层", () => {
beforeAll(() => console.log("第二层 - beforeAll"));
describe("第三层", () => {
beforeAll(() => console.log("第三层 - beforeAll"));
test("测试", () => {
console.log("测试");
expect("hello" + " " + "world").toBe("hello world");
});
});
});
});
所以可以得出一些结论:
每一个 describe 都可以有自己的钩子函数
每一个 describe 都有自己的作用域
每一个 钩子函数也有自己的作用域,就是当前所在的 describe
每一个 describe 里面的钩子函数对自己作用域下面所有的测试用例都生效
如果 describe 是多层嵌套的,那么测试用例执行的顺序是由外到内
最后再补充一个知识点:
如果有·、多个测试用例,但是只想运行一个的时候,注释掉其它的测试用例往往不是最好的选择,我们可以使.only语法去执行:
// index.test.js
test.only("这个测试会被执行", () => {
expect("A").toBe("A");
});
test("这个测试会被跳过", () => {
expect("B").toBe("B");
});
这样就可以单独运行一个测试用例,其它测试会被跳过。
以上内容为大家介绍了前端自动化测试框架Jest中的钩子函数及作用域,本文由多测师亲自撰写,希望对大家有所帮助。了解更多自动化测试相关知识:https://www.aichudan.com/xwzx/