Honza Král
@honzakral
Raise your hand if you:
Be Lazy! Let the computer do the boring work.
from unittest import TestCase
class TestInterview(TestCase):
def test_ask_indicators_when_active(self):
interview = Interview( ... )
self.assertEquals(True, interview.asking_started())
self.assertEquals(False, interview.asking_ended())
self.assertEquals(True, interview.can_ask())
No interaction with other components
- Including DB
Fast
Tied to the code
Testing small part of the code
from django.test import TestCase
class TestInterview(TestCase):
def test_unanswered_questions(self):
interview = Interview.objects.create(...)
q = Question.objects.create(interview=interview, content='What ?')
self.assertEquals([q], list(interview.unanswered_questions()))
def my_view(request, some_id, action, ...):
main_model = get_object_or_404(Model, pk=some_id)
other = main_model.method(action)
...
compute ... some ... data
...
return render_to_response(...)
To test you need to:
class MyView(object):
def get_objects(self, some_id):
return get_object_or_404(Model, pk=some_id)
def render_response(self, context):
return render_to_response(...)
def compute_data(self, m, action):
m.method(action)
...
return {'some': data}
def __call__(self, request, some_id, action, ...):
m = self.get_objects(some_id)
context = self.compute_data(m, action)
return self.render_response(context)
class BoxNode(template.Node):
def __init__(self, model, lookup):
self.model, self.lookup = model, lookup
def get_data(self, model, lookup):
return model.objects.get(** lookup)
def render(self, context):
data = self.get_data(self.model, self.lookup)
return data.title
def _parse_box(bits):
if (len(bits) != 4 or bits[2] != 'for') and ...:
raise template.TemplateSyntaxError(...)
...
return BoxNode(model=model, lookup={smart_str(bits[5]): bits[6]})
@register.tag('box')
def do_box(parser, token):
return _parse_box(token.split_contents())
from unittest import TestCase
class TestBoxParsing(TestCase):
def test_parse_fails_on_too_few_arguments(self):
self.assertRaises(TemplateSyntaxError, _parse_box, ['box', 'box_type', 'for'])
def test_parse_box_with_pk(self):
node = _parse_box( ['box', 'box_type', 'for', 'core.category', 'with', 'pk', '1'])
self.assertTrue(isinstance(node, BoxNode))
self.assertEquals('box_type', node.box_type)
self.assertEquals(Category, node.model)
self.assertEquals({'pk': 1}, node.lookup)
from unittest import TestCase
from mock import Mock
class TestBoxRendering(TestCase):
def test_box_renders_objects_title(self):
class MyBoxNode(BoxNode):
get_data = Mock(return_value=Article(title='Article 1'))
bn = MyBoxNode('type', Article, lookup=('pk', 1))
bn.get_data.assert_called_once_with(Article, {'pk': 1})
self.assertEquals('Article 1', bn.render({}))
from unittest import TestCase
class TestPaymentAssesmentFormSet(TestCase):
def setUp(self):
self.data = {...}
def test_formset_validates_valid_data(self):
fset = PaymentAssesmentFormSet(self.data)
self.assertTrue(fset.is_valid())
def test_fail_for_change_inside_a_month(self):
self.data['form-0-valid_to'] = '1.06.2009'
self.data['form-1-valid_from'] = '2.06.2009'
fset = PaymentAssesmentFormSet(self.data)
self.assertFalse(fset.is_valid())
@periodic_task(run_every=timedelta(hours=1))
def maintenance(now=None):
if now is None:
now = datetime.now()
site.maintenance(now)
for cube in base.cubes.values():
if cube._meta.maintenance:
cube.data.maintenance(now)
def test_custom_crop_box_is_used(self):
format = Format(max_height=100, max_width=100)
i = Image.new('RGB', (200, 200), "red")
i.putpixel((99, 99), 0)
f = Formatter(i, format, crop_box=(0,0,100,100))
i, crop_box = f.format()
self.assertEquals((0,0,100,100), crop_box)
self.assertEquals((100, 100), i.size)
self.assertEquals((0,0,0), i.getpixel((99,99)))
def get_user(password='secret', profile_data={}, commit=False, ** kwargs):
defaults = {'email': 'someone@example.com', 'username': 'some_username'}
defaults.update(kwargs)
u = User(username=username, ** defaults)
u.set_password(password)
u._password = password # in case a test wants the clear-text password to login
if commit:
u.save()
if hasattr(settings, 'AUTH_PROFILE_MODULE'):
ProfileClass = get_profile_model()
p = ProfileClass(user=u, ** profile_data)
u._profile_cache = p
if commit:
p.save()
return u
def get_article(commit=False, ** kwargs):
defaults = {'title': 'A1', 'text': 'Lorem ipsum ' * 10, ...}
defaults.update(kwargs)
if 'author' not in defaults:
defaults['author'] = get_user(commit=commit)
a = Article(** defaults)
if commit:
a.save()
return a
import os, sys
from os.path import join, pardir, abspath, dirname
os.environ['DJANGO_SETTINGS_MODULE'] = 'test_project.settings'
# add test_project to python path
sys.path.insert(0, abspath(join(dirname(__file__), pardir)))
test_runner, old_config = None, None
def setup():
global test_runner, old_config
from django.test.simple import DjangoTestSuiteRunner
test_runner = DjangoTestSuiteRunner()
test_runner.setup_test_environment()
old_config = test_runner.setup_databases()
def teardown():
test_runner.teardown_databases(old_config)
test_runner.teardown_test_environment()
Treat it as such.
Honza Král
@honzakral