Automate Tests With GitHub Actions for Python

Deepjyoti Barman @deepjyoti30
Mar 26, 2021 6:11 AM UTC
Post cover

Since the addition of GitHub Actions, a lot of things, that previsouly we had to use third party services for, have become easier. Recently, an user raised an issue in my downloader-cli repository. He suggested that addition of tests would be greatly helpful. More importantly because that way when people make a PR, the tests would tell the developers if the PR can be accepted.

So, I decided to add some nice tests for my app. downloader-cli is written in Python and it is a small, simple, downloader library that features a highly customizable, responsive progressbar for the commandline.

How will it work

The idea is simple. We will add a GitHub workflow file. This file will have the details as to when and what to do. For the sake of this example, I will make the tests run when a push is made to the master branch or a pull request is made to the master branch.

In case you don't already know, GitHub's workflow files are written in YAML and are pretty simple to get started with.

You just need to create a directory named .github and a subdirectory inside that named workflows. Inside the subdirectory, you can add as many workflow files as you want, given that all of them follow proper syntax and are written in YAML.

Adding Conditions to run

We will create a file named tests.yml and add the basic conditions to make it run on PR's and Pushes.

name: Run tests

on:
  push:
    branches:
      - "master"
  pull_request:
    branches:
      - "master"

The above code does the following:

  • Add condition to run on push on branch master
  • Add condition to run on pull_request on branch master

Add the job

So once we tell GitHub about when to run the action, we also need to pass them some commands on what to do when running the action. These can be called as jobs. One action file can have multiple jobs and jobs can depend on other jobs so that they will run only after the job they depend on is run.

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        # Run in all these versions of Python
        python-version: [3.5, 3.6, 3.7, 3.8, 3.9]

    steps:
        # Checkout the latest code from the repo
      - name: Checkout repo
        uses: actions/checkout@v2
        # Setup which version of Python to use
      - name: Set Up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
        # Display the Python version being used
      - name: Display Python version
        run: python -c "import sys; print(sys.version)"
        # Install the package using the setup.py
      - name: Install package
        run: python setup.py install
        # Install pytest (you can use some other testing utility)
      - name: Install pytest
        run: |
          python -m pip install --upgrade pip
          pip install pytest
        # Run the tests. I'm using pytest and the file is in the tests directory.
      - name: Run tests
        run: pytest tests/test*

In the above code, we add a job with the name test.

  • This job runs-on the latest Ubuntu Version as deonoted by ubuntu-latest.
  • We are using the matrix strategy to run it for different python versions.

Then we have added a few steps. The steps do the following:

  • Checkout the latest code from the repo
  • Setup the python-version as passed by the matrix strategy.
  • Display the python version (just cross check).
  • Install the package. (In my case it is using the setup.py file.)
  • Install pytest.
  • Run the tests.

Push the code

Once you have the file setup, you can try try out the changes by pushing the code to the master branch.

Just do a push using git and go to GitHub and open the Actions tab. You will see a job running with the yellow indicator on the left. (The yellow means it is running).

Conclusion

If you want to take a look at the actions of my repo, you can check them here.

Also, GitHub Actions can be used for various automations. Most useful usecase (at least for me) being the ability to add CI/CD pipelines which have made a lot of my deployments painless. You can see an example of that in my ytmdl-web repo.

Also, in case you want to take a look at the file from my downloader-cli repo, you can check it here.

Discussion