You maybe alredy familiar with two well known types of tests: unit tests and integration tests. Unit tests are used for test a very small unit of code, such as a single method or function. Integration tests are used for whole application, from invocation to response. They check whether the tested units behave correctly as a group.
In big project tests are good habit. Without properly testing your code, you will never know if the code works as it should. If you employ test you will have more confidence in your code.
We will test models, views and forms at django app. The test app has following structure:
Model to test
# vim models.py
from django.db import models
class Animal(models.Model):
title = models.CharField('Title', max_length=50)
weight = models.PositiveIntegerField('Weight')
def __unicode__(self):
return self.title
We will use the following settings for our test. It uses sqlite3 and disabled migrations for performance.
from settings import *
COMPRESS_ENABLED = False
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3'
}
}
SOUTH_TESTS_MIGRATE = False
Test models
# vim test/test_models.py
from django.test import TestCase
from animals.models import Animal
class AnimalTest(TestCase):
def test_animal_creation(self):
animal = Animal.objects.create(title='Lion', weight=65)
self.assertTrue(isinstance(animal, Animal))
self.assertEqual(animal.__unicode__(), animal.title)
Run test
python manage.py test --settings=dj16.test_settings animals
Test views
Simple test view for HTTP success status and appereance text in page
# vim test/test_views.py
from django.test import TestCase
from django.core.urlresolvers import reverse
from animals.models import Animal
class AnimalTest(TestCase):
def test_animal_list_view(self):
animal = Animal.objects.create(title='Lion', weight=65)
url = reverse('animals')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertIn(animal.title, response.content)
#self.assertContains(response, animal.title)
#self.assertQuerysetEqual(response.context['animals'], [''])
Run test
python manage.py test --settings=dj16.test_settings animals -v 2
Test application functionality with selenium
# vim test/test_views.py
from django.test import LiveServerTestCase
from django.core.urlresolvers import reverse
from selenium.webdriver.firefox.webdriver import WebDriver
from animals.models import Animal
class AnimalSeleniumTest(LiveServerTestCase):
@classmethod
def setUpClass(cls):
cls.selenium = WebDriver()
super(AnimalSeleniumTest, cls).setUpClass()
@classmethod
def tearDownClass(cls):
cls.selenium.quit()
super(AnimalSeleniumTest, cls).tearDownClass()
def test_animal_add_view(self):
self.selenium.get(self.live_server_url + reverse('animal_add'))
self.selenium.find_element_by_id('id_title').send_keys('Lion')
self.selenium.find_element_by_id('id_weight').send_keys('57')
self.selenium.find_element_by_id('btn_submit').click()
self.selenium.get(self.live_server_url + reverse('animals'))
ul = self.selenium.find_element_by_tag_name('ul')
self.assertIn('Lion', ul.text)
Run test
python manage.py test --settings=dj16.test_settings --liveserver=localhost:8000 animals -v 2
Test forms
# vim test/test_forms.py
from django.test import TestCase
from animals.models import Animal
from animals.forms import AnimalAddForm
class AnimalTest(TestCase):
def test_animal_valid_form(self):
animal = Animal.objects.create(title='Lion', weight=65)
data = {'title': animal.title, 'weight': animal.weight}
form = AnimalAddForm(data=data)
self.assertTrue(form.is_valid())
Coverage
Install coverage and add coverage to your INSTALLED_APPS
pip install coverage
Run coverage
coverage run manage.py test animals -v 2
Build report to see what remain to test
coverage html --include='animals/*'
or in terminal
coverage report --include='animals/*'