DEV Community

loading...

Set up your Node project to run tests locally and on CircleCI

Corey Cleary
Tech Lead primarily working with JavaScript and Node.js
Originally published at coreycleary.me ・3 min read

Originally published at coreycleary.me. This is a cross-post from my content blog. I publish new content every week or two, and you can sign up to my newsletter if you'd like to receive my articles directly to your inbox! I also regularly send cheatsheets and other freebies.

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 setting up your project to be able to run tests on CI - using CircleCI as our job runner.

Configuring CircleCI to run tests

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 package.json script.

In package.json, add the following:

"test:ci": "NODE_ENV=test mocha ./tests/**/*.test.js",

The glob pattern for your tests - the ./tests/*/.test.js 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 import statements instead of require for your modules/dependencies, check out how to do that here.

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

Why `test:ci` and not just `test`?

I like having the flexibility of running my tests locally differently - for example, being able to run the tests in --watch 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 test:ci.

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

"test": "NODE_ENV=test mocha --watch ./tests/**/*.test.js"

CircleCI config

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

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

In the config.yml file, copy and paste the following:

version: 2

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

jobs:
  core:
    <<: *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

Now, whenever you push a change to your master branch, CircleCI will run the core job configured in config.yml, 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, here's that link again to subscribe to my newsletter!

Discussion (0)