Prerequisite
- First, we need a set up node project. I'm currently running a graphql project of my own. it's a boilerplate project with no controller code. All we need is a project with a running server.
- We need to run tests. code coverage works by calculating the percentage of your source code covered in tests. you can read more about code coverage here.
For this project we will run an index test. A simple check to see that one thing equals another.
Continuous Integration with CircleCI
Let's start with integrating CI into the project, by signing up to CircleCI. We can do this with out github account, which will authorise the CircleCI app on our account. Next, we add the repository we are trying to integrate with CircleCI. Once we ad the repository, CircleCI will tell us to either download a config.yml setup file, or add it automatically to our repository (in a .circleci
folder in root). For this walk through, just click on start building
.
On the initial build, our CircleCI integration will fail. This is because we are yet to add our config.yml file, and there are no tests in our code.
The next step is to allow for orbs in our CircleCI organisation directory. CircleCI orbs are 'shareable packages of configuration elements, including jobs, commands, and executors'. This allows you to use 3rd party apps to enhance your CI workflow. To use the coveralls orb, we need to opt-in to 3rd party orbs on our organisation’s security settings page, since coveralls orb is not a CircleCI partner. you can read more about this here.
Connecting with Coveralls
Now that we've got our CircleCI setup sorted, it's time to sort out our code coverage with coveralls. We'll head on over to coveralls, and signup with our github account. we will be redirected by github to authorise the coveralls web app for our repositories. click authorise.
Here, we'll add the repository we want to track the coverage of. Once the repository is added, there will be no builds recorded. This is because we've not yet done any heavy lifting. Navigate into the repository page in coveralls and copy the repo token. Save it somewhere safe. This token will be integral to further integrations. That's all we need to do to setup the repository in coveralls.
Repository Setup
Setting up the Job
- in our local code (or directly in github), we'll add the config.yml file below in a
.circleci
folder in our root directory.
version: 2.1
orbs:
coveralls: coveralls/coveralls@1.0.4
jobs:
build:
docker:
- image: circleci/node:10.16.0
working_directory: ~/project-api
environment:
NODE_ENV: test
DATABASE_URL: process.env.DATABASE_URL_TEST
steps:
- checkout
- run: npm install
# - run: npm test
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: install-npm-wee
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- ./node_modules
- run: # run tests
name: test
command: npm run test
- run: # run code coverage report
name: code-coverage
command: npm run coverage
- coveralls/upload
- store_artifacts: # special step to save test results as as artifact
# Upload test summary for display in Artifacts: https://circleci.com/docs/2.0/artifacts/
path: test-results
prefix: tests
- store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/
path: coverage
prefix: coverage
- store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
path: test-results
- run: # test what branch we're on.
name: "What branch am I on?"
command: echo ${CIRCLE_BRANCH}
notify:
webhooks:
- url: https://coveralls.io/webhook?repo_token=${process.env.COVERALLS_REPO_TOKEN}
Let's break down this code bit by bit so we know what's happening. in every line. it will instruct the entire workflow of our integration in CircleCI
version: 2.1
orbs:
coveralls: coveralls/coveralls@1.0.4
First, we start with the CircleCI infrastructure version we want to use. Here it's the 2.x infrastructure. The second part is setting up the CircleCI orbs. We need to use the coveralls orb, as we want to share coverage data between CircleCI and coveralls. you can read more about CircleCI coveralls orb here.
jobs:
build:
docker:
- image: circleci/node:10.16.0
working_directory: ~/project-api
I am using docker for my project, so I've add an image of the node environment needed, as well as the route to the working directory.
environment:
NODE_ENV: test
DATABASE_URL: process.env.DATABASE_URL_TEST
Here, we specify that the current environment we're working on is the test environment, so CircleCI is able to run our test code. We also specify the database the tests are to be run against (This variable values should be placed in the CircleCI environment variables setting.
steps:
- checkout
- run: npm install
# - run: npm test
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: install-npm-wee
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- ./node_modules
This section tells the CircleCI job to either restore the cached package.json dependencies/dev-dependencies it currently has for this particular project (from previous builds), or install the modules again, and save the node_module into its current cache.
- run: # run tests
name: test
command: npm run test
- run: # run code coverage report
name: code-coverage
command: npm run coverage
- coveralls/upload
- store_artifacts: # special step to save test results as as artifact
# Upload test summary for display in Artifacts: https://circleci.com/docs/2.0/artifacts/
path: test-results
prefix: tests
- store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/
path: coverage
prefix: coverage
- store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
path: test-results
This is the meat of the CircleCI process. In this section, we tell the job to run the tests we've written for our project. The test files are normally placed in a /test
folder in the project /src
folder.When all the test are completed (and successful), we tell the job to run our code coverage, to get the percentage of source code covered by our tests. After performing the code coverage, the job stores our coverage in CircleCI artifacts. We also store the test results themselves, making them visible in the CircleCI web application terminal (normally under the test summary section).
- run: # test what branch we're on.
name: "What branch am I on?"
command: echo ${CIRCLE_BRANCH}
This allows us to view, through the CircleCI application terminal, the exact repository branch being tested during the job.
notify:
webhooks:
- url: https://coveralls.io/webhook?repo_token=${process.env.COVERALLS_REPO_TOKEN}
This final section of the code is where we add the coverall web-hook to the CircleCI build. This web-hook is called at the end of the build. Coveralls is notified upon success of each build, and uses the test coverage data we ran and stored earlier to show the percentage coverage.
To be certain of which repository this coverage is for, in the coveralls web app, we need to pass the repository token to the url (remember the token we saved from coveralls earlier?). Add the COVERALLS_REPO_TOKEN
as an environment variable in the CircleCI project settings, with the repo token as its value.
Mocking the Test
Now you know what the CircleCI config file is doing, let's add a mock test to our database. Create a /test
folder in your /src
folder, and add an index.js
file. This is where we'll place our simple test. Copy and paste the code below.
import chai from 'chai';
const { expect } = chai;
describe('Initial test', () => {
it('should be equal to generic thing', () => {
expect('this thing').to.equal('this thing');
});
});
As you can see, we've written a mock test that simply checks if the first string is equal to the second string. now we need to install a few useful npm packages, and edit our scripts. run this in your terminal
npm i --save-dev nyc mocha-lcov-reporter mocha chai coveralls @babel/register
After installation, add the test scripts below to your package.json
{
"scripts": {
"test": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text --reporter=html mocha src/test/*.js --timeout 10000 -c --require @babel/register --exit",
},
"coverage": "nyc report --reporter=text-lcov | coveralls",
}
These test script allows the application to run the specified files in the /test
folder, as well as save the test coverage report. This coverage report can also be viewed from the CircleCI web application, as we've specified in the job config script. The coverage
command will be ran in CircleCI to generate the coverage files needed by coveralls. We can now run our local test (in the terminal), to see that it works.
$ npm run test
Let's push our repository changes to github. If we raise a pull request on our branch with our commit, we should see the CircleCI pull request check mark, showing a successful build. if everything goes right, we should also see the coveralls check mark on the pull request.
Back in our CircleCI web environment, we can see our build status as successful, and we should be ready to go. Over at our coveralls web app, we can also confirm that the build coverage has been recorded.
That's it. we've successfully integrated CircleCI alongside coveralls in our node project.
Badges.
Badges help external developers know the status of our repository. letting them know if our development branch passes its tests, as well as the current code coverage on that branch. Badges are placed in the README.md
file of oour repository.
To get a CircleCI badge, we need to navigate to our project settings in CircleCI. Under API permissions
, click on add api token
, with its scope as status
. We'll can label it anything we like, or keep the label empty. Save that token and add it to the badge path below.
[![CircleCI](https://circleci.com/gh/YOUR-GITHUB>/<YOUR-REPO>/tree/<YOUR-HEAD-BRANCH>.svg?style=svg&circle-token=<YOUR-TOKEN>)](https://circleci.com/gh/YOUR-GITHUB>/<YOUR-REPO>/tree/<YOUR-HEAD-BRANCH>)
For coveralls, there is no token required in the badge themselves. let;s navigate to our repository on coveralls, copy the badge for our head branch and add it to our README.md
. The badges usually come in the format below.
[![Coverage Status](https://coveralls.io/repos/github/<YOUR-GITHUB>/<YOUR-REPO>/badge.svg?branch=<YOUR-HEAD-BRANCH>)](https://coveralls.io/github/<YOUR-GITHUB>/<YOUR-REPO>?branch=<YOUR-HEADBRANCH>)
Happy coding.
Top comments (4)
Hi. I set up a circleci workflow for one of my repos to send the coverage info to coveralls via the coveralls circleci orb. I ran the coveralls/upload command once in verbose mode and after logging the contents of the coverage/lcov.info file, it's definitely sending something to coveralls with a 200 response, and the entire pipeline is succeeding, but nothing is reflecting on the coveralls dashboard, and the coverage badge still says "unknown".
I don't have a .coveralls.yml file in my project but from what I know it's optional and just stores the token required by coveralls, which I already have set in my env vars in circleci. Can't seem to figure out what's wrong. Please help.
Update:
It seems coveralls is just slow. I checked a day later without making any changes, the build was there but the badge wasn't updated. I merged the PR with the circleci config changes and a day after that the badge got updated.
Facing similar issue, please help.
thank for the guide, I use jest and jest can generate coverage test, I dont need to install coverall as dependency
coverall are much easier to setup then codecov, codecov also report my coverage incorrectly