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!