Automatically run tests & linters with CI!
Tags: github, opensource, python
Published: 2023-11-16 04:15:31

This week, I am using **Continuous Integration** to automatically lint and test [my open source project](https://github.com/kliu57/go-go-web) whenever the code is pulled or pushed to GitHub!

[Continuous Integration](https://docs.github.com/en/actions/automating-builds-and-tests/about-continuous-integration) (CI) is a practice of committing code frequently and with every commit the code is built and tested (using unit tests, style checkers, etc.) If every time code is pushed or pulled all these tests are run, we can catch bugs early and maintain good coding convention. This is especially important for open source projects, where contributors may forget to run linters or tests prior to making a PR.

This automation can be done with [GitHub Actions](https://github.com/features/actions). This `.github/workflows/ci.yml` file below is all that is needed to trigger GitHub Actions to do the following:

- run `Pylint` to evaluate the code and only pass if the score is above 9.0/10
- run previously set up `pytest` unit tests

```
# .github/workflows/ci.yml

# Continuous Integration (CI) Workflow
name: Lint and Run Unit Tests

# This workflow will run unit tests whenever we push commits to the
# main branch, or whenever there's a pull request to the main branch
on:
  pull_request:
    branches:
      - main
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - name: Set up Python 3.12
        uses: actions/setup-python@v3
        with:
          python-version: '3.12' 

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pylint
          pip install pytest
          <any other installations need to make your code run>

      - name: Test with pytest
        run: |
          pytest

      - name: Analysing the code with pylint
        run: |
          pylint --fail-under=9.0 <dir> <dir> <file>
```

This is just a starter file I have made, but you can find more starter files [here](https://github.com/actions/starter-workflows/tree/main/ci) for `python` and **many other languages**.

After I push this .yml file to GitHub, I can see that every time I push code to my repo, it triggers GitHub Actions.

![GitHub Actions page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owm2pj5bkmcaiju9jfje.png)

If any of my `pytest` unit tests failed, the workflow run will show with a red `x` and if they all pass the workflow run will show a green `check`. Clicking a failed run allows you to see more details. You can check [this run](https://github.com/kliu57/go-go-web/actions/runs/6874249402/job/18695577518) I failed on purpose just to test my CI workflow.

In the [details of a run](https://github.com/kliu57/go-go-web/actions/runs/6887388356/job/18734510732), you can also see the `Pylint` score.

![Pylint details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/me4t9l4l44dbr8mgibzd.png)

## How GitHub Actions can help you review PRs

When a new PR is made on your repo, GitHub Actions automatically run, helping you to review the PR!

This is what will appear under the PR if the PR failed the unit tests:
![failed workflow PR](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d7vjkw1vwoggk3k40p2d.png)

Once the contributor fixes the code and commits the fix to their branch:
![passed workflow PR](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4hwvg8t5nj26jpwqerra.png)

## Contributing tests to project in C++

Another task I completed this week in open source was contributing to [Roy](https://dev.to/rjwignar)'s [project](https://github.com/rjwignar/ctil) by adding some unit tests. This was my first time contributing open source code in C++, and I am glad that Roy reached out to collab with me since I've been mostly working with Python/Java/JavaScript these days and I wanted to step out of my comfort zone. Roy created an [issue](https://github.com/rjwignar/ctil/issues/13) for the tests he required and I submitted my [PR](https://github.com/rjwignar/ctil/pull/14) which he later merged :)

Roy's project uses [Google Test](https://github.com/google/googletest), a C++ testing framework. His testing setup is similar to mine as we both keep source files in one directory and tests in another. The key difference is that I can run the tests using the Visual Studios run button. It was fairly easy to write the new tests as there were existing ones that I could reference to check the syntax!

Here is a snapshot of the Visual Studios test setup:
![Visual Studios](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3muxi4nzgfbc5k6q0usl.png)

## Reflection

Setting up GitHub Actions using a YAML file was much easier than I had expected. If ever any unit tests fail or my lint evaluation score dropped, I could catch on right away by monitoring the GitHub Actions workflow run that is produced after every push. Lastly, when a contributor makes a PR on my repo, it automatically helps me review the PR by checking the `Pylint` score and running unit tests. In the future, I also plan on looking into using Git Hooks to autoformat my code when I commit!