Set up your Node project to run tests locally and on CircleCI
Tags: node, javascript
Published: 2019-11-25 16:49:52

---
title: Set up your Node project to run tests locally and on CircleCI
published: true
canonical_url: https://www.coreycleary.me/set-up-your-node-project-to-run-tests-locally-and-on-circleci/
tags: node,javascript
---

<em><strong>Originally published at <a href="https://www.coreycleary.me/set-up-your-node-project-to-run-tests-locally-and-on-circleci/">coreycleary.me</a></strong>. This is a cross-post from my content blog. I publish new content every week or two, and you can <a href="https://www.coreycleary.me/about/">sign up to my newsletter</a> if you'd like to receive my articles directly to your inbox! I also regularly send cheatsheets and other freebies.</em>

You're creating the backend API for your new Node.js service and it's come time to setup Continuous Integration / CI so you can actually deploy the service.

CI pipelines can handle a lot of different tasks (building, linting, running tests, checking dependencies, publishing the package if it's a module, etc).

But here we'll just focus on <strong>setting up your project to be able to run tests on CI</strong> - using <a href="https://circleci.com/" rel="noopener" target="_blank">CircleCI</a> as our job runner.

<h3>Configuring CircleCI to run tests</h3>

In order for CircleCI to be able to run tests, it needs to know what script to run to actually run the tests. There are multiple ways you can do this, but I like using a <code>package.json</code> script.

In <code>package.json</code>, add the following:

<pre><code class="json">"test:ci": "NODE_ENV=test mocha ./tests/**/*.test.js",
</code></pre>

The glob pattern for your tests - the <code>./tests/**/*.test.js</code> from above -  may differ, and you might be using Jest over Mocha, or using different Mocha args, but the gist is the same.

Also, for your tests if you want to leverage <code>import</code> statements instead of <code>require</code> for your modules/dependencies, <a href="https://www.coreycleary.me/how-to-use-import-export-in-node-without-babel/" rel="noopener" target="_blank">check out how to do that here</a>.

The most important thing to note from above is that we've named the script <strong>test:ci</strong> and not just <strong>test</strong>.

<h3>Why `test:ci` and not just `test`?</h3>

I like having the flexibility of running my tests locally differently - for example, being able to run the tests in <code>--watch</code> mode so that everytime my code changes, the tests run again. Very useful for TDD!

The problem with that is, if we run the tests in watch mode on CI, they will never exit, and eventually the CI job will time out.

So by adding another CI-specific test script, we can have CircleCI leverage <code>test:ci</code>.

And then we can have another script to run tests locally, like so:

<pre><code class="json">"test": "NODE_ENV=test mocha --watch ./tests/**/*.test.js"
</code></pre>

<h3>CircleCI config</h3>

Now, for configuring CircleCI to run those tests...

Create a <code>.circleci</code> folder in the root of your project, and add a <code>config.yml</code> file to it.

In the <code>config.yml</code> file, copy and paste the following:

<pre><code class="sh">version: 2

defaults: &amp;defaults
  working_directory: ~/repo
  docker:
    - image: circleci/node:10.14.2

jobs:
  core:
    &lt;&lt;: *defaults
    working_directory: ~/repo

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
            - v1-dependencies-`{{ checksum "package.json" }}`
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-

      - run: npm ci

      - run: npm run test:ci

      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-`{{ checksum "package.json" }}`

      - persist_to_workspace:
          root: ~/repo
          paths: .

workflows:
  version: 2
  core:
    jobs:
      - core:
          filters:
            branches:
              only:
                - master
</code></pre>

Now, whenever you push a change to your <code>master</code> branch, CircleCI will run the <code>core</code> job configured in <code>config.yml</code>, which will install the dependencies for your project then run the tests!

If those tests finish successfully, then your project has run in an isolated, production-like environment and you've got confidence that it will run correctly in production!

Love JavaScript but still getting tripped up by setting up CI and your project structure? I publish articles on JavaScript and Node every 1-2 weeks, so if you want to receive all new articles directly to your inbox, <a href="https://www.coreycleary.me/about/">here's that link again</a> to subscribe to my newsletter!