Intro to JavaScript Testing With Mocha
Tags: testing, javascript, mocha
Published: 2020-12-02 19:06:09

With my last few blog posts, I spent time talking about the importance of testing with software development, and I gave an intro to writing tests with Rails. For this post, I’m going to talk about how to write tests in one of the foremost JavaScript testing frameworks.

With plain old vanilla JavaScript, not using any frameworks like React or Angular, there are a variety of testing frameworks you can choose from, but I am going to talk about [Mocha](https://mochajs.org). The reason I chose Mocha is that the syntax is similar to the tests I was writing with Rails, and it is the framework my Bootcamp used for writing tests, so it feels familiar to me. It also has very good documentation with clear examples and explanations, and it has been around for a long time so they’ve had a chance to iron out all the bugs, and there are a lot examples of it being used.

To get started with using Mocha for your JavaScript project, run these commands in the top level of your project directory:
```
~ // ♥ > npm install mocha
~ // ♥ > mkdir test
~ // ♥ > touch test/test.js
```
These commands will add Mocha to your project, create a test directory, and make a file to write your tests in. The test file doesn’t have to be called `test.js`, you can name it whatever you like, and if you’re going to be testing multiple files, you should have a test file for each one with a name referencing the file you’re testing, like `<filename>Test.js`.

Now for writing you first test. Using Node.js’ built-in [assert](https://nodejs.org/api/assert.html) module, you could write a simple test like this:
```
const assert = require('assert') // from Node.js' assert module

describe('Array', function () {
  describe('#indexOf()', function () {
    it('should return -1 when the value is not present', function(){
      assert.equal([1, 2, 3].indexOf(4), -1)
    })
    it('should return the index when present', function(){
      assert.equal([1, 2, 3].indexOf(2), 1)
    })
  })
})
```
It is pretty clear from the function names what is going on here. The `describe` function is given a name that tells you what all of the tests inside it are going to be testing; in this example JavaScript’s `Array` `indexOf` function. The `it` function is given a name that describes exactly what the test is checking for, as well as a callback function. Inside the callback is an assertion. Assertions are designed to evaluate something for expected results. In this example we check that each call of the `indexOf` function on the given array returns the number we expect.

Now to run the tests from the command line, and see the results:
```
~ // ♥ > ./node_modules/mocha/bin/mocha

  Array
    #indexOf()
      ✓ should return -1 when the value is not present
      ✓ should return the index when present

  2 passing (7ms)
```
One thing to note here: you can see from the result that tests were run in the order that they were written in the file. This will always be the case for all tests that are written to run normally (I’ll get into running tests “abnormally” another time).

Back to running the tests, you can see that the command to run them is long and annoying to type out, so to make it easier you can set up a test script in your package.json file:
```
"scripts": {
  "test": "mocha"
}
```
Then you can run your tests with a simple command (you use `test` because it is the key you put in your script):
```
~ // ♥ > npm test
```
Another thing you can add to your `script` for running your tests is a reporter. Reporters change the way the results of your tests look in your terminal. The example I have above uses `spec`, which is the default. There is a wide range of reporters, some with the function descriptions for passing tests included, like `span`, and some that just include the name of the function if it fails. There is a full list of the reporters Mocha has [here](https://mochajs.org/#reporters). My favorite is `nyan` and it looks like this:
![A Nyan Cat version of passing tests](https://dev-to-uploads.s3.amazonaws.com/i/j6yjt1or9oiqn11y41md.png)
To change your reporter to something other than `span` you just have to change the script in your package.json to look like this:
```
"scripts": {
  "test": "mocha --reporter <reporter-name>"
}
```
The example I have above works just fine, but there are other options for how to write tests. For example, Mocha allows you to use any assertion library you want. One that I like because it has very useful and clear types of assertions is called [chai](https://www.chaijs.com/); it has `expect()`, `assert()` and `should`-style assertions, and you can choose to use any of these you like. After installing chai with `npm install chai`, I could rewrite the tests from before to look like this:
```
const expect = require('chai').expect; // add to the top of the file

describe('Array', function () {
  describe('#indexOf()', function () {
    it('should return -1 when the value is not present', function(){
      expect([1, 2, 3].indexOf(4)).to.equal(-1)
    })
    it('should return the index when present', function(){
      expect([1, 2, 3].indexOf(2)).to.equal(1)
    })
  })
})
```
I personally like this better because I think `expect(a).to.equal(b)` makes it clearer to someone reading it what you’re checking for, as opposed to `assert.equal(a, b)`. There are also a lot more methods than just `equal()` that you can use in your assertions, for example, `expect(foo).to.be.a(‘string’)`. You can see all of them listed out in chai’s documentation.

Another thing to note: Passing arrow functions to Mocha is discouraged. Arrow functions bind this so you cannot access the Mocha context. This can sometimes lead to some errors in your tests, and while arrow functions will usually work, avoiding them will cause you less problems down the line.

And that is all I’m going to talk about in writing JavaScript tests with Mocha today. I think I’ve laid a good foundation for how to get started with writing tests for a basic JavaScript project. In my next post, I’ll go into some of the more interesting things that you can do with Mocha tests.