Udostępnij za pośrednictwem


How to write JavaScript unit tests with Mocha

In part one of this series on JavaScript unit testing, we covered some guiding principles and common excuses. Let's continue with part two, where we'll write unit tests using Mocha.

Get Visual Studio

First of all, you need Visual Studio. If you don't have it already, you can download a free edition called Visual Studio 2013 Express for Web. If you're a student, check with your administrators to see if your college is enrolled in DreamSpark. If so, you'll have free access on the DreamSpark site to paid versions of Visual Studio such as the Professional edition. This gives you more features. If you're a startup, enroll in BizSpark to get a MSDN license for 3 years. This also gives you paid versions of Visual Studio such as Professional and Ultimate.

Create a web site and add unit tests

  1. Download the following code sample: 5025.Calculator.zip. Right click on it, and choose Extract All.
  2. In Visual Studio, go to File -> Open Web Site. Select the Calculator folder you unzipped in step 1.
  3. Launch the website by choosing Debug -> Start Debugging. Or, you can just hit F5. This is the Mocha test runner and you'll see the output for a single unit test. It tests the add function on the Calculator object.
  4. Close the browser window that just launched.
  5. In Visual Studio, open index.html, js/calculator.js, and test/calculator-tests.js.
  6. In index.html, you'll see the unit test framework Mocha referenced. You'll also see a reference to Expect. That's an assertion library. It then references the JavaScript being tested, calculator.js, and then the unit tests themselves, calculator-tests.js.
  7. In calculator.js, you'll see a JavaScript IIFE which defines a Calculator constructor and the add function.
  8. In calculator-tests.js you'll see 3 sections. The describe at the top defines the test suite. The beforeEach sets up any necessary state. Perhaps your unit test relies on things being set up a certain way. Do that in beforeEach. The remaining describe function describes the specification. It corresponds to a particular feature. The call to the it function defines what the test should do. Be as explicit as possible. Lastly, expect asserts what the result of the test should be.
  9. Let's add a new test. In calculator-tests.js, copy this code for the subtract test and paste it below the add test:
 describe("Subtract", function () {
    it("should return the difference of both operands", function () {
        expect(calculator.subtract(5, 3)).to.be(2);
    });
});
  1. Hit F5 to run the tests, and it should fail. This is called TDD: Test-Driven Development. In TDD, you write your unit test first, run it to verify it fails, and only then implement the code you're testing. This prevents you from accidentally writing a unit test which always passes, giving you a false sense of safety.
  2. In calculator.js, create this subtract function. Note that the function body is incorrect. That's on purpose:
 Calculator.prototype.subtract = function (operand1, operand2) {
    return operand1 + operand2;
};
  1. Run the tests again by hitting F5. This time you'll get a different error.
  2. Change the subtract function in calculator.js to correctly implement subtraction:
 Calculator.prototype.subtract = function (operand1, operand2) {
    return operand1 - operand2;
};
  1. Run the tests a final time by hitting F5. This time both tests should pass. If you don't notice a difference, it could be because your web page is cached. Reload the page by hitting Control-R.

Commentary

Recall the principles of unit testing from part one in this series. How do the above unit tests stack up?

  1. The unit tests are predictable. We pass in static arguments and everything is reproducible.
  2. It's obvious when the unit tests pass or fail.
  3. The tests are self-documenting. A quick look at the Add unit test tells us that "Add should return the sum of both operands". We know what that means without having to look anything up.
  4. The unit tests have a single responsibility and only test one thing at a time.
  5. When the tests fail, we get useful error messages.
  6. They don't test multiple components, so they're not integration tests.

 

How about the excuses we listed in part one? Were these tests too hard to write, or too cumbersome? Once you learn how tests are written, they should be pretty simple especially when compared with debugging code without unit tests.

Want to learn more? Take a look at the Pluralsight course Front-end First: Testing and Prototyping JavaScript Apps by Elijah Manor. That's where this example is from.

In part three of this series, we'll see how to use the Chutzpah unit test runner in Visual Studio.