Unit Testing with Mocha

  1. Overview
    1. A unit test is an automated test that verifies a function or method is working correctly
    2. Mocha is a popular JavaScript testing framework that runs on Node.js and in the browser
    3. Mocha is often combined with Chai, an assertion library for writing unit tests
    4. Mocha and Chai support Behavior Driven Development (BDD):
      1. Write an initial specification composed of tests for the most basic functionality
      2. Create an initial implementation
      3. Run Mocha to see if the implementation works
      4. Add more use cases (tests) to the spec that likely fail
      5. Update the implementation and run Mocha until no errors remain
      6. Repeat steps 4 and 5 until the implementation is complete
  2. Testing in the browser
    1. Use the web page below as a template to test one or more functions
      <!DOCTYPE html>
      <html>
      <head>
        <!-- Mocha CSS to style the results -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.css">
        
        <!-- Mocha framework -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.js"></script>
        <script>
          mocha.setup('bdd'); // minimal setup
        </script>
        
        <!-- Chai -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.js"></script>
        <script>
          // Make chai assert global
          const assert = chai.assert;
        </script>
      </head>
      
      <body>
      
        <script>
      
      // Function to test
      function factorial(n) {
         let answer = 1;
      
         for (let i = n; i >= 1; i--) {
            answer *= i;
         }
      
        return answer;
      }
      
        </script>
      
        <!-- Script with tests -->
        <script src="test.js"></script>
      
        <!-- Show test results -->
        <div id="mocha"></div>
      
        <!-- Run tests -->
        <script>
          mocha.run();
        </script>
      </body>
      
      </html>
      
    2. test.js script uses Mocha and Chai functions to create the spec:
      1. describe("title", func) - Name the spec and supply a function with test cases
      2. it("use case description", func) - Gives English description of what the test case does and a function that implements the test
      3. assert.equal(actual, expected) - Throws an AssertionError if actual == expected is false
      // test.js
      describe("factorial", function() {
      
         it("3 factorial is 6", function() {
            assert.equal(factorial(3), 6);
         });
        
         it("4 factorial is 24", function() {
            assert.equal(factorial(4), 24);
         });
      });
      

      Screenshot from Chrome:

      factorial with green checkmarks next to '3 factorial is 6' and '4 factorial is 24'
    3. Use a Map and loop to test more numbers
      describe("factorial", function() {
      
         const testValues = new Map([
            [0, 1], [3, 6], [4, 24], [5, 120]
         ]);
      
         for (let [num, answer] of testValues) {
            it(`${num} factorial is ${answer}`, function() {
               assert.equal(factorial(num), answer);
            });
         }
      });
      
  3. Other Chai assert methods:
    1. assert.equal(actual, expected) - Checks if expected == actual
    2. assert.strictEqual(actual, expected) - Checks if expected === actual
    3. assert.isTrue(value) - Checks if value === true
    4. assert.isFalse(value) - Checks if value === false
    5. assert.isNull(value) - Checks if value is null
    6. assert.isNaN(value) - Checks if value is NaN
    7. See the complete list
  4. Exercise: Continue the BDD process
    1. Add a test case that verifies factorial() returns NaN if passed a negative number or a non-integer number (Hint: Number.isInteger() could be helpful)
    2. Verify the test cases fail
    3. Update the implementation and run Mocha to verify your update works