Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Automating Tests with GitHub Actions CI Pipeline

Introduction

In our previous lesson, we explored Test-Driven Development (TDD), a powerful practice that places testing at the heart of the development process. You've now built a comprehensive understanding of writing unit, integration, and end-to-end tests for both your Spring Boot backend and React frontend. However, writing tests is only half the battle; ensuring they run consistently and automatically is what truly safeguards your codebase.

This lesson is the capstone of our module on software testing. We will bridge the gap between writing tests and automating them by setting up a Continuous Integration (CI) pipeline. You will learn how to configure GitHub Actions to automatically build your application and run your entire test suite every time you push new code. This practice is a non-negotiable standard in modern software development and a critical skill for any developer aspiring to a senior role.

1. What is Continuous Integration?

At its core, Continuous Integration (CI) is a DevOps practice where developers regularly merge their code changes into a central repository, after which automated builds and tests are run. The goal is to catch integration bugs early, improve code quality, and make the development process more efficient. Instead of running tests manually on your local machine, a CI server takes on that responsibility, providing a consistent and reliable feedback loop.

GitHub Actions is a powerful and flexible platform built directly into GitHub that allows you to automate these workflows. A CI pipeline is just one of many workflows you can create. The typical flow, as shown in the diagram below, involves a developer committing code, which triggers the CI pipeline to automatically build the code and run tests.

A conceptual overview of a CI pipeline. A code commit triggers an automated sequence of building, testing, and packaging the application.

To get a clear understanding of what GitHub Actions is and the problems it solves, the following video provides an excellent high-level introduction.

GitHub Actions Tutorial - Basic Concepts and CI/CD Pipeline with Docker

This segment from the "GitHub Actions Tutorial" by TechWorld with Nana explains the purpose of GitHub Actions beyond just CI/CD.

Watch the introduction from the beginning. Focus on the idea of automating developer workflows and how CI/CD is a key example of this.

2. The Anatomy of a GitHub Actions Workflow

To build a CI pipeline, you need to understand the basic building blocks of GitHub Actions. These are defined in a YAML file that you place in your repository's .github/workflows/ directory.

The key concepts are:

  • Workflow: The top-level automated process. You can have multiple workflows in a repository.
  • Event: A specific activity that triggers a workflow, such as a push to a branch or a pull_request being opened.
  • Job: A set of steps that execute on a specified runner. By default, jobs run in parallel.
  • Runner: A server that executes your jobs. GitHub provides runners with different operating systems like Ubuntu, Windows, and macOS.
  • Step: An individual task within a job. A step can either run a shell command (run) or use a pre-built, reusable component called an Action (uses).
  • Action: A reusable unit of code that performs a common task, like checking out your repository (actions/checkout) or setting up a specific version of Java (actions/setup-java).

The next segment of the video provides a fantastic walkthrough of a sample workflow file, explaining how these components fit together.

GitHub Actions Tutorial - Basic Concepts and CI/CD Pipeline with Docker

The presenter breaks down the syntax of a basic workflow file, explaining each of the core concepts we just discussed.

Watch the detailed explanation from this timestamp. Pay close attention to the distinction between the uses keyword for actions and the run keyword for commands.

3. CI Pipeline for a Spring Boot Project

Let's apply these concepts to your Spring Boot backend. You will create a workflow that checks out your code, sets up the Java environment, and runs your test suite using Maven or Gradle.

To do this, you would create a file named ci.yml (or similar) inside the .github/workflows/ directory of your Spring Boot project repository.

The following article provides a detailed guide. We will focus specifically on the sections that configure the build and test process.

Step‑by‑Step Guide to Spring Boot CI/CD Using GitHub ...

This guide walks through creating a full CI/CD pipeline. For this lesson, we will focus only on the CI part: building and testing.

First, read the introductory sections to understand the basics: What is GitHub Action gives a good summary. The flow explains where to place the YAML file. The sections on Events and Jobs explain the on and jobs keywords. Next, focus on the section "Test the project". This section details the exact steps needed to run the unit tests in a Spring Boot application.

Here is a consolidated YAML configuration for a simple build-and-test workflow for a Maven-based Spring Boot project. This combines the compile and test steps into a single job for simplicity.

File: .github/workflows/ci.yml

name: Java CI with Maven

