JavaScript - Testing with Jasmine

在此附上 Elie Schoppik 講師的 slides

為什麼要用 Jasmine?

  • Jasming 提供了各式各樣不同的測試方式
  • 在各種 JavaScript 環境下都能順利運行!

Getting Started

  1. 新增一 html 檔
  2. 連結 CSS、JavaScript 檔
  3. 開始寫測試程式碼!
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Jasmine Tests</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.2/jasmine.css">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.2/jasmine.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.2/jasmine-html.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.6.2/boot.js"></script>
</body>
</html>

一些 keywords

  • describe - ‘let me describt __ to you.’
  • it - ‘let me tell you about __.’
  • expect - ‘here’s what I expect.’

概念化

  • describe(‘Earth’)
    • it(‘is round’)
      • expect(earth.isRound.toBe(true))
    • it (‘is the third planet from the sun’)
      • expect(earth.numberFromSun).toBe(3)

寫成程式碼的話

在這裡,我一律使用 ES2015 的 arrow function 來使 程式碼 更加簡潔!

1
2
3
4
5
6
7
8
9
var earth = {
isRound: true,
numberFromSun: 3
}

describe('Earth', () => {
it('is round', () => expect(earth.isRound).toBe(true));
it('is the third planet from the sun', () => expect(earth.numberFromSun).toBe(3));
});

Matchers

Jasmine 提供了很多種 matchers,在這裡可以看到官方詳細的介紹

  • toBe / not.toBe
  • toBeCloseTo
  • toBeDefined
  • toBeFalsey / toBeTruthy
  • toBeGreaterThan / toBeLessThan
  • toContain
  • toEqual
  • jasmine.any()

beforeEach 和 afterEach

  • beforeEach 會在每次 “it” callback 前先執行,如此可以大符降低程式碼的重複性

舉例來說:

1
2
3
4
5
6
7
8
9
10
describe('Arrays', () => {
var arr;
beforeEach(() => arr = [1, 3, 5]); // run before each "it" callback
it('adds elements to an array', () => {
arr.push(7);
expect(arr).toEqual([1, 3, 5, 7]);
});
it('returns the new length of the array', () => expect(arr.push(7)).toBe(4));
it('adds anything into the array', () => expect(arr.push({})).toBe(4));
});
  • 類似的概念,afterEach 則是在每次 “it” callback 後執行

一樣來看個例子:

1
2
3
4
5
6
7
describe('Counting', () => {
var count = 0;
beforeEach(() => count++);
afterEach(() => count = 0); // run after each "it" callback
it('has a counter that increments', () => expect(count).toBe(1));
it('gets reset', () => expect(count).toBe(1));
});
  • beforeAll / afterAll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var arr = [];
beforeAll(() => arr = [1, 3, 5]);
describe('Counting', () => {
it('starts with an array', () => {
arr.push(4);
expect(1).toBe(1);
});
it('keeps mutating that array', () => {
console.log(arr); // [1, 2, 3, 4]
arr.push(5);
expect(1).toBe(1);
});
});
describe('Again', () => {
it('keeps mutating the array...again', () => {
console.log(arr); // [1, 2, 3, 4, 5]
expect(1).toBe(1);
});
});