3. You already do!
Whenever you
● open your browser to look at the result
● run some part of your code in a console
● look into the database directly
Is it fun?
5. Even if you are perfect
programmers (which you are not)
Tests will make you fearless of:
● deployment (will this work?)
● refactoring (what will this break?)
● new developers (can I trust them?)
● regressions (didn't I fix this before?)
Why assume it's OK when you can test?
10. Integration tests
● Test how components cooperate together
● Most common tests in Django apps
● Usually slower and cover more code
● Important to have
12. (unit) testability
● avoid side effects
● separate components
● only accept parameters you need
●
request is bad
● be smart about transactions and models
● don't put busines logic into views (use models)
13. Separate components (views)
def my_view(request, some_id, action, ...):
main_model = get_object_or_404(M, pk=some_id)
other = main_model.method(action)
...
compute ... some ... data
...
return render_to_response(...)
● To test this you need to:
● define the template
● mock request or use test client
● access the database
● ...
14. Class-based views FTW!
class MyView(object):
def get_objects(self, some_id, action):
...
def render_response(self, context):
...
def compute_data(self, m1, m2):
...
def __call__(
self, request, some_id, action, ...):
m1, m2 = self.get_objects(some_id, action)
context = self.compute_data(m1, m2)
return self.render_response(context)
● now you can easily test individual methods
● or just the interesting ones (compute_data)
16. Testing templatetags
from unittest import TestCase
class TestRenderTag(TestCase):
def setUp(self):
self.template = template.Template(
'{% load myapp %}{% render var %}')
def test_does_not_escape_output(self):
c = template.Context({'var': '<html> ""'})
self.assertEquals(
'<html> ""', self.template.render(c))
17. Testing models
Try to avoid DB
def test_taller_img_gets_cropped_to_ratio(self):
format = Format(
max_height=100, max_width=100)
i = Image.new('RGB', (100, 200), "black")
f = Formatter(i, format)
i, crop_box = f.format()
self.assertEquals(
(0, 50, 100, 150), crop_box)
self.assertEquals((100, 100), i.size)
18. Populating test DB
● fixtures only work for static data
● natural keys FTW!
● use factories when fixtures aren't enough
def get_payment_assesment(stay, ** kwargs):
defaults = {
'modified_by':
User.objects.get_or_create(...),
'stay': stay,
...}
defaults.update(kwargs)
return PaymentAssesment.objects.create(
**defaults)
21. Infrastructure
● simple and convenient way to run tests
● fast tests (or way to run just part of the suite)
● never let your test suite break
● continuous integration
● reporting
● leaving this to the experts
(assuming they catch their flight)
22. Other requirements
● when test fails you must know what went wrong
● no doctests
● descriptive test names
● short tests touching minimal amount of code
● write even trivial tests as a starting point
● make sure tests work
23. Happy hour
If you have done your tests right, you will get
extras:
● convenient way to bootstrap your application
● no need for server/browser during development
● calmer nerves
● people will trust your work!