我們要寫一個函式,pow(x, n) 該函式將產出 x 的 n 次方,在創建函式之前可以描述該函式的功能有 3 個規範。
describe("title", function() { ... }) 描述函式名稱。
it("title", function() { ... }) 描述函式功能
assert.equal(value1, value2) 帶入參數測試函數的產出是否正確
The development flow
撰寫規範
撰寫基本函式可以跑測試
執行測試框架 mocha ,檢測函示是否正確
增加更多案例到測試中
測試失敗修改函式
重複 3 ~ 5 步驟
The spec in action
測試主要用到 3 個 librarues。
mocha 主要執行的框架 包含 descibeit 等函數。
chai 有很多 assertions 函式,範例使用 assert.equal。
Sinon 用來監視函數模擬內建函式。
<!DOCTYPE html><html><head> <!-- add mocha css, to show results --> <linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.css"> <!-- add mocha framework code --> <scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.js"></script> <script> mocha.setup('bdd'); // minimal setup </script> <!-- add chai --> <scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.js"></script> <script> // chai has a lot of stuff, let's make assert global let assert = chai.assert; </script></head><body> <script> function pow(x, n) {/* function code is to be written, empty now */ } </script> <!-- the script with tests (describe, it...) --> <scriptsrc="test.js"></script> <!-- the element with id="mocha" will contain test results --> <divid="mocha"></div> <!-- run tests! --> <script> mocha.run(); </script></body></html>
頁面分為 5 個部分
head 引入 libraries
script 撰寫測試的函示
測試程式碼寫在 test.js
<div id='mocha'> 用來輸出 mocha 執行的結果
mocha.run() 執行 mocha
Improving the spec
增加更多情況到測試中,一個測試只檢查一個功能。
// method1describe("pow",function() {it("raises to n-th power",function() {assert.equal(pow(2,3),8);assert.equal(pow(3,4),81); });});// method2 betterdescribe("pow",function() {it("2 raised to power 3 is 8",function() {assert.equal(pow(2,3),8); });it("3 raised to power 3 is 27",function() {assert.equal(pow(3,3),27); });});
Improving the implementation
functionpow(x, n) {let result =1;for (let i =0; i < n; i++) { result *= x; }return result;}// testdescribe("pow",function() {functionmakeTest(x) {let expected = x * x * x;it(`${x} in the power 3 is ${expected}`,function() {assert.equal(pow(x,3), expected); }); }for (let x =1; x <=5; x++) {makeTest(x); }});
Nested describe
makeTest() 只用在 for 迴圈內,因此將他們綁在一起,下一個測試不會在用到。
describe("pow",function() {describe("raises x to power 3",function() {functionmakeTest(x) {let expected = x * x * x;it(`${x} in the power 3 is ${expected}`,function() {assert.equal(pow(x,3), expected); }); }for (let x =1; x <=5; x++) {makeTest(x); } });// ... more tests to follow here, both describe and it can be added});
describe("test",function() {before(() =>alert("Testing started – before all tests"));after(() =>alert("Testing finished – after all tests"));beforeEach(() =>alert("Before a test – enter a test"));afterEach(() =>alert("After a test – exit a test"));it('test 1', () =>alert(1));it('test 2', () =>alert(2));});// resultTesting started – before all tests (before)Before a test – enter a test (beforeEach)1After a test – exit a test (afterEach)Before a test – enter a test (beforeEach)2After a test – exit a test (afterEach)Testing finished – after all tests (after)
Extending the spec
增加規範,程式碼出現錯誤,修改程式碼。
// add specdescribe("pow",function() {// ...it("for negative n the result is NaN",function() {assert.isNaN(pow(2,-1)); });it("for non-integer n the result is NaN",function() {assert.isNaN(pow(2,1.5)); });});// improve pow(x ,n)functionpow(x, n) {if (n <0) returnNaN;if (Math.round(n) != n) returnNaN;let result =1;for (let i =0; i < n; i++) { result *= x; }return result;}
assert.equal(value1, value2) – checks the equality value1 == value2.
assert.strictEqual(value1, value2) – checks the strict equality value1 === value2.
assert.notEqual, assert.notStrictEqual – inverse checks to the ones above.
assert.isTrue(value) – checks that value === true
assert.isFalse(value) – checks that value === false