Testing Django Applications




Honza Král


Follow me: @honzakral
E-mail me: honza.kral@gmail.com
Why Test?
You already do!
Whenever you
●   open your browser to look at the result
●   run some part of your code in a console
●   l...
Be lazy!

Let the computer do the boring work.
Even if you are perfect
    programmers (which you are not)

Tests will make you fearless of:
●   deployment (will this wo...
Terminology
●   Unit tests
●   Integration tests
●   Acceptance tests
●   Performance tests
●   Load tests
●   Stress test...
Unit tests
from unittest import TestCase

class TestInterview(TestCase):
  def setUp(self):
     self.interview = Intervie...
Unit tests
●   No interaction with other components
    ●   Including DB
●   Fast
●   Tied to the code
●   Testing small p...
Integration tests
from django.test import TestCase

class TestInterview(TestCase):
  def setUp(self):
     self.interview ...
Integration tests
●   Test how components cooperate together
●   Most common tests in Django apps
●   Usually slower and c...
Testability
(unit) testability
●   avoid side effects
●   separate components
●   only accept parameters you need
    ●
        reques...
Separate components (views)
def my_view(request, some_id, action, ...):
  main_model = get_object_or_404(M, pk=some_id)
  ...
Class-based views FTW!
class MyView(object):
  def get_objects(self, some_id, action):
     ...
  def render_response(self...
Separate components (template tags)
def test_parse_fails_on_too_few_arguments(self):
  self.assertRaises(
     TemplateSyn...
Testing templatetags
from unittest import TestCase

class TestRenderTag(TestCase):
  def setUp(self):
     self.template =...
Testing models
Try to avoid DB

def test_taller_img_gets_cropped_to_ratio(self):
     format = Format(
       max_height=1...
Populating test DB
●   fixtures only work for static data
●   natural keys FTW!
●   use factories when fixtures aren't eno...
Testing forms
from unittest import TestCase

class TestPaymentAssesmentFormSet(TestCase):
  def setUp(self):
     self.dat...
Tests alone are not enough!
Infrastructure
●   simple and convenient way to run tests
●   fast tests (or way to run just part of the suite)
●   never ...
Other requirements
●   when test fails you must know what went wrong
    ●   no doctests
    ●   descriptive test names
  ...
Happy hour
If you have done your tests right, you will get
extras:
●   convenient way to bootstrap your application
●   no...
?
Thanks for listening




Honza Král


Follow me: @honzakral
E-mail me: honza.kral@gmail.com
Upcoming SlideShare
Loading in …5
×

Testing Django Applications

2,460 views
2,339 views

Published on

Talk given at euro djangocon 2010

Published in: Technology, Education
0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,460
On SlideShare
0
From Embeds
0
Number of Embeds
73
Actions
Shares
0
Downloads
39
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

Testing Django Applications

  1. 1. Testing Django Applications Honza Král Follow me: @honzakral E-mail me: honza.kral@gmail.com
  2. 2. Why Test?
  3. 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?
  4. 4. Be lazy! Let the computer do the boring work.
  5. 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?
  6. 6. Terminology ● Unit tests ● Integration tests ● Acceptance tests ● Performance tests ● Load tests ● Stress tests ● UX tests ● .........
  7. 7. Unit tests from unittest import TestCase class TestInterview(TestCase): def setUp(self): self.interview = Interview( ... ) def test_ask_indicators_when_active(self): self.assertEquals( True, self.interview.asking_started()) self.assertEquals( False, self.interview.asking_ended()) self.assertEquals( True, self.interview.can_ask())
  8. 8. Unit tests ● No interaction with other components ● Including DB ● Fast ● Tied to the code ● Testing small portion of the code
  9. 9. Integration tests from django.test import TestCase class TestInterview(TestCase): def setUp(self): self.interview = Interview.objects.create( ...) def test_unanswered_questions(self): q = Question.objects.create( interview=self.interview, content='What ?') self.assertEquals( [q], self.interview.unanswered_questions())
  10. 10. Integration tests ● Test how components cooperate together ● Most common tests in Django apps ● Usually slower and cover more code ● Important to have
  11. 11. Testability
  12. 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. 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. 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)
  15. 15. Separate components (template tags) 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)
  16. 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. 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. 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)
  19. 19. Testing forms 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())
  20. 20. Tests alone are not enough!
  21. 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. 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. 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!
  24. 24. ?
  25. 25. Thanks for listening Honza Král Follow me: @honzakral E-mail me: honza.kral@gmail.com

×