TIL coding
  • Initial page
  • 排版
  • Flexbox
  • Grid
  • jQuery
  • Untitled
  • JavaScript
    • An Introduction to JavaScript
    • Hello, world!
    • Code structure
    • The modern mode, "use strict"
    • Variables
    • Data types
    • Type Conversions
    • Operators
    • Comparisons
    • Interaction: alert, prompt, confirm
    • Conditional operators: if, '?'
    • Logical operators
    • Loops: while and for
    • The "switch" statement
    • Functions
    • Function expressions and arrows
    • JavaScript specials
    • Comments
    • Ninja code
    • Automated testing with mocha
    • Polyfills
    • Objects
    • Garbage collection
    • Symbol type
    • Object methods, "this"
    • Object to primitive conversion
    • Constructor, operator "new"
    • Methods of primitives
    • Numbers
    • Strings
    • Arrays
    • Array methods
    • Iterables
    • Map, Set, WeakMap and WeakSet
    • Object.keys, values, entries
    • Destructuring assignment
    • Date and time
    • JSON methods, toJSON
    • Recursion and stack
    • Rest parameters and spread operator
    • Closure
    • The old "var"
    • Global object
    • Function object, NFE
    • The "new Function" syntax
    • Scheduling: setTimeout and setInterval
    • Decorators and forwarding, call/apply
    • Function binding
    • Currying and partials
    • Arrow functions revisited
    • Property flags and descriptors
    • Property getters and setters
    • Prototypal inheritance
    • F.prototype
    • Native prototypes
    • Prototype methods, objects without __proto__
    • The “class” syntax
    • Class inheritance
    • Static properties and methods
    • Private and protected properties and methods
    • Extending built-in classes
    • Class checking: "instanceof"
    • Mixins
    • Error handling, "try..catch"
    • Custom errors, extending Error
    • Introduction: callbacks
    • Promise
    • Promises chaining
    • Error handling with promises
    • Promise API
  • Bootstrap
    • Navbar
Powered by GitBook
On this page
  • Why we need tests?
  • Behavior Driven Development (BDD)
  • Development of “pow”: the spec
  • The development flow
  • The spec in action
  • Improving the spec
  • Improving the implementation
  • Nested describe
  • Extending the spec

Was this helpful?

  1. JavaScript

Automated testing with mocha

自動化測試是工程師基本要求。

Why we need tests?

當撰寫一個函式,我們會預期產出的結果,我們可能會帶入不同參數用 console 來檢視結果,但若有錯誤修改後,又要一一測試之前帶入的參數,所以測試跟開發是分開的,測試可以很容易執行,檢查主要使用沒問題。

Behavior Driven Development (BDD)

行為驅動的開發被用在許多專案中,BDD 包含 3 件事測試、文件、範例。

Development of “pow”: the spec

我們要寫一個函式,pow(x, n) 該函式將產出 x 的 n 次方,在創建函式之前可以描述該函式的功能有 3 個規範。

  1. describe("title", function() { ... }) 描述函式名稱。

  2. it("title", function() { ... }) 描述函式功能

  3. assert.equal(value1, value2) 帶入參數測試函數的產出是否正確

The development flow

  1. 撰寫規範

  2. 撰寫基本函式可以跑測試

  3. 執行測試框架 mocha ,檢測函示是否正確

  4. 增加更多案例到測試中

  5. 測試失敗修改函式

  6. 重複 3 ~ 5 步驟

The spec in action

測試主要用到 3 個 librarues。

  • mocha 主要執行的框架 包含 descibe it 等函數。

  • chai 有很多 assertions 函式,範例使用 assert.equal。

  • Sinon 用來監視函數模擬內建函式。

<!DOCTYPE html>
<html>
<head>
  <!-- add mocha css, to show results -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.css">
  <!-- add mocha framework code -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.js"></script>
  <script>
    mocha.setup('bdd'); // minimal setup
  </script>
  <!-- add chai -->
  <script src="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...) -->
  <script src="test.js"></script>

  <!-- the element with id="mocha" will contain test results -->
  <div id="mocha"></div>

  <!-- run tests! -->
  <script>
    mocha.run();
  </script>
</body>

</html>

頁面分為 5 個部分

  1. head 引入 libraries

  2. script 撰寫測試的函示

  3. 測試程式碼寫在 test.js

  4. <div id='mocha'> 用來輸出 mocha 執行的結果

  5. mocha.run() 執行 mocha

Improving the spec

增加更多情況到測試中,一個測試只檢查一個功能。

// method1
describe("pow", function() {

  it("raises to n-th power", function() {
    assert.equal(pow(2, 3), 8);
    assert.equal(pow(3, 4), 81);
  });

});

// method2 better
describe("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

function pow(x, n) {
  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

// test
describe("pow", function() {

  function makeTest(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() {

    function makeTest(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));

});

// result
Testing started – before all tests (before)
Before a test – enter a test (beforeEach)
1
After a test – exit a test   (afterEach)
Before a test – enter a test (beforeEach)
2
After a test – exit a test   (afterEach)
Testing finished – after all tests (after)

Extending the spec

增加規範,程式碼出現錯誤,修改程式碼。

// add spec
describe("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)
function pow(x, n) {
  if (n < 0) return NaN;
  if (Math.round(n) != n) return NaN;

  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

PreviousNinja codeNextPolyfills

Last updated 5 years ago

Was this helpful?

…the full list is in the

docs