使用 Karma + Jasmine 构建 Web 测试环境(1)Jasmine 简介更新
- UID
- 1066743
|
使用 Karma + Jasmine 构建 Web 测试环境(1)Jasmine 简介更新
使用 Jasmine 编写测试用例下面,我们从一个实际的需求出发,学习如何使用这些方法来编写测试用例。
在开始之前,我们需要先定义应用模型(Model),模型的作用除了定义数据结构,也定义了测试用例的范围。也可以说,这些测试用例其实就是围绕着这些模型展开的。
清单 1. Mode.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| function Student(id, name){
this.id = id;
this.name = name;
this.age = -1;
this.teacher = null;
}
function Teacher(id, name){
this.id = id;
this.name = name;
this.age = -1;
}
function SchoolService(){
this.getTeachers = function(){
var teachers = [];
for(var i=0;i<5;i++){
var teacher = new Teacher();
teacher.id = "01" + i;
teacher.name = "teacher" + i;
teachers.push(teacher);
}
return teachers;
}
this.getStudents = function(){
var students = [];
for(var i=0;i<10;i++){
var student = new Student();
student.id = "00" + i;
student.name = "student" + i;
var teacher = new Teacher();
var tId = Math.ceil(i/2);
teacher.id = "01" + tId;
teacher.name = "teacher" + tId;
student.teacher = teacher;
students.push(student);
}
return students;
}
this.getTeacher = function(tId){
var r = null;
var teachers = this.getTeachers();
for(var i=0;i<teachers.length;i++){
var teacher = teachers;
if(teacher.id == tId){
r = teacher;
break;
}
}
return r;
}
this.getStudent = function(sId){
var r = null;
var students = this.getStudents();
for(var i=0;i<students.length;i++){
var student = students;
if(student.id == sId){
r = student;
break;
}
}
return r;
}
this.getStudents = function(tId){
var r = [];
var students = this.getStudents();
for(var i=0;i<students.length;i++){
var student = students;
if(student.teacher && student.teacher.id == tId){
r.push(student);
}
}
return r;
}
}
|
这里,我们分别定义了 Teacher 与 Student 类,以及对外提供的 SchoolService 类。不难看出 SchoolService 类就是我们需要重点测试的对象。下面,我们来编写测试用例
首先,我们需要测试 getTeachers() 方法
清单 2. 测试 getTeachers 方法1
2
3
4
5
6
7
8
9
10
11
12
13
| describe("A test suite for SchoolService", function() {
var schoolService = new SchoolService();
it("Spec test 1, test the getTeachers function", function() {
var teachers = schoolService.getTeachers();
expect(teachers).not.toBe(null);
expect(teachers.length).toEqual(5);
});
it("Spec test 2: test the getStudents function", function() {
var students = schoolService.getStudents();
expect(students).not.toBe(null);
expect(students.length).toEqual(10);
});
});
|
接下来,使用较为复杂的 Matchers 测试 getTeacher() 方法
清单 3. 测试 getTeacher() 方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| describe("A test suite for SchoolService", function() {
var schoolService = new SchoolService();
it("Spec test 1, test the getTeachers function", function() {
var teachers = schoolService.getTeachers();
expect(teachers).not.toBe(null);
expect(teachers.length).toEqual(5);
});
it("Spec test 2: test the getStudents function", function() {
var students = schoolService.getStudents();
expect(students).not.toBe(null);
expect(students.length).toEqual(10);
});
it("Spec test 3: test the getTeacher function", function() {
var teacher = schoolService.getTeacher("011");
expect(teacher).not.toBe(null);
expect(teacher.name).toMatch(/teacher/);
expect(teacher.name).toMatch("teacher");
expect(teacher.name).not.toMatch(/people/);
var teacher6 = schoolService.getTeacher("016");
expect(teacher6).toBe(null);
});
});
|
这时,我们发现每个方法内 teachers 与 students 对象总是重复的出现。因此我们考虑使用 beforeEach / afterEach 方法来优化测试代码
清单 4. 使用 beforeEach / afterEach 方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| describe("A test suite for SchoolService", function() {
var schoolService = new SchoolService();
var teachers = [];
var students = [];
beforeEach(function() {
teachers = schoolService.getTeachers();
students = schoolService.getStudents();
});
it("Spec test 1, test the getTeachers function", function() {
expect(teachers).not.toBe(null);
expect(teachers.length).toEqual(5);
});
it("Spec test 2: test the getStudents function", function() {
expect(students).not.toBe(null);
expect(students.length).toEqual(10);
});
it("Spec test 3: test the getTeacher function", function() {
var teacher = schoolService.getTeacher("011");
expect(teacher).not.toBe(null);
expect(teacher.name).toMatch(/teacher/);
expect(teacher.name).toMatch("teacher");
expect(teacher.name).not.toMatch(/people/);
var teacher6 = schoolService.getTeacher("016");
expect(teacher6).toBe(null);
});
afterEach(function() {
teachers = [];
students = [];
});
});
|
更进一步,如果能够将测试用例中的 Teacher 部分与 Student 分开,代码的逻辑就会显得更加整齐,于是,我们想到了使用嵌套测试
清单 5. 使用嵌套测试1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| describe("A test suite for SchoolService", function() {
//上面的代码与清单4相同
describe("A nested test suite", function() {
it("Spec test 4: test the getStudent function", function() {
var student10 = schoolService.getStudent("0010");
expect(student10).toBe(null);
var student9 = schoolService.getStudent("009");
var teacher = student9.teacher;
expect(teacher).toBeDefined();
});
it("Spec test 5: test the getStudentsByTeacher function", function() {
var students = schoolService.getStudentsByTeacher("014");
expect(students).not.toBe(null);
expect(students.length).toEqual(2);
var idArray = [];
idArray.push(students[0].id);
idArray.push(students[1].id);
expect(idArray).toContain("007", "008");
});
});
});
|
而且,一旦不再需要测试 Student 部分,我们只需要将 describe 更改成 xdescribe 即可。这个时候,Jasmine 在运行时就会忽略这部分的测试代码。(如果希望忽略 it 方法,则需要将它改成 xit) |
|
|
|
|
|