Story on how to use Wiremock to run CI on Github with Github Actions
This story setup a basic Django project using Docker and Docker Compose and then use Wiremock to run tests against a stubbed external API, both locally and on Github via Github Actions.
Prerequisites
I won't be showing everything in detail here but rather focus on what is relevant for this story, eg. docker-compose and github actions.
This will not be a complete from zero to hero tutorial, rather I'll assume that you know enough basic Django and Docker to be able to apply the shown yourself.
requirements.txt
asgiref==3.5.0
attrs==21.4.0
backports.zoneinfo==0.2.1
certifi==2021.10.8
charset-normalizer==2.0.12
Django==4.0.4
gunicorn==20.1.0
idna==3.3
iniconfig==1.1.1
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyparsing==3.0.8
pytest==7.1.1
pytest-django==4.5.2
requests==2.27.1
sqlparse==0.4.2
tomli==2.0.1
urllib3==1.26.9
docker-compose.yml
version: '3.7'
services:
django:
restart: always
build:
dockerfile: ./docker/Dockerfile
context: .
environment:
- DEBUG=1
- PYTHONDONTWRITEBYTECODE=1
- PYTHONUNBUFFERED=1
- ENV=DOCKER_LOCAL
- PORT=8000
ports:
- 8000:8000
volumes:
- .:/app
command: /usr/local/bin/gunicorn config.wsgi:application -w 2 -b :8000 --reload
wiremock:
image: wiremock/wiremock
ports:
- "8080:8080"
- "8443:8443"
volumes:
- ./wiremock:/home/wiremock
Dockerfile
FROM python:3.8
ARG APP_USER=appuser
RUN groupadd -r ${APP_USER} && useradd --no-log-init -r -g ${APP_USER} ${APP_USER}
EXPOSE 8000
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DEBUG 0
RUN apt-get update && apt-get install
RUN apt-get install -y \
libpq-dev \
libmariadb-dev-compat \
libmariadb-dev \
gcc git \
&& apt-get clean
RUN pip install -U pip
COPY ./requirements.txt /app/requirements.txt
RUN python -m pip install -r /app/requirements.txt
COPY . /app/
RUN mkdir -p /app/media
RUN mkdir -p /app/staticfiles
RUN chown -R ${APP_USER}:${APP_USER} /app/media
RUN chown -R ${APP_USER}:${APP_USER} /app/staticfiles
.github/workflows/push.yml
name: Python application
on:
push:
branches: [ master ]
jobs:
build_and_test:
runs-on: ubuntu-latest
services:
wiremock:
image: wiremock/wiremock
ports:
- 8080:8080
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8
uses: actions/setup-python@v3
with:
python-version: 3.8
- name: curl
run: sudo apt-get install -y curl
- name: import stubs to wiremock
run: curl -v -d @./wiremock/mappings/externalapi-stubs.json http://localhost:8080/__admin/mappings/import
- name: install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run migrations
run: python manage.py migrate
env:
ENV: GITHUB_ACTION_CI
- name: Run tests with pytest
run: pytest
env:
ENV: GITHUB_ACTION_CI
pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = config.settings
# -- recommended but optional:
python_files = tests.py test_*.py *_tests.py
company/tests.py
from django.test import TestCase
import requests
def test_get_the_api_response():
url = "http://localhost:8080/helloworld"
r = requests.get(url)
assert r.status_code == 200
assert r.text == "hello world"
wiremock/mappings/externalapi-stubs.json
{
"mappings" : [ {
"id" : "f5d37aa8-e436-491a-8e80-570f55b34d14",
"name" : "hello world",
"request" : {
"url" : "/helloworld",
"method" : "GET"
},
"response" : {
"status" : 200,
"body" : "hello world",
"headers" : { }
},
"uuid" : "f5d37aa8-e436-491a-8e80-570f55b34d14",
"persistent" : true,
"priority" : 5
} ],
"meta" : {
"total" : 1
}
}