Getting Started with Node.js and Mocha - Semaphore Tutorial (2024)

Mocha is a testing library for Node.js, created to be a simple, extensible, and fast. It’s used for unit and integration testing, and it’s a great candidate for BDD (Behavior Driven Development).

This article will walk you through its installation and configuration, as well as demonstrate its usage by implementing a color converter that can translate from RGB (red, green, blue) to hexadecimal color representation. In addition, we will create a web server that exposes the above converter and demonstrates how to test asynchronous code.

Bootstrap

We will start by creating an empty directory.

$ mkdir converter$ cd converter

Node’s official package manager — npm — will help us set up an empty project. Npm’s init command-line option will launch a wizard, which creates a package.json for our project.

For the purpose of this tutorial, answer its questions as follows:

$ npm init{ "name": "converter", "version": "0.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC"}

Our project’s structure will contain an app directory that with the main code, and a test directory with the Mocha test files:

$ mkdir app$ mkdir test

Next, we will install our testing framework, and an expectation library called Chai that serves as a nice replacement for Node’s standard assert function.

$ npm install --save mocha chai

Note that we are using the --save option to automatically save these dependencies in our package.json file.

During the server testing phase, we will need a way to send HTTP requests. Request is an excellent choice. Install it as follows:

$ npm install --save request

Finally, we will also need the Express package that defines a simple DSL (domain-specific language) for routing and handling incoming HTTP requests:

$ npm install --save express

At this point, we are finished with the bootstrap process. However, we will configure one more thing to make running the test suite easier. We will set up the test command inside the package.json file, in order to run our tests simply by executing npm test from the command line.

The following command is used to invoke the Mocha binary installed locally in the ./node_modules directory:

$ npx mocha --reporter spec

Note that we have many different report formats to choose from. You can explore other reporters on Mocha’s official website.

Next, we will update the test command in package.json to contain the above command. That file should now look like this:

{ "name": "converter", "version": "0.0.0", "description": "", "main": "index.js", "scripts": { "test": "mocha --reporter spec" }, "author": "", "license": "ISC"}

Describing the Color Converter

We will follow the TDD (test-driven development) practice, and begin our project by creating tests before the implementation.

Let’s start by creating a test file:

$ touch test/converter.js

Mocha gives us the ability to describe the features that we are implementing by giving us a describe function that encapsulates our expectations. The first argument is a simple string that describes the feature, while the second argument is a function that represents the body of the description.

Our color converter description:

describe("Color Code Converter", function() { // specification code});

In the body of that description, we will create fine-grained segments that represent our feature in a little bit more detail:

describe("Color Code Converter", function() { describe("RGB to Hex conversion", function() { // specification for RGB to HEX converter }); describe("Hex to RGB conversion", function() { // specification for HEX to RGB converter });});

We will set up a concrete thing we are testing using the it feature. The it function is very similar to the describe function, except that we can only put expectations in the body of the it function. Let’s use it for our color converter:

describe("Color Code Converter", function() { describe("RGB to Hex conversion", function() { it("converts the basic colors", function() { }); }); describe("Hex to RGB conversion", function() { it("converts the basic colors", function() { }); });});

We can now introduce our first expectation. We will use the Chai library and its expect keyword to compare the result of our feature’s implementation and the result we expect to get. Of course, we first need to require the Chai library:

var expect = require("chai").expect;var converter = require("../app/converter");

Note that our implementation code doesn’t exist at this point, but this need not bother us, and we can write our tests as if the implementation already exists.

In the body of our first it function, we will test the rgbToHex color converter. As its name says, it converts from a (red, green, blue) tuple to hexadecimal. We will test it by converting the basic colors. The final test/converter.js looks like:

// test/converter.jsvar expect = require("chai").expect;var converter = require("../app/converter");describe("Color Code Converter", function() { describe("RGB to Hex conversion", function() { it("converts the basic colors", function() { var redHex = converter.rgbToHex(255, 0, 0); var greenHex = converter.rgbToHex(0, 255, 0); var blueHex = converter.rgbToHex(0, 0, 255); expect(redHex).to.equal("ff0000"); expect(greenHex).to.equal("00ff00"); expect(blueHex).to.equal("0000ff"); }); }); describe("Hex to RGB conversion", function() { it("converts the basic colors", function() { var red = converter.hexToRgb("ff0000"); var green = converter.hexToRgb("00ff00"); var blue = converter.hexToRgb("0000ff"); expect(red).to.deep.equal([255, 0, 0]); expect(green).to.deep.equal([0, 255, 0]); expect(blue).to.deep.equal([0, 0, 255]); }); });});

Notice the .to.deep.equal part of the above snippet. It is called a matcher, and it matches the result of a feature with an expected value.

There are of course many other matchers defined in the Chai libary, that can match expectations by various criteria. For example, to check the equality of two simple objects, we could write:

expect(1+1).to.equal(2)

In the above example, we have used the deep.equal because we were comparing two nested objects. The .deep part tells Chai to match all the elements of the arrays, one by one.

If we run npm test at this point, it will complain about a missing implementation file for our color converter:

$ npm testmodule.js:340 throw err; ^Error: Cannot find module '../app/converter'npm ERR! Test failed. See above for more details.npm ERR! not ok code 0

Don’t worry, this is perfectly normal.

Implementing the Color Converter

We will implement our converter in the following file:

$ touch app/converter.js

The first description for our color converter describes an RGB to hexadecimal color conversion. It takes three arguments and returns a string that represents the color in its hexadecimal representation.

We will use the toString method of the incoming numbers, combined with the number 16, to invoke a conversion to hexadecimal representation.

// app/converter.jsexports.rgbToHex = function(red, green, blue) { var redHex = red.toString(16); var greenHex = green.toString(16); var blueHex = blue.toString(16); return pad(redHex) + pad(greenHex) + pad(blueHex);};function pad(hex) { return (hex.length === 1 ? "0" + hex : hex);}. . .

Notice that we have padded the resulting value with a zero prefix if it is only one character long because a valid hexadecimal representation must always contain two characters.

To implement the function that converts from hexadecimal to RGB representation, we will use the parseInt function with the base 16 to convert parts of the incoming strings into valid decimal RGB values.

Add the following function to app/converter.js:

// app/converter.js. . .exports.hexToRgb = function(hex) { var red = parseInt(hex.substring(0, 2), 16); var green = parseInt(hex.substring(2, 4), 16); var blue = parseInt(hex.substring(4, 6), 16); return [red, green, blue];};

After this step, we can run our tests with npm test and should see that all our tests are passing:

Color Code Converter RGB to Hex conversion ✓ converts the basic colors Hex to RGB conversion ✓ converts the basic colors2 passing (8ms)

Implementing the Web Server

In this step, we will expose the color converter through an HTTP API, and demonstrate writing tests for asynchronous code using Mocha.

First, we will create a test file:

$ touch test/server.js

The same as in the previous test, we will require chai. To test the HTTP request, we will also require the request package.

// test/server.jsvar expect = require("chai").expect;var request = require("request");

Here is the description of the functionality we want to implement, nicely laid out with Mocha’s descriptions:

describe("Color Code Converter API", function() { describe("RGB to Hex conversion", function() { it("returns status 200", function() {}); it("returns the color in hex", function() {}); }); describe("Hex to RGB conversion", function() { it("returns status 200", function() {}); it("returns the color in RGB", function() {}); });});

We will store the full path to the resource we want to test in a variable. Before running the tests, we will run our web server on the localhost port 3000.

describe("Color Code Converter API", function() { describe("RGB to Hex conversion", function() { var url = "http://localhost:3000/rgbToHex?red=255&green=255&blue=255"; it("returns status 200", function() {}); it("returns the color in hex", function() {}); }); describe("Hex to RGB conversion", function() { var url = "http://localhost:3000/hexToRgb?hex=00ff00"; it("returns status 200", function() {}); it("returns the color in RGB", function() {}); });});

Note that in a bigger test suite, it is probably easier and nicer to put the host part of the URLs in a global constant, and reuse it in all tests.

To make a request, we will use the Request package. We need to pass two arguments to it: a URL to visit, and a function to be invoked when the request is completed. We will set up our expectations inside those callback functions.

describe("Color Code Converter API", function() { describe("RGB to Hex conversion", function() { var url = "http://localhost:3000/rgbToHex?red=255&green=255&blue=255"; it("returns status 200", function() { request(url, function(error, response, body) { expect(response.statusCode).to.equal(200); }); }); it("returns the color in hex", function() { request(url, function(error, response, body) { expect(body).to.equal("ffffff"); }); }); }); describe("Hex to RGB conversion", function() { var url = "http://localhost:3000/hexToRgb?hex=00ff00"; it("returns status 200", function() { request(url, function(error, response, body) { expect(response.statusCode).to.equal(200); }); }); it("returns the color in RGB", function() { request(url, function(error, response, body) { expect(body).to.equal("[0,255,0]"); }); }); });});

If we run the above code, something strange will happen. Nothing will fail, but, at the same time, no expectation will be checked. This happens because we didn’t give Mocha enough time to wait for the requests to finish. In other words, the code inside the request’s callback is never actually executed.

Fortunately, Mocha gives us a nice abstraction for this issue. For every it that needs to wait for a response value, we will inject a done callback function and call it only when our expectations were executed. This way, Mocha will know it needs to wait for some of the expectations.

The final test/server.js should look like:

// test/server.jsvar expect = require("chai").expect;var request = require("request");describe("Color Code Converter API", function() { describe("RGB to Hex conversion", function() { var url = "http://localhost:3000/rgbToHex?red=255&green=255&blue=255"; it("returns status 200", function(done) { request(url, function(error, response, body) { expect(response.statusCode).to.equal(200); done(); }); }); it("returns the color in hex", function(done) { request(url, function(error, response, body) { expect(body).to.equal("ffffff"); done(); }); }); }); describe("Hex to RGB conversion", function() { var url = "http://localhost:3000/hexToRgb?hex=00ff00"; it("returns status 200", function(done) { request(url, function(error, response, body) { expect(response.statusCode).to.equal(200); done(); }); }); it("returns the color in RGB", function(done) { request(url, function(error, response, body) { expect(body).to.equal("[0,255,0]"); done(); }); }); });});

When we run our tests again with npm test, all the expectations will fail. Of course, this happens because we don’t have a matching implementation for our color converter yet.

Color Code Converter RGB to Hex conversion ✓ converts the basic colors Hex to RGB conversion ✓ converts the basic colorsColor Code Converter API RGB to Hex conversion 1) returns status 200 2) returns the color in hex Hex to RGB conversion 3) returns status 200 4) returns the color in RGB2 passing (29ms)4 failing

A Web API for the Color Converter

Let’s create a new file for our API implementation:

$ touch app/server.js

We will use the Express framework to create a simple web API:

// app/server.jsvar express = require("express");var app = express();. . .

We will also include our previous color converter implementation:

. . .var converter = require("./converter");. . .

Express gives us a nice DSL for defining the routes for our API:

. . .app.get("/rgbToHex", function(req, res) {});app.get("/hexToRgb", function(req, res) {});app.listen(3000);

The listen method runs a web server on the provided port (in our case port 3000).

The only thing left is to parse our incoming parameters, pass them to the converter, and send the results back to the client.

Our final version of app/server.js should be:

// app/server.jsvar express = require("express");var app = express();var converter = require("./converter");app.get("/rgbToHex", function(req, res) { var red = parseInt(req.query.red, 10); var green = parseInt(req.query.green, 10); var blue = parseInt(req.query.blue, 10); var hex = converter.rgbToHex(red, green, blue); res.send(hex);});app.get("/hexToRgb", function(req, res) { var hex = req.query.hex; var rgb = converter.hexToRgb(hex); res.send(JSON.stringify(rgb));});app.listen(3000);

To run our tests, we will first need to run our server:

$ node app/server.js

We can now run our tests with npm test in a separate shell session:

Color Code Converter RGB to Hex conversion ✓ converts the basic colors Hex to RGB conversion ✓ converts the basic colorsColor Code Converter API RGB to Hex conversion ✓ returns status 200 ✓ returns the color in hex Hex to RGB conversion ✓ returns status 200 ✓ returns the color in RGB6 passing (50ms)

Continuous Integration for NodeJs

Continuous Integration (CI) is a software development practice where developers integrate the code into a shared repository several times a day. Having everything in a central location allows for continuous testing. CI allows us to create a short feedback loop, we know immediately the exact point where an error has been introduced..

Teams using CI can merge many times per day, shortening development cycles while improving on software quality.

To get started, we need to push the code to GitHub.

Getting Started with Node.js and Mocha - Semaphore Tutorial (1)
  • Copy the repository URL:
Getting Started with Node.js and Mocha - Semaphore Tutorial (2)
  • And use it to push the code:
$ echo "node_modules/" >> .gitignore$ git init$ git remote add origin YOUR_REPOSITORY_URL$ git add -A$ git commit -m "initial commit"$ git push origin master

Add the Project to Semaphore

Adding CI to the project takes only a few minutes.

Follow these steps to create a CI Pipeline:

  • Head over to Semaphore and use the Sign up with GitHub button to create a free account.
  • On Semaphore, use the + (plus sign) next to Projects to add your repository:
Getting Started with Node.js and Mocha - Semaphore Tutorial (3)
  • Pick your repository and click on Choose:
Getting Started with Node.js and Mocha - Semaphore Tutorial (4)
  • Select the NodeJS starter workflow and click on Customize it first:
Getting Started with Node.js and Mocha - Semaphore Tutorial (5)

When we choose to Customize it, Semaphore shows us the Workflow Editor screen, which consists of the following components:

Getting Started with Node.js and Mocha - Semaphore Tutorial (6)
  • Pipeline: A pipeline has a specific objective, e.g. building or testing. Pipelines are made of blocks that are executed from left to right in an agent.
  • Agent: The agent is the virtual machine that powers the pipeline. We have three machine types to choose from. The machine runs an optimized Ubuntu 18.04 image with build tools for many languages.
  • Block: blocks group jobs that can be executed in parallel. Jobs in a block usually have similar commands and configurations. Once all jobs in a block complete, the next block begins.
  • Job: jobs define the commands that do the work. They inherit their configuration from their parent block.

We need to make a small change before we can run our pipeline. We have to ensure the application is running before we try the tests:

  • Click on the Test block.
  • On the right side, add the following line before npm test:
    • node app/server.js &
Getting Started with Node.js and Mocha - Semaphore Tutorial (7)
  • Click on Run the Workflow and Start to run the pipeline for the first time:
Getting Started with Node.js and Mocha - Semaphore Tutorial (8)

The pipeline is now running the tests in the CI environment:

Getting Started with Node.js and Mocha - Semaphore Tutorial (9)

Improving the Pipeline

We can make our pipeline run faster and scale better by making a couple of modifications:

  • Split the install and test steps into different jobs.
  • Save the NodeJS dependencies in the cache. If we don’t use the cache, Semaphore will have to re-download all the node modules every time the pipeline runs.

Semaphore has a complete toolbox with commands to help us manage the CI workflow:

  • checkout: the checkout commands clones the correct revision of the GitHub repository and changes the directory. It’s usually the first command in a job.
  • sem-version: with sem-version, we can switch the active version of a language. Semaphore fully supports many languages, including NodeJS and JavaScript.
  • cache: the cache is your project file storage. Cache smart enough to figure out which files have to be stored and retrieved. We’ll use the cache to persist the node_module directory.

Install Block

We’ll start by replacing the Test block with the Install Block:

  • Click on the Test block and rename it to “Install”.
  • Rename the job to “npm install”
  • Type the following commands in the job box:
checkoutsem-version node 12cache restorenpm installcache store
Getting Started with Node.js and Mocha - Semaphore Tutorial (10)

Test Block

The next step is to create a Test Block:

  • Click on the +Add Block dotted line button to create a new block:
Getting Started with Node.js and Mocha - Semaphore Tutorial (11)
  • Set its name to “Test”
  • Change the name of the job to “mocha”
  • Type the following commands in the job box:
node app/server.js &npm test
  • Open the Prologue section, which is executed before all jobs in the block, and type the following commands:
checkoutsem-version node 12cache restore
  • Open the Environment Variables section and use the +Add env_vars link to define the variable: NODE_ENV = test
Getting Started with Node.js and Mocha - Semaphore Tutorial (12)
  • Click on Run the Workflow and then Start:
Getting Started with Node.js and Mocha - Semaphore Tutorial (13)

Congratulations! You have an optimized pipeline, a solid foundation for your NodeJS projects.

Getting Started with Node.js and Mocha - Semaphore Tutorial (14)

Next Reads

Don’t miss these great JavaScript and NodeJS tutorials. Learn to test and deploy applications to Serverless and Kubernetes:

  • Releasing NodeJS with Docker & Kubernetes:
    • Dockerizing a Node.js Web Application
    • How to Release Faster with Continuous Delivery for Google Kubernetes
    • How To Build and Deploy a Node.js Application To DigitalOcean Kubernetes Using CI/CD
  • JavaScript and Serverless deployments:
    • A CI/CD Pipeline for Serverless Cloudflare Workers
    • Serverless CI/CD and hosting with Semaphore and ZEIT Now

Summary

Mocha is a nice and easy DSL that makes writing tests a great pleasure. Mocha’s strength comes from its modularity, and while in this tutorial we didn’t use any other library other than chai, I encourage you to explore other libraries such as Sinon and Should.js.

Getting Started with Node.js and Mocha - Semaphore Tutorial (2024)

FAQs

Is Node.js difficult to learn? ›

If you already have experience using JavaScript, then Node is fairly easy to pick up. You're now going to be able to use that same knowledge to help you fast-track into learning the back-end also, and become a full-stack developer. And if you're not using JavaScript yet, you'll learn it as you learn to use Node.

What is the function of it in Mocha? ›

it() functions

In Mocha, the it() function is used to execute individual tests. It accepts a string to describe the test and a callback function to execute assertions. Calls to it() are commonly nested within describe() blocks.

How do I install Mocha locally? ›

Install Mocha

In the embedded Terminal ( Alt F12 ) , type one of the following commands: npm install mocha for local installation in your project. npm install -g mocha for global installation. npm install --save-dev mocha to install Mocha as a development dependency.

How to skip Mocha test? ›

By appending .skip() , you may tell Mocha to ignore test case(s). Anything skipped will be marked as pending, and reported as such.

What is the difference between Node testing Mocha and Jest? ›

Jest and Mocha are excellent frameworks used in JavaScript/Node applications. Jest is a closed library that provides out-of-box functionality. At the same time, Mocha is a much lighter library that integrates well with third-party libraries to deliver exactly what you require.

Can I learn node JS in 3 days? ›

Owing to this, it will take substantially more time to learn the basic skills necessary to start working with Node. js than learning how to use Node. js. The framework itself can be picked up in only a few days of study by skilled JavaScript programmers.

Is Node.js still relevant in 2024? ›

Yes, Node. js is still prevalent in 2024. Node. js has a large community, and many companies are using it in production, so we expect that the language will be supported for many years.

How many hours does it take to learn node JS? ›

How long does it take to learn Node JS if I know JavaScript? If you know JavaScript, are good at any frontend framework, or have one year of working experience, I think it would take you one month to learn how to build basic API in Node. js with authentication and authorization.

When to use Mocha? ›

Mocha is a testing framework for Javascript running on Node. js. The frameworks make it easier to test asynchronous Javascript concepts in the browser. Mocha is widely used for testing Javascript codes before deploying them onto the server.

What are the benefits of Mocha testing? ›

Advantages of Using Mocha for Testing

Extensive support for both Node-based and browser-based tests offers a flexible approach to testing. When run serially, Mocha tests excel at detecting exceptions that will affect the outcome of future tests.

What is Mocha npm? ›

Mocha is a testing library for Node. js, created to be a simple, extensible, and fast. It's used for unit and integration testing, and it's a great candidate for BDD (Behavior Driven Development).

How to run mocha in node js? ›

Then, run the command below on the command line to install Mocha JS in your project and an assertion library, Chai.
  1. npm i --save-dev mocha chai.
  2. npm install selenium-webdriver.
  3. npm i cross-env.
  4. LT_USERNAME="Your Username" LT_ACCESS_KEY="Your Access Key"
  5. "scripts": { "test": "mocha" },
May 21, 2024

How do I run a node server locally? ›

Running a Node. js Server Locally
  1. Step 1: Create a Simple Node. js Server. Initialize a Node. ...
  2. Step 2: Run the Server. Start the Server: In your terminal, run node server. js . ...
  3. Step 3: Stopping the Server. Stop the Server: To stop the server, simply press Ctrl + C in your terminal.
Feb 5, 2024

How to run js file locally with node? ›

Procedure
  1. Step 1: Save your javascript with . js extension.
  2. Step 2: Open the command prompt.
  3. Step 3: Locate your path where the . js file is saved.
  4. Step 4: To compile the .js file we have to write.
  5. Node <Filename>.js.
  6. Step 5: Press the Enter key.
  7. Output:

How to run test cases in Mocha? ›

Follow the steps below to create and run a test script using the Page Object Model. Step 1: Create a folder called MochaSeleniumTests. In the folder, create a folder called pageModel and test. Then, run the command below on the command line to install Mocha JS in your project and an assertion library, Chai.

How to test node.js apps using Mocha Chai and Sinonjs? ›

  1. Mocha is a feature-rich JavaScript test framework that runs on Node. ...
  2. Run npm install to install project dependencies.
  3. Notice that test-related packages mocha , chai , sinon , and faker are saved in the dev-dependencies.
  4. The test script uses a custom glob ( ./src/**/*.
Dec 22, 2022

How to write test cases for node js API? ›

Below the beforeEach segment, you should have describe() for every method that will be tested. This can result in different outcomes. That's why in your describe() , you also need it() segments, which will cover all possible scenarios for the tested method.

How to group test cases in Mocha? ›

In Mocha, the describe() function is used to group tests. It accepts a string to describe the group of tests and a callback function which contains it() tests. Calls to describe() are commonly nested to resemble the structure of the code being tested.

Top Articles
Latest Posts
Article information

Author: Neely Ledner

Last Updated:

Views: 5871

Rating: 4.1 / 5 (42 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Neely Ledner

Birthday: 1998-06-09

Address: 443 Barrows Terrace, New Jodyberg, CO 57462-5329

Phone: +2433516856029

Job: Central Legal Facilitator

Hobby: Backpacking, Jogging, Magic, Driving, Macrame, Embroidery, Foraging

Introduction: My name is Neely Ledner, I am a bright, determined, beautiful, adventurous, adventurous, spotless, calm person who loves writing and wants to share my knowledge and understanding with you.