on:
  push:
    branches: [ "main", "develop" ]
  pull_request:
    branches: [ "main", "develop" ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin' # A popular open-source distribution of Java

    - name: Cache Maven packages
      uses: actions/cache@v4
      with:
        path: ~/.m2/repository
        key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
        restore-keys: |
          ${{ runner.os }}-maven-

    - name: Build and Test with Maven
      run: ./mvnw -B test # '-B' runs Maven in non-interactive (batch) mode

This workflow will trigger on any push or pull request to your main or develop branches. It checks out the code, sets up Java 17, caches dependencies to speed up future runs, and finally executes ./mvnw -B test to compile the code and run all your JUnit tests.

4. CI Pipeline for a React Project

The process for your React frontend is conceptually the same, but the specific tools and commands differ. Here, you'll use actions/setup-node and npm commands.

The following article provides a clear, concise guide to setting this up.

Build and Test React app with GitHub Actions

This article is a focused tutorial on creating a CI pipeline for a React application.

Read the section explaining how to update the workflow file. Pay special attention to the strategy block for defining Node.js versions and the final run step that uses npm ci, npm run build, and npm test. The article also provides a helpful explanation of the difference between npm ci and npm install. Then, review the complete yml file to see how all the pieces come together.

Here is a complete YAML configuration for a React project testing workflow.

File: .github/workflows/ci.yml

name: React CI

on:
  push:
    branches: [ "main", "develop" ]
  pull_request:
    branches: [ "main", "develop" ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [18.x] # Use the Node.js version relevant to your project

    steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm' # This caches npm dependencies

    - name: Install dependencies
      run: npm ci

    - name: Run tests
      run: npm test

This workflow runs on pushes and pull requests to main or develop. It sets up Node.js 18, installs dependencies using npm ci (which is faster and more reliable for CI environments), and then runs your test suite with npm test.

5. Viewing the Results

Once you commit and push your workflow file to GitHub, the pipeline will run automatically. You can view its progress and results in the "Actions" tab of your repository.

The GitHub Actions UI showing a list of workflow runs. A green checkmark indicates success, while a red 'X' indicates failure. You can click on any run to see the detailed logs for each step.

If a test fails, the Run tests step will fail, causing the entire job to fail. You can click into the logs for that step to see the exact test output, which will tell you which assertion failed. This immediate feedback is what makes CI so valuable for maintaining code quality.

Practical Application

Your task is to implement a CI pipeline for one of the projects you've been working on during this course.

  1. Choose a Project: Select either your Spring Boot backend or your React frontend project that you have already written tests for.
  2. Create the Workflow File: In your chosen project's repository, create the .github/workflows/ci.yml file.
  3. Add the Configuration: Copy the appropriate YAML configuration from this lesson (either the Spring Boot or React example) into your ci.yml file. Adjust the Java or Node.js version if necessary to match your project's requirements.
  4. Commit and Push: Commit the ci.yml file and push it to your main or develop branch on GitHub.
  5. Observe the Run: Navigate to the "Actions" tab in your GitHub repository. Watch your workflow trigger and execute. Confirm that it passes with a green checkmark.
  6. Test the Failure Case (Optional but Recommended): To see the full feedback loop in action, intentionally modify a test so it fails (e.g., change an expected value to something incorrect). Commit and push this change. Observe the workflow run again, but this time it should fail. Click into the logs to find the error message from your test runner. Then, fix the test and push again to see it turn green.

This exercise provides direct, practical experience in setting up one of the most fundamental automation practices in modern software engineering.

Conclusion

Congratulations on completing the "Software Testing and Quality Assurance" module! You have progressed from knowing nothing about testing to mastering unit, integration, and end-to-end tests, adopting the TDD mindset, and finally, automating your entire test suite with a CI pipeline. This automation is the safety net that enables teams to move fast without breaking things—a core competency for a senior developer.

Key Takeaways:

  • Continuous Integration (CI) automates the building and testing of code every time a change is made, providing rapid feedback.
  • GitHub Actions is a platform for automating developer workflows using YAML files stored within your repository.
  • A workflow is triggered by events (like push) and consists of one or more jobs, which are made up of steps.
  • The run keyword executes shell commands (e.g., npm test), while the uses keyword leverages pre-built actions (e.g., actions/checkout).

With a solid foundation in ensuring code quality, we will now shift our focus from code to process. In the next module, Agile Mastery and Technical Project Management, you will learn the principles and practices that high-performing teams use to deliver value efficiently, starting with the Agile Manifesto and the Scrum framework.

Can't find a good explanation? Sign up and we'll make it for you

Sign up