Continuous Integration in JavaScript: a Guide (ft. Github Actions)
Tags: testing, javascript, devops, git
Published: 2019-08-30 10:58:50

---
title: "Continuous Integration in JavaScript: a Guide (ft. Github Actions)"
published: true
description: "Learn automated testing and continuous integration in JavaScript with this easy guide."
tags: testing, javascript, devops, git
canonical_url: https://www.valentinog.com/blog/ci-js/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/y9u4dh59irlgy5ve1fz4.png
---

**Just crossed 5k follower on dev.to! Thank you everyone! What a fantastic community! Who's on Twitter too? Let's connect => [I'm here](https://twitter.com/gagliardi_vale)**.

_Is there a way to automate testing once the code leaves your computer? Learn continuous integration in JavaScript with this easy to read guide. (Featuring Github Actions!)._

## Automated testing and continuous integration in JavaScript: what you will learn

_**NOTE**: even if you don't like JavaScript I suggest reading the guide, continuous integration is not tied to any programming language in particular. The concepts you'll learn here apply to any other language or platform._

In this guide you'll learn:
 
- **what is automated testing**
- **what is continuous integration**
- how to apply **automated unit testing** and continuous integration to a simple JavaScript project

## Who this guide is for

If you know your way around JavaScript testing and want to **learn continuous integration** then this guide is for you. If you're still new to testing make sure to check out [Getting started with Jest for JavaScript testing](https://www.valentinog.com/blog/jest/) and then come back here.

The guide assumes a **good knowledge of version control**, Git and its terminology like commit and push. I suggest going through the first pages of [Git book](https://git-scm.com/book/en/v2) and then come back to this post if you're new to Git and version control.

Enjoy!

## What is automated testing?

**Testing your code is crucial**, we can all agree on that. These days testing on the local workstation is easy as pressing a button in your favorite IDE, but how do you **enforce tests when the code leaves your computer?** It's also easy to let some unit test slip off when a new member joins the team and he/she is not still expert, after all we're human.

So what? As you can see there's the need for a tool which runs your tests in an **automated fashion**.

**Automated testing** is **the ability to run tests without human intervention**, in an environment that most of the times is not your local workstation anymore.

**Automated testing** is achieved with the help of specific tools running inside a so called **continuous integration service.** Let's clarify **what is continuous integration** before taking a look at the tooling.

## What is continuous integration?

Since the inception of software and web development there had always been the need to address some specific issues:

- **enforce testing** before releasing to production
- **catch bugs before** a product is shipped
- get **rapid feedback** about the product

Since the early days there were pioneering attempts to streamline all these steps into a so called **pipeline**. A **pipeline** is made of a well defined **set of steps**, running one after another (or in parallel). Here's how a pipeline looks like:

**file changes** -> trigger an **automated test** -> **release to production**

With time all these techniques got "standardized" under the name of **continuous integration**. More broadly **continuous integration is a practice** which prescribes to continuously integrate **new code** and new features into a shared codebase.

The theory is that the team can get rapid feedback, adjust errors and fix bugs more quickly if **all the developers integrate changes into the same codebase, multiple time a day**. The fundamental pre-requisite for continuous integration is **version control**. Every line of code, every line of configuration, should stay under **version control**.

Easier said than done? Continuous integration is not an easy beast to tame, but these days there are neat tools for creating **pipelines** in a bunch of lines of code. So let's take a look at this modern tooling.

## Automated Testing and Continuous Integration in JavaScript: choosing a CI/CD service

At the core of a continuous integration (CI from now on) system there is a **pipeline**.

A **pipeline** is a set of steps **happening after a specific action**. By **action I mean a change in the codebase** which is ideally hosted on a version control server. Once upon a time "there was" SVN, but eventually Git became the most popular version control system.

Once the developer **changes some line of code**, makes a **commit** and **pushes** to a **repository** the **pipeline springs into action**. What happens next depends on how you configured your **CI service**. As part of the pipeline you can:

- test your code/software/UI
- build a production version and deploy it

But what's exactly a **CI service**? It's **a tool that runs your pipeline**. You can install it on a server (on premise) or rent from an external provider (as a service). There are many CI services these days, some free, some paid: I can name **TravisCI**, **CircleCI** and **GitLab CI**. Pick your own!

These days you may also want to get rid of FTP for "deploying". Most CI services are equipped with some sort of **CD capability**, short for **continuous delivery**. That's why we call these tools "CI/CD services".

Continuous delivery means releasing the software as soon as tests are passing. Continuous delivery is akin to continuous integration: after the automated test passes we can build a production artifact and then **automatically deploy to production.**

Hand tight, in the next sections you'll finally make some practice with CI.

## Automated Testing and Continuous Integration in JavaScript: configuring a CI/CD service, the workflow

Let's recap what we've learned so far. **Continuous integration is a practice** . The core principle prescribes that everything must be under version control and developers must integrate code daily into a shared codebase. 

Today continuous integration is practiced on CI/CD services where you create a so called pipeline which is triggered every time a developer makes changes.

The **pipeline takes care of building your code and running automated tests against it**. But **how does a CI/CD service work** in practice? Well, most of the times **you should configure the service** with a **configuration file**.

As I was writing this guide I got beta access to [Github actions](https://github.blog/2019-08-08-github-actions-now-supports-ci-cd/), a new Github feature which includes also a **CI/CD service** (free for public repos). Actions are directly integrated with Github repos and it's a great way to practice CI without relying on external services other than Github.

Most CI/CD service are configured through a [YAML file](https://en.wikipedia.org/wiki/YAML) which usually takes:

- the name of the pipeline (Github calls it "workflow")
- a list of jobs to do
- a list of steps for every job

If we want to translate the configuration to actual things to do we can configure the CI service for:

- setting up a JavaScript environment (mostly Node.js)
- installing the dependencies for the project
- optionally building the project
- running automated tests

In the next section we'll **configure a Github workflow for automating a couple of unit tests**. Before getting to the next section take some time to look at the [Workflow syntax for GitHub Actions](https://help.github.com/en/articles/workflow-syntax-for-github-actions) to make yourself comfortable with the syntax.

## Automated Testing and Continuous Integration in JavaScript: automated unit testing

In [Getting started with Jest for JavaScript testing](https://www.valentinog.com/blog/jest/) I covered the basics of testing and I left the reader with a simple JavaScript project. It has a bunch of unit tests for a function called filterByTerm.

Now let's clone the repo for adding a testing pipeline with Github workflow:

```bash
git clone git@github.com:valentinogagliardi/getting-started-with-jest.git
```

Move inside the project folder, install the dependencies and run a quick test:

```bash
cd getting-started-with-jest
npm i
npm test
```

These are exactly the steps that we're going to automate. Note that the **first test should always happen on your local workstation, never commit failing code**. It’s your responsibility to test the code before pushing to the repo. Now still in the repo create a new folder named **.github/workflows/**:

```bash
mkdir -p .github/workflows/
```

That folder is where Github expects to find your workflows (pipelines). Now we need a **configuration file for the workflow**, in YAML. Create a new file named **javascript.yml** in **.github/workflows/**.

I won't go every through line, the configuration should be easy to grok. With the steps we outline before:

- setting up a JavaScript environment (mostly Node.js)
- installing the dependencies for the project
- optionally building the project
- running automated tests

we can configure our first workflow like so:

```yaml
name: JavaScript workflow

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - name: Use Node.js 12.x
      uses: actions/setup-node@v1
      with:
        node-version: "12.x"
    - name: npm install, and test
      run: |
        npm install
        npm test
      env:
        CI: true
```

The workflow has a name, "JavaScript workflow", runs on every **push**, and as a result it creates a virtual Ubuntu environment with Node.js 12.x (see the steps above).

Not let's make a commit, note that the workflow file should be pushed to the repo:

```bash
git add .github/
git commit -m  "Configuring a Github workflow"
git push origin HEAD
```

Now the **workflow should run** and I can confirm that it went well by going to the tab **Actions** on Github:

![Github workflow test passing](https://thepracticaldev.s3.amazonaws.com/i/ocnw9y04jqyi3fmno1rk.png)

Test passing! Believe it or not this is all it takes to **start with automated testing and continuous integration** in JavaScript, with a bit of help from Github.

Of course real world projects will have different requirements and use **more complex workflow configurations**. But my point is that **with the tools we have today there should be no more excuses for not practicing continuous integration and automated testing**.

I suggest going through the documentation on Github for exploring what workflow have to offer.

## Conclusions and where to go from here

Continuous integration was first theorized in 1991 and later adopted by an ever growing number of teams and software developers all over the world. 

**Continuous integration is a discipline**, more than a practice, it requires a complete shift in your approach to software and web development. But with the sacrifice of adopting CI/CD come a lot of perks.

Continuous integration builds on the following core principles:

- code and configuration must stay under version control
- everything should be automatically testable
- if the test breaks then we must stop and fix the bug

Today continuous integration is made dead simple by a growing number of CI/CD services like Gitlab CI, Bitbucket pipelines, CircleCI, and Github workflow.

But is continuous integration really worth it? Considering **how simple is to set up a build/test pipeline today** there should be no more excuses for avoiding CI/CD, even when a project has a short-ish lifespan.

So where to go from here? After having learned about automated unit testing with this simple example try to **automate some UI test** in a Github workflow. (Or in your tool of choice). What steps should your YAML file take? For UI testing I strongly recommend using [Cypress](https://www.valentinog.com/blog/cypress/), you'll have fun.

Thanks for reading and stay tuned!