Sooner or later during your development, you will need to deploy your code somewhere. Either cloud or your own servers. One of the best practices for seamless deployment to production is continuous integration. Until you are working alone you won’t need it really. But as your team grows it will help to develop and deploy your product faster.
In software engineering, continuous integration (CI) is the practice of merging all developers’ working copies to shared mainline several times a day. Grady Booch first proposed the term CI in his 1991 method, although he did not advocate integrating several times a day. Extreme programming (XP) adopted the concept of CI and did advocate integrating more than once per day – perhaps as many as tens of times per day.
Running Django tests in continuous integration pipeline
One of the important parts of continuous integration is running tests. It is the only way to know that new commits from your teammate didn’t break anything. You probably don’t want to develop something for 2 weeks and then suddenly realize: I broke half of the code. Therefore it makes sense to run tests in your CI pipeline on every git push. Practicing that, you will be notified of every failed test. You should also merge every production change into your feature branch. Tests in the CI pipeline will tell you if your changes + production changes work together.
Set up CircleCI
Firstly, go to CircleCI and sign up with your Github account. After you’ve done that, create a new repository on Github called django_circleci. Clone it and create Django project inside it (you can find the example project here):
django-admin.py startproject django_circleci .
Create a new app:
django-admin.py startapp example
After that, we can add our dummy test. Open example/tests.py and add a dummy test:
# example/tests.py
from django.test import TestCase
# Create your tests here.
class DummyTest(TestCase):
def test_dummy(self):
self.assertEqual(True, True)
Now we are able to run our tests locally:
python manage.py test
You should see output like this:
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Destroying test database for alias 'default'...
As we have done that, we are ready to add a CircleCI configuration. Inside the project, you need to add a directory named .circleci. Inside that folder, you need to create a YAML file called config.yml. Firstly, we need to define a version of the CircleCI configuration. Let’s add this to file which now looks like this:
# .circleci/config.yaml
version: 2.1
After that, we need to define a job that will run our Django tests.
# .circleci/config.yaml
version: 2.1
jobs:
tests:
docker:
- image: circleci/python:3.6.4
steps:
- checkout
- run: sudo chown -R circleci:circleci /usr/local/bin
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.6/site-packages
- restore_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
- run:
name: Install Dependencies
command: |
pip install --user -r requirements.txt
- save_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
paths:
- ".venv"
- "/usr/local/bin"
- "/usr/local/lib/python3.6/site-packages"
- run: python manage.py test
We have to define d which docker image to use for the environment in which we will run our tests:
docker:
- image: circleci/python:3.6.4
Then we define steps that will execute our tests. Firstly, we check out the code from Github. Then we install requirements/use cached ones. And then the tests are run. Read More Here.
- run: sudo chown -R circleci:circleci /usr/local/bin
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.6/site-packages
- restore_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
- run:
name: Install Dependencies
command: |
pip install --user -r requirements.txt
- save_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
paths:
- ".venv"
- "/usr/local/bin"
- "/usr/local/lib/python3.6/site-packages"
- run: python manage.py test
After that, we need to add a workflow definition to our configuration.
version: 2.1
jobs:
tests:
docker:
- image: circleci/python:3.6.4
steps:
- checkout
- run: sudo chown -R circleci:circleci /usr/local/bin
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.6/site-packages
- restore_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
- run:
name: Install Dependencies
command: |
pip install --user -r requirements.txt
- save_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
paths:
- ".venv"
- "/usr/local/bin"
- "/usr/local/lib/python3.6/site-packages"
- run: python manage.py test
workflows:
main:
jobs:
- tests
When you’ve done that. Add all files to git, commit and push to Github. After that, go to CircleCI and select your Github account. Find your new project on the list and click on its name. Then click the Start building button. After that select Add manually. After that, again click on Start building.
Congratulations, you’ve just run your Django tests on CircleCI.
Using PostgreSQL for Django tests
We’ve succeeded to run our Django tests on CircleCI but SQLite was used as a database. In production environments, you probably won’t use it. Instead, you will use some other SQL databases, for example, PostgreSQL. It makes sense that we use it in tests too. So edit Django settings file to look like this:
# django_circleci/settings.py
... other code ...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'example',
'USER': 'example',
'PASSWORD': 'example',
'HOST': 'localhost',
'PORT': '5432',
}
}
... other code ...
We need to edit CircleCI config too. We need to add database container. Add this to docker section:
- image: circleci/postgres:9.6.2-alpine
environment:
POSTGRES_USER: example
POSTGRES_PASSWORD: example
POSTGRES_DB: example
So our config now looks like this:
version: 2.1
jobs:
tests:
docker:
- image: circleci/python:3.6.4
- image: circleci/postgres:9.6.2-alpine
environment:
POSTGRES_USER: example
POSTGRES_PASSWORD: example
POSTGRES_DB: example
steps:
- checkout
- run: sudo chown -R circleci:circleci /usr/local/bin
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.6/site-packages
- restore_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
- run:
name: Install Dependencies
command: |
pip install --user -r requirements.txt
- save_cache:
key: deps9-{{ .Branch }}-{{ checksum "requirements.txt" }}
paths:
- ".venv"
- "/usr/local/bin"
- "/usr/local/lib/python3.6/site-packages"
- run: python manage.py test
workflows:
main:
jobs:
- tests
That’s it. Commit and push again. Check that your tests passed on CircleCI.
Happy coding!
Read more:
1 Comment
PyCharm tricks every Python developer should know - Jan Giacomelli · March 18, 2020 at 10:23 am
[…] Django tests on CircleCI […]