Database testing with ShiningPanda (1/2)
With ShiningPanda CI it has never been so easy to run tests against databases. Starting a database server on the fly is literally one click away from your job configuration!
Let's see how with this tutorial in two parts that describes how to test your existing projects on multiple databases:
- The first part deals with writing and running tests against databases,
- The second part deals with integration with Jenkins.
Sample project
This tutorial is based on the poll application from the Django tutorial.
It describes all the required steps to run your Django tests on multiple databases.
The source code can be found here. This sample project is organized as follow:
The following features are implemented:
- Poll management via the Django admin site,
- Vote submission.
Don't forget to install Django!
$ pip install Django
Testing tools
In this tutorial, the following tools are used:
- django-jenkins: a Django test runner dedicated to Jenkins,
- coverage: a tool for measuring code coverage of Python programs,
- pylint: analyzes Python source code looking for bugs and signs of poor quality.
Install them all by typing:
$ pip install django-jenkins coverage pylint
Write test
A good start is to have a look at Django documentation.
Then let's have a look on the models located in djangotutorial/polls/models.py
:
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def was_published_today(self):
return self.pub_date.date() == datetime.date.today()
Our goal in this tutorial is to test Poll.was_published_today
on multiple databases.
First create a tests
module in djangotutorial.polls
(a file djangotutorial/polls/tests.py
).
To write a test, just create a class that inherits from django.test.TestCase
and add as many test methods you want.
import datetime
from django.test import TestCase
from polls.models import Poll
class ModelsTest(TestCase):
def test_poll_was_published_today(self):
poll = Poll.objects.create(
question='ShiningPanda is awesome no?',
pub_date=datetime.datetime.now(),
)
self.assertTrue(poll.was_published_today())
Here we are adding a test_poll_was_published_today
methods that creates a new Poll
object with its publication date set to current date and time (pub_date=datetime.datetime.now()
) and then asserts that Poll.was_published_today
returns True
.
Now it's time to run this test!
Run tests
To run the test, just execute:
$ python djangotutorial/manage.py test polls
Creating test database for alias 'default'...
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Destroying test database for alias 'default'...
Note that polls
is the name of the application to test.
What about Jenkins?
Now we want this project to be ready for Jenkins.
Edit djangotutorial/settings.py
and add the following if
block at the end of it (don't forget to import os
):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'djangotutorial',
# Other parameters
}
}
# [...]
if os.getenv('JENKINS_URL', False):
INSTALLED_APPS += ('django_jenkins', )
PROJECT_APPS = ('polls', )
DATABASES['default'].update(dict(
ENGINE=os.getenv('DBA_SQL_DJANGO_ENGINE'),
USER=os.getenv('DBA_SQL_ADMIN'),
PASSWORD=os.getenv('DBA_SQL_ADMIN_PASSWORD'),
HOST=os.getenv('DBA_SQL_HOST'),
PORT=os.getenv('DBA_SQL_PORT'),
))
Let's have a look on this block:
if os.getenv('JENKINS_URL', False)
: activate this configuration only on Jenkins,INSTALLED_APPS += ('django_jenkins', )
: enabledjango_jenkins
features,PROJECT_APPS = ('polls', )
: list applications to test,DATABASES['default'].update(...)
: update database connection parameters from environment variables exported by Jenkins.
Now let's run tests by mocking Jenkins environment:
$ JENKINS_URL=1 DBA_SQL_DJANGO_ENGINE=django.db.backends.sqlite3 python djangotutorial/manage.py jenkins
Creating test database for alias 'default'...
.----------------------------------------------------------------------
Ran 1 test in 0.003s
OK
Destroying test database for alias 'default'...
Check that the reports
folder created:
$ ls reports
TEST-polls.tests.ModelsTest.xml coverage.xml pylint.report
It contains some useful data for Jenkins:
TEST-polls.tests.ModelsTest.xml
: test results,coverage.xml
: code coverage analysis,pylint.report
: static code analysis.
This project is now Jenkins ready!
What's next?
Check our next blog post out to have a look on how to integrate this project with Jenkins!