Upload
ericholscher
View
11.627
Download
1
Embed Size (px)
DESCRIPTION
Talk about where Testing is in Django, and how to get started doing it.
Citation preview
Django TestingEric Holscher
http://ericholscher.com
Django Testing
1Tuesday, May 5, 2009
How do you know?
• First 4 months of my job was porting and testing Ellington
• Going from Django r1290 to Django 1.0.
• Suite from 0 to 400 tests.
2Tuesday, May 5, 2009
30,000 Ft View
• State of testing in Django
• Why you should be testing
• How you start testing
• Useful tools
• Eventual Goals
3Tuesday, May 5, 2009
State of Django Testing
4Tuesday, May 5, 2009
assertTrue('Hello World', community.testing.status)
5Tuesday, May 5, 2009
Django 1.1
Making Testing Possible since 2009
6Tuesday, May 5, 2009
manage.py startapp creates a tests.py
7Tuesday, May 5, 2009
from django.test import TestCase
class SimpleTest(TestCase): def test_basic_addition(self): """ Tests that 1 + 1 always equals 2. """ self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2True"""}
8Tuesday, May 5, 2009
Fast Tests(Transactions)
9Tuesday, May 5, 2009
0
15
30
45
60
Django 1.0 Django 1.1
Ellington Test Speedup
Minutes (Lower is better)
10Tuesday, May 5, 2009
You now have no excuse.
11Tuesday, May 5, 2009
Why to test
12Tuesday, May 5, 2009
Scary13Tuesday, May 5, 2009
Less Scary14Tuesday, May 5, 2009
Not Scary15Tuesday, May 5, 2009
Peace of Mind16Tuesday, May 5, 2009
Code must adapt
17Tuesday, May 5, 2009
“It is not the strongest of the species that survives, nor the most intelligent, but the
one most responsive to change.”
- Charles Darwin
18Tuesday, May 5, 2009
Won’t somebody please think of the users?!
19Tuesday, May 5, 2009
Tests as Documentation
20Tuesday, May 5, 2009
Tests as Documentation
Test driven development +
Document driven development=
Test Driven Documentation
20Tuesday, May 5, 2009
“Code without tests is broken as designed”- Jacob Kaplan-Moss
21Tuesday, May 5, 2009
Dizzying Array of Testing Options
22Tuesday, May 5, 2009
What kind of test?
• doctest
• unittest
23Tuesday, May 5, 2009
Doctests
• Inline documentation
• <Copy from terminal to test file>
• Can’t use PDB
• Hide real failures
• “Easy”
24Tuesday, May 5, 2009
def parse_ttag(token, required_tags): """ A function to parse a template tag.
It sets the name of the tag to 'tag_name' in the hash returned.
>>> from test_utils.templatetags.utils import parse_ttag >>> parse_ttag('super_cool_tag for my_object as obj', ['as']) {'tag_name': u'super_cool_tag', u'as': u'obj'} >>> parse_ttag('super_cool_tag for my_object as obj', ['as', 'for']) {'tag_name': u'super_cool_tag', u'as': u'obj', u'for': u'my_object'}
""" bits = token.split(' ') tags = {'tag_name': bits.pop(0)} for index, bit in enumerate(bits): bit = bit.strip() if bit in required_tags: if len(bits) != index-1: tags[bit] = bits[index+1] return tags
25Tuesday, May 5, 2009
Unit Tests
• Use for everything else
• More rubust
• setUp and tearDown
• Standard (XUnit)
26Tuesday, May 5, 2009
import randomimport unittest
class TestRandom(unittest.TestCase):
def setUp(self): self.seq = range(10)
def testshuffle(self): # make sure the shuffled sequence does not lose any elements random.shuffle(self.seq) self.seq.sort() self.assertEqual(self.seq, range(10))
if __name__ == '__main__': unittest.main()
27Tuesday, May 5, 2009
Django TestCase
• Subclasses unittest
• Fixtures
• Assertions
• URLs
28Tuesday, May 5, 2009
Test Client
• Test HTTP Requests without server
• Test Views, Templates, and Context
29Tuesday, May 5, 2009
from django.contrib.auth.models import Userfrom django.test import TestCasefrom django.core import mail
class PasswordResetTest(TestCase): fixtures = ['authtestdata.json'] urls = 'django.contrib.auth.urls'
def test_email_not_found(self): "Error is raised if the provided email address isn't currently registered" response = self.client.get('/password_reset/') self.assertEquals(response.status_code, 200) response = self.client.post('/password_reset/', {'email': '[email protected]'}) self.assertContains(response, "That e-mail address doesn't have an associated user account") self.assertEquals(len(mail.outbox), 0)
30Tuesday, May 5, 2009
What flavor of test?
• Unit
• Functional
• Browser
31Tuesday, May 5, 2009
Unit test
• Low level tests
• Small, focused, exercising one bit of functionality
32Tuesday, May 5, 2009
Regression test
• Written when you find a bug
• Proves bug was fixed
• Django Tickets
33Tuesday, May 5, 2009
Functional
• “Black Box Testing”
• Check High Level Functionality
34Tuesday, May 5, 2009
Functional Testing Tools
• Twill
• Django Test Client
• ...
35Tuesday, May 5, 2009
Ellington
• Lots of different clients
• Need to test deployment (Functional)
36Tuesday, May 5, 2009
go {{ site.url }}/marketplace/search/formvalue 1 q pizzasubmitcode 200
37Tuesday, May 5, 2009
38Tuesday, May 5, 2009
Pretty Functional Tests39Tuesday, May 5, 2009
Can test
• All sites on a server
• All sites of a certain type
• A single problemed client
• A test across all sites
40Tuesday, May 5, 2009
Browser tests
• Run tests in a web browser
• Check compatibility of design
• Basically an IE sanity check
• Only real way to test JS, AJAX, CSS
41Tuesday, May 5, 2009
Browser Testing Tools
• Windmill
• Selenium
42Tuesday, May 5, 2009
43Tuesday, May 5, 2009
Other kinds of testing
• Spiders
• Fuzz testing
• Load testing
• Prayer
44Tuesday, May 5, 2009
Where do I start?
45Tuesday, May 5, 2009
Fixed a bug
46Tuesday, May 5, 2009
Poking at code on the command line
47Tuesday, May 5, 2009
Pony turned Horse
48Tuesday, May 5, 2009
Now what?
49Tuesday, May 5, 2009
Start with a regression test or a functional test
50Tuesday, May 5, 2009
Use unittest unless you have a reason not to!
51Tuesday, May 5, 2009
Use the data, Luke
• Use data as a pivot
• Fixtures means you use Unit Tests
• Creation on the command line, Doctests
52Tuesday, May 5, 2009
Creating Fixtures
• ./manage.py dumpdata <app>
• ./manage.py makefixture Model[x:y]
• Follows relations
• By Hand
53Tuesday, May 5, 2009
TestShell
./manage.py testshell <fixture>
54Tuesday, May 5, 2009
Making Functional tests
• Usually a relatively annoying process
• Testmaker makes it easy.
• ./manage.py testmaker <app>
• Simply browse and your session is recorded.
55Tuesday, May 5, 2009
Testing your views generally gets you the
most coverage.
56Tuesday, May 5, 2009
80% Case
57Tuesday, May 5, 2009
When > Where
58Tuesday, May 5, 2009
Tools
59Tuesday, May 5, 2009
Coverage
60Tuesday, May 5, 2009
61Tuesday, May 5, 2009
Mock Objects
• http://www.voidspace.org.uk/python/mock/
62Tuesday, May 5, 2009
import unittestfrom mock import Mock from templatetags.cms_tags import if_link_is_active, IsActiveNode class TestIsActiveTag(unittest.TestCase): def test_returns_correct_node_type(self): token = Mock(methods=['split_contents']) token.split_contents.return_value = ('if_link_is_active', 'bar') self.assertEqual(type(if_link_is_active(Mock(), token)), IsActiveNode)
63Tuesday, May 5, 2009
Custom Test Runners
64Tuesday, May 5, 2009
Django Test Extensions
• Gareth Rushgrove
• Extra Assertions
• Coverage and XML Test Runners
• http://github.com/garethr/django-test-extensions
65Tuesday, May 5, 2009
Django Sane Testing
• Ella Folk, Lucas (Hi!)
• Based on nosetests
• Selenium
• Live server
• http://devel.almad.net/trac/django-sane-testing/
66Tuesday, May 5, 2009
Django Test Utils
• Mine!
• Testmaker
• Crawler
• Random fanciness
• http://github.com/ericholscher/django-test-utils/tree/master
67Tuesday, May 5, 2009
Recording tests is generally seen as bad.
68Tuesday, May 5, 2009
My philosophy
• Write tests.
• Notice patterns and best practices
• Automate recording of tests with those patterns
• If you can’t automate, use tools to make it easier.
69Tuesday, May 5, 2009
Process for testmaker
• Most view tests check status_code and response context
• Write middleware that catches this info
• Records it to a file
• Err on the side of more data.
70Tuesday, May 5, 2009
Goals(That perfect world)
71Tuesday, May 5, 2009
Some form of TDD
• Write tests as you write code
• Makes your code easy to test
72Tuesday, May 5, 2009
Follow Django’s Model
• Tests with every commit
• Docs with every commit
• Run tests before commiting
73Tuesday, May 5, 2009
Use a DVCS
• At work we have a central SVN repo
• Git feature branches
• Code is staged for documentation and testing
• Committed to SVN once it is “done”
74Tuesday, May 5, 2009
Continuous Integration
75Tuesday, May 5, 2009
NEVER LEAVE THE BUILD BROKEN
76Tuesday, May 5, 2009
Love Green77Tuesday, May 5, 2009
Fast(er) Tests
78Tuesday, May 5, 2009
JSON
79Tuesday, May 5, 2009
Profiling
python -m cProfile manage.py test
80Tuesday, May 5, 2009
Mock Objects
http://www.voidspace.org.uk/python/mock/
81Tuesday, May 5, 2009
Future and Ponies
82Tuesday, May 5, 2009
Summer of Code
• Test-Only Models
• Coverage
• Windmill tests of the admin
83Tuesday, May 5, 2009
Test Suites in Django
84Tuesday, May 5, 2009
Central Testing Repository
85Tuesday, May 5, 2009
Nose Plugin Integration
86Tuesday, May 5, 2009
Things to remember
• Testing is not hard, you just have to get started.
• If your code doesn’t have tests, it will be hard/impossible to refactor
• Once you have tests, you need to run them!
87Tuesday, May 5, 2009
Credits
• http://www.flickr.com/photos/tym/192416981/
• http://www.flickr.com/photos/seandreilinger/2459266781/
• http://www.homebabysafety.com/images/baby_crawl_suit.jpg
• http://www.flickr.com/photos/pinkypigs/960572985/
88Tuesday, May 5, 2009