There’s plenty of material (documentation, blogs, books) out there that’ll help you write a site using Django… but then what? You’ve still got to test, deploy, monitor, and tune the site; failure at deployment time means all your beautiful code is for naught.
This tutorial examines how best to cope when the Real World intrudes on your carefully designed website.
54. “
I don’t do test driven
development. I do stupidity
driven testing… I wait until
I do something stupid, and
”
then write tests to avoid
doing it again.
— Titus Brown
12
55. Whatever happens, don’t let
your test suite break thinking,
“I’ll go back and fix this later.”
13
71. Unit tests
• “Whitebox” testing
• Verify the small functional units of your
app
• Very fine-grained
17
72. Unit tests
• “Whitebox” testing
• Verify the small functional units of your
app
• Very fine-grained
• Familier to most programmers (JUnit,
NUnit, etc.)
17
73. Unit tests
• “Whitebox” testing
• Verify the small functional units of your
app
• Very fine-grained
• Familier to most programmers (JUnit,
NUnit, etc.)
• Provided in Python by unittest
17
84. Doctests
• Easy to write & read.
• Produces self-documenting code.
• Great for cases that only use assertEquals.
20
85. Doctests
• Easy to write & read.
• Produces self-documenting code.
• Great for cases that only use assertEquals.
• Somewhere between unit tests and
functional tests.
20
86. Doctests
• Easy to write & read.
• Produces self-documenting code.
• Great for cases that only use assertEquals.
• Somewhere between unit tests and
functional tests.
• Difficult to debug.
20
87. Doctests
• Easy to write & read.
• Produces self-documenting code.
• Great for cases that only use assertEquals.
• Somewhere between unit tests and
functional tests.
• Difficult to debug.
• Don’t always provide useful test failures.
20
88. class Choices(object):
"""
Easy declarative "choices" tool::
>>> STATUSES = Choices("Live", "Draft")
# Acts like a choices list:
>>> list(STATUSES)
[(1, 'Live'), (2, 'Draft')]
# Easily convert from code to verbose:
>>> STATUSES.verbose(1)
'Live'
# ... and vice versa:
>>> STATUSES.code("Draft")
2
"""
…
21
93. Functional tests
• a.k.a “Behavior Driven Development.”
• “Blackbox,” holistic testing.
• All the hardcore TDD folks look down on
functional tests.
23
94. Functional tests
• a.k.a “Behavior Driven Development.”
• “Blackbox,” holistic testing.
• All the hardcore TDD folks look down on
functional tests.
• But they keep your boss happy.
23
95. Functional tests
• a.k.a “Behavior Driven Development.”
• “Blackbox,” holistic testing.
• All the hardcore TDD folks look down on
functional tests.
• But they keep your boss happy.
• Easy to find problems; harder to find the
actual bug.
23
103. django.test.Client
• Test the whole request path without
running a web server.
• Responses provide extra information
about templates and their contexts.
25
104. class StoryAddViewTests(TestCase):
fixtures = ['authtestdata', 'newsbudget_test_data']
urls = 'newsbudget.urls'
def test_story_add_get(self):
r = self.client.get('/budget/stories/add/')
self.assertEqual(r.status_code, 200)
…
def test_story_add_post(self):
data = {
'title': 'Hungry cat is hungry',
'date': '2009-01-01',
}
r = self.client.post('/budget/stories/add/', data)
self.assertEqual(r.status_code, 302)
…
26
107. Web browser testing
• The ultimate in functional testing for
web applications.
• Run test in a web browser.
27
108. Web browser testing
• The ultimate in functional testing for
web applications.
• Run test in a web browser.
• Can verify JavaScript, AJAX; even CSS.
27
109. Web browser testing
• The ultimate in functional testing for
web applications.
• Run test in a web browser.
• Can verify JavaScript, AJAX; even CSS.
• Test your site across supported browsers.
27
127. Designing for reuse
• Do one thing, and do it well.
• Don’t be afraid of multiple apps.
33
128. Designing for reuse
• Do one thing, and do it well.
• Don’t be afraid of multiple apps.
• Write for flexibility.
33
129. Designing for reuse
• Do one thing, and do it well.
• Don’t be afraid of multiple apps.
• Write for flexibility.
• Build to distribute.
33
130. Designing for reuse
• Do one thing, and do it well.
• Don’t be afraid of multiple apps.
• Write for flexibility.
• Build to distribute.
• Extend carefully.
33
137. Good focus
• “Handle storage of users and
authentication of their identities.”
37
138. Good focus
• “Handle storage of users and
authentication of their identities.”
• “Allow content to be tagged, del.icio.us
style, with querying by tags.”
37
139. Good focus
• “Handle storage of users and
authentication of their identities.”
• “Allow content to be tagged, del.icio.us
style, with querying by tags.”
• “Handle entries in a weblog.”
37
141. Bad focus
• “Handle entries in a weblog, and users
who post them, and their authentication,
and tagging and categorization, and some
flat pages for static content, and...”
38
149. Small is good
• Many great Django apps are very small.
• Even a lot of “simple” Django sites
commonly have a dozen or more
applications in INSTALLED_APPS.
40
150. Small is good
• Many great Django apps are very small.
• Even a lot of “simple” Django sites
commonly have a dozen or more
applications in INSTALLED_APPS.
• If you’ve got a complex site and a short
application list, something’s probably wrong.
40
159. The monolith anti-pattern
• The “application” is the whole site.
• Re-use? YAGNI.
• Plugins that hook into the “main” application.
43
160. The monolith anti-pattern
• The “application” is the whole site.
• Re-use? YAGNI.
• Plugins that hook into the “main” application.
• Heavy use of middleware-like concepts.
43
164. The Django mindset
• Application: some bit of functionality.
• Site: several applications.
45
165. The Django mindset
• Application: some bit of functionality.
• Site: several applications.
• Spin off new “apps” liberally.
45
166. The Django mindset
• Application: some bit of functionality.
• Site: several applications.
• Spin off new “apps” liberally.
• Develop a suite of apps ready for when
they’re needed.
45
169. Django encourages this
• INSTALLED_APPS
• Applications are just Python packages,
not some Django-specific “app” or
“plugin.”
46
170. Django encourages this
• INSTALLED_APPS
• Applications are just Python packages,
not some Django-specific “app” or
“plugin.”
• Abstractions like django.contrib.sites
make you think about this as you develop.
46
172. Spin off a new app?
• Is this feature unrelated to the app’s focus?
47
173. Spin off a new app?
• Is this feature unrelated to the app’s focus?
• Is it orthogonal to the rest of the app?
47
174. Spin off a new app?
• Is this feature unrelated to the app’s focus?
• Is it orthogonal to the rest of the app?
• Will I need similar functionality again?
47
180. But… what about…
• Site A wants a contact form that just
collects a message.
52
181. But… what about…
• Site A wants a contact form that just
collects a message.
• Site B’s marketing department wants a
bunch of info.
52
182. But… what about…
• Site A wants a contact form that just
collects a message.
• Site B’s marketing department wants a
bunch of info.
• Site C wants to use Akismet to filter
automated spam.
52
198. Form processing
• You want to redirect after successful
submission.
• Supply a default URL.
58
199. Form processing
• You want to redirect after successful
submission.
• Supply a default URL.
• (Preferably by using reverse resolution).
58
200. Form processing
• You want to redirect after successful
submission.
• Supply a default URL.
• (Preferably by using reverse resolution).
• Let users override the default.
58
201. def edit_entry(request, entry_id):
form = EntryForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('entry_detail', entry_id)
return render_to_response('entry/form.html', {…})
59
202. def edit_entry(request, entry_id,
form_class=EntryForm,
template_name='entry/form.html',
post_save_redirect=None):
form = form_class(request.POST or None)
if form.is_valid():
form.save()
if post_save_redirect:
return redirect(post_save_redirect)
else:
return redirect('entry_detail', entry_id)
return render_to_response([template_name, 'entry/form.html'], {…})
60
226. Where apps really live
• Single module directly on Python path
(registration, tagging, etc.).
70
227. Where apps really live
• Single module directly on Python path
(registration, tagging, etc.).
• Related modules under a top-level
package (ellington.events,
ellington.podcasts, etc.)
70
228. Where apps really live
• Single module directly on Python path
(registration, tagging, etc.).
• Related modules under a top-level
package (ellington.events,
ellington.podcasts, etc.)
• No projects (ellington.settings doesn’t
exist).
70
231. Want to distribute?
• Build a package with distutils/setuptools.
• Put it on PyPI (or a private package
server).
71
232. Want to distribute?
• Build a package with distutils/setuptools.
• Put it on PyPI (or a private package
server).
• Now it works with easy_install, pip,
buildout, …
71
235. General best practices
• Establish dependancy rules.
• Establish a minimum Python version
(suggestion: Python 2.5).
72
236. General best practices
• Establish dependancy rules.
• Establish a minimum Python version
(suggestion: Python 2.5).
• Establish a minimum Django version
(suggestion: Django 1.0).
72
237. General best practices
• Establish dependancy rules.
• Establish a minimum Python version
(suggestion: Python 2.5).
• Establish a minimum Django version
(suggestion: Django 1.0).
• Test frequently against new versions
of dependancies.
72
242. Don’t touch!
• Good applications are extensible
without patching.
• Take advantage of every extensibility point
an application gives you.
75
243. Don’t touch!
• Good applications are extensible
without patching.
• Take advantage of every extensibility point
an application gives you.
• You may end up doing something that
deserves a new application anyway.
75
257. Other tricks
• Signals lets you fire off customized
behavior when certain events happen.
81
258. Other tricks
• Signals lets you fire off customized
behavior when certain events happen.
• Middleware offers full control over
request/response handling.
81
259. Other tricks
• Signals lets you fire off customized
behavior when certain events happen.
• Middleware offers full control over
request/response handling.
• Context processors can make additional
information available if a view doesn’t.
81
260. If you must make
changes to
external code…
82
262. Keep changes to a minimum
• If possible, instead of adding a feature,
add extensibility.
83
263. Keep changes to a minimum
• If possible, instead of adding a feature,
add extensibility.
• Keep as much changed code as you can
out of the original app.
83
266. Stay up-to-date
• Don’t want to get out of sync with the
original version of the code!
• You might miss bugfixes.
84
267. Stay up-to-date
• Don’t want to get out of sync with the
original version of the code!
• You might miss bugfixes.
• You might even miss the feature you
needed.
84
269. Use a good VCS
• Subversion vendor branches don’t cut it.
85
270. Use a good VCS
• Subversion vendor branches don’t cut it.
• DVCSes are perfect for this:
85
271. Use a good VCS
• Subversion vendor branches don’t cut it.
• DVCSes are perfect for this:
• Mercurial queues.
85
272. Use a good VCS
• Subversion vendor branches don’t cut it.
• DVCSes are perfect for this:
• Mercurial queues.
• Git rebasing.
85
273. Use a good VCS
• Subversion vendor branches don’t cut it.
• DVCSes are perfect for this:
• Mercurial queues.
• Git rebasing.
• At the very least, maintain a patch queue
by hand.
85
275. Be a good citizen
• If you change someone else’s code, let
them know.
86
276. Be a good citizen
• If you change someone else’s code, let
them know.
• Maybe they’ll merge your changes in and
you won’t have to fork anymore.
86
283. Deployment should...
• Be automated.
• Automatically manage dependencies.
• Be isolated.
• Be repeatable.
89
284. Deployment should...
• Be automated.
• Automatically manage dependencies.
• Be isolated.
• Be repeatable.
• Be identical in staging and in production.
89
285. Deployment should...
• Be automated.
• Automatically manage dependencies.
• Be isolated.
• Be repeatable.
• Be identical in staging and in production.
• Work the same for everyone.
89
294. Dependancy management
• The Python ecosystem rocks!
• Python package management doesn’t.
• Installing packages — and dependancies
— correctly is a lot harder than it should be;
most defaults are wrong.
91
295. Dependancy management
• The Python ecosystem rocks!
• Python package management doesn’t.
• Installing packages — and dependancies
— correctly is a lot harder than it should be;
most defaults are wrong.
• Here be dragons.
91
298. Vendor packages
• APT, Yum, …
• The good: familiar tools; stability; handles
dependancies not on PyPI.
92
299. Vendor packages
• APT, Yum, …
• The good: familiar tools; stability; handles
dependancies not on PyPI.
• The bad: small selection; not (very)
portable; hard to supply user packages.
92
300. Vendor packages
• APT, Yum, …
• The good: familiar tools; stability; handles
dependancies not on PyPI.
• The bad: small selection; not (very)
portable; hard to supply user packages.
• The ugly: installs packages system-wide.
92
307. pip
http://pip.openplans.org/
• “Pip Installs Packages”
• The good: Just Works™; handles non-
PyPI packages (including direct from
SCM); repeatable dependancies;
integrates with virtualenv for isolation.
94
308. pip
http://pip.openplans.org/
• “Pip Installs Packages”
• The good: Just Works™; handles non-
PyPI packages (including direct from
SCM); repeatable dependancies;
integrates with virtualenv for isolation.
• The bad: still young; not yet bundled.
94
309. pip
http://pip.openplans.org/
• “Pip Installs Packages”
• The good: Just Works™; handles non-
PyPI packages (including direct from
SCM); repeatable dependancies;
integrates with virtualenv for isolation.
• The bad: still young; not yet bundled.
• The ugly: haven’t found it yet.
94
311. zc.buildout
http://buildout.org/
• The good: incredibly flexible; handles any
sort of dependancy; repeatable builds;
reusable “recipes;” good ecosystem;
handles isolation, too.
95
312. zc.buildout
http://buildout.org/
• The good: incredibly flexible; handles any
sort of dependancy; repeatable builds;
reusable “recipes;” good ecosystem;
handles isolation, too.
• The bad: often cryptic, INI-style
configuration file; confusing duplication of
recipes; sometimes too flexible.
95
313. zc.buildout
http://buildout.org/
• The good: incredibly flexible; handles any
sort of dependancy; repeatable builds;
reusable “recipes;” good ecosystem;
handles isolation, too.
• The bad: often cryptic, INI-style
configuration file; confusing duplication of
recipes; sometimes too flexible.
• The ugly: nearly completely undocumented.
95
317. Package isolation
• Why?
• Site A requires Foo v1.0; site B requires
Foo v2.0.
• You need to develop against multiple
versions of dependancies.
96
325. Why automate?
• “I can’t push this fix to the servers until
Alex gets back from lunch.”
98
326. Why automate?
• “I can’t push this fix to the servers until
Alex gets back from lunch.”
• “Sorry, I can’t fix that. I’m new here.”
98
327. Why automate?
• “I can’t push this fix to the servers until
Alex gets back from lunch.”
• “Sorry, I can’t fix that. I’m new here.”
• “Oops, I just made the wrong version of
our site live.”
98
328. Why automate?
• “I can’t push this fix to the servers until
Alex gets back from lunch.”
• “Sorry, I can’t fix that. I’m new here.”
• “Oops, I just made the wrong version of
our site live.”
• “It’s broken! What’d you do!?”
98
335. Capistrano
http://capify.org/
• The good: lots of features; good
documentation; active community.
• The bad: stale development; very
“opinionated” and Rails-oriented.
100
354. import os, sys
# Add to PYTHONPATH whatever you need
sys.path.append('/usr/local/django')
# Set DJANGO_SETTINGS_MODULE
os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
# Create the application for mod_wsgi
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
110
370. Connection middleware
• Proxy between web and database layers
• Most implement hot fallover and
connection pooling
119
371. Connection middleware
• Proxy between web and database layers
• Most implement hot fallover and
connection pooling
• Some also provide replication, load
balancing, parallel queries, connection
limiting, &c
119
372. Connection middleware
• Proxy between web and database layers
• Most implement hot fallover and
connection pooling
• Some also provide replication, load
balancing, parallel queries, connection
limiting, &c
• DATABASE_HOST = '127.0.0.1'
119
405. CREATE POOL mypool
POOL mypool ADD 10.0.0.100
POOL mypool ADD 10.0.0.101
CREATE SERVICE mysite
SET listen = my.public.ip
SET role = reverse_proxy
SET pool = mypool
SET verify_backend = on
SET buffer_size = 120k
ENABLE mysite
130
407. proxy proxy proxy media media
load balancing cluster media server cluster
django django django cache cache
web server cluster cache cluster
database database database
database server cluster
132
409. BALANCE = None
def balance_sheet(request):
global BALANCE
if not BALANCE:
bank = Bank.objects.get(...)
BALANCE = bank.total_balance()
...
134
410. BALANCE = None
def balance_sheet(request):
global BALANCE
if not BALANCE:
bank = Bank.objects.get(...)
BALANCE = bank.total_balance()
...
FAIL 134
419. Further reading
• Cal Henderson, Building Scalable Web Sites
• John Allspaw, The Art of Capacity Planning
139
420. Further reading
• Cal Henderson, Building Scalable Web Sites
• John Allspaw, The Art of Capacity Planning
• http://kitchensoap.com/
139
421. Further reading
• Cal Henderson, Building Scalable Web Sites
• John Allspaw, The Art of Capacity Planning
• http://kitchensoap.com/
• http://highscalability.com/
139
425. Goals
• When the site goes down, know it immediately.
• Automatically handle common sources of
downtime.
141
Notas del editor
Oh hai. I’m Jacob Kaplan-Moss; here’s a few ways to get in touch with me.
I wear quite a few hats. Today, I’m wearing two: I’m one of the lead developers of Django; I’m a partner at `Revolution Systems`__, a consulting business specializing in, well, the stuff I’m about to talk about.
Just a brief shameless plug: my day job is as a consultant working in and around these issues. I get to come talk about this stuff publicly because of this gig, so If you need info specific to your situation please consider giving us a call!
Credit where credit is due: I first gave this talk at PyCon 2009 with the help of `James Bennett`__, so much of my thinking and some of the content comes from James.
__ http://b-list.org/
This is the main theme of this tutorial: you’ve written a Django site...
... and you’ve barely started.
Writing the app is the easy part; what comes next is seriously complicated.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
Here’s just one list (Leonard Lin’s) of what you might need to think about *after* writing your app; I could easily add another dozen more things to this list. Luckily, not every site needs *all* of this... but any site of any size will need to understand at last some of this stuff, and bigger deployments will need to worry about all of it.
Obviously this is far too much to cover even in a long tutorial, so we’ll pick and choose; the point is that writing the app is usually the easy part. Today we’re talking about what comes next.
So here’s the bare minimum you’ll need to think about:
* You need to test your sites. Without tests, you can’t move forward without downtime.
* You need to write your code in a way that makes deployment possible — and easy.
* You need to use deployment tools that automate the repetitive bits and keep you from shooting yourself in the foot.
* You need a production environment that scales with your traffic.
* You need to watch your sites in action so that you know what’s up.
* When things go slow you need to fix it.
So here’s the bare minimum you’ll need to think about:
* You need to test your sites. Without tests, you can’t move forward without downtime.
* You need to write your code in a way that makes deployment possible — and easy.
* You need to use deployment tools that automate the repetitive bits and keep you from shooting yourself in the foot.
* You need a production environment that scales with your traffic.
* You need to watch your sites in action so that you know what’s up.
* When things go slow you need to fix it.
So here’s the bare minimum you’ll need to think about:
* You need to test your sites. Without tests, you can’t move forward without downtime.
* You need to write your code in a way that makes deployment possible — and easy.
* You need to use deployment tools that automate the repetitive bits and keep you from shooting yourself in the foot.
* You need a production environment that scales with your traffic.
* You need to watch your sites in action so that you know what’s up.
* When things go slow you need to fix it.
So here’s the bare minimum you’ll need to think about:
* You need to test your sites. Without tests, you can’t move forward without downtime.
* You need to write your code in a way that makes deployment possible — and easy.
* You need to use deployment tools that automate the repetitive bits and keep you from shooting yourself in the foot.
* You need a production environment that scales with your traffic.
* You need to watch your sites in action so that you know what’s up.
* When things go slow you need to fix it.
So here’s the bare minimum you’ll need to think about:
* You need to test your sites. Without tests, you can’t move forward without downtime.
* You need to write your code in a way that makes deployment possible — and easy.
* You need to use deployment tools that automate the repetitive bits and keep you from shooting yourself in the foot.
* You need a production environment that scales with your traffic.
* You need to watch your sites in action so that you know what’s up.
* When things go slow you need to fix it.
So here’s the bare minimum you’ll need to think about:
* You need to test your sites. Without tests, you can’t move forward without downtime.
* You need to write your code in a way that makes deployment possible — and easy.
* You need to use deployment tools that automate the repetitive bits and keep you from shooting yourself in the foot.
* You need a production environment that scales with your traffic.
* You need to watch your sites in action so that you know what’s up.
* When things go slow you need to fix it.
So now you’ve got a working app, but how do you *know* that it works? Sure, you could just run the site and click around, but that guarantees nothing. The difference between stable and unstable code is often the quality of the tests.
The “fear” that Beck is talking about here is the fear of not knowing if your new site will run or not. Testing, while often boring, relives you of that fear.
`Test Driven Development`__ by Kent Beck is the bible of TDD. Beck requires that you only add new code to your project after an existing test fails. This means writing tests before writing any new code. It can be rewarding -- particularly if you’re pair programming so you can keep each other honest. Unfortunately, it’s also simply not practical for most developers.
__ http://www.amazon.com/dp/0321146530/
This is the pragmatic approach to testing: write tests when you need them. If you need to chase down a bug, write a test to trigger the bug, then when the test passes you know the bug is licked.
Yes, this leaves you with less than perfect coverage.
I’m speaking from experience here. Once you commit with even a *single* breaking test, finding the time to clean up is an uphill battle. Knowing the suite fails discourages you from even running the tests at all, and thus the quality continues to decline.
I tend to think of this as a continuum of testing; another way of thinking about this is a continuum between internal/external, or whitebox/blackbox.
I tend to think of this as a continuum of testing; another way of thinking about this is a continuum between internal/external, or whitebox/blackbox.
I tend to think of this as a continuum of testing; another way of thinking about this is a continuum between internal/external, or whitebox/blackbox.
I tend to think of this as a continuum of testing; another way of thinking about this is a continuum between internal/external, or whitebox/blackbox.
Testing web applications is *hard*. Anything with a persistent state -- i.e. a database -- and network communications -- HTTP -- is a real pain to test.
Ruby on Rails really changed the game, though. When it shipped a set of tools that took most of the pain out of automating web tests, it galvenized developers to compete.
Django’s since come out with our own spin on this set of tools. I’m only going to cover doctests in this intro tutorial, so a brief overview of the other tools is in order:
* Unit tests: Django can run tests using Python’s standard `unittest` framework, which is based on Java’s JUnit. Perfect for more formal unit tests like you’d see in Java/C#.
* Fixtures: fixtures are a way of loading preset data into the database for each test, thus letting you test against “real” data.
* The test client: this lets you “fake” a request to your views and inspect the returned response, template, and context.
* Email capture: the test suite will intercept sent email so you can test logic involving email.
Testing web applications is *hard*. Anything with a persistent state -- i.e. a database -- and network communications -- HTTP -- is a real pain to test.
Ruby on Rails really changed the game, though. When it shipped a set of tools that took most of the pain out of automating web tests, it galvenized developers to compete.
Django’s since come out with our own spin on this set of tools. I’m only going to cover doctests in this intro tutorial, so a brief overview of the other tools is in order:
* Unit tests: Django can run tests using Python’s standard `unittest` framework, which is based on Java’s JUnit. Perfect for more formal unit tests like you’d see in Java/C#.
* Fixtures: fixtures are a way of loading preset data into the database for each test, thus letting you test against “real” data.
* The test client: this lets you “fake” a request to your views and inspect the returned response, template, and context.
* Email capture: the test suite will intercept sent email so you can test logic involving email.
Testing web applications is *hard*. Anything with a persistent state -- i.e. a database -- and network communications -- HTTP -- is a real pain to test.
Ruby on Rails really changed the game, though. When it shipped a set of tools that took most of the pain out of automating web tests, it galvenized developers to compete.
Django’s since come out with our own spin on this set of tools. I’m only going to cover doctests in this intro tutorial, so a brief overview of the other tools is in order:
* Unit tests: Django can run tests using Python’s standard `unittest` framework, which is based on Java’s JUnit. Perfect for more formal unit tests like you’d see in Java/C#.
* Fixtures: fixtures are a way of loading preset data into the database for each test, thus letting you test against “real” data.
* The test client: this lets you “fake” a request to your views and inspect the returned response, template, and context.
* Email capture: the test suite will intercept sent email so you can test logic involving email.
Testing web applications is *hard*. Anything with a persistent state -- i.e. a database -- and network communications -- HTTP -- is a real pain to test.
Ruby on Rails really changed the game, though. When it shipped a set of tools that took most of the pain out of automating web tests, it galvenized developers to compete.
Django’s since come out with our own spin on this set of tools. I’m only going to cover doctests in this intro tutorial, so a brief overview of the other tools is in order:
* Unit tests: Django can run tests using Python’s standard `unittest` framework, which is based on Java’s JUnit. Perfect for more formal unit tests like you’d see in Java/C#.
* Fixtures: fixtures are a way of loading preset data into the database for each test, thus letting you test against “real” data.
* The test client: this lets you “fake” a request to your views and inspect the returned response, template, and context.
* Email capture: the test suite will intercept sent email so you can test logic involving email.
Testing web applications is *hard*. Anything with a persistent state -- i.e. a database -- and network communications -- HTTP -- is a real pain to test.
Ruby on Rails really changed the game, though. When it shipped a set of tools that took most of the pain out of automating web tests, it galvenized developers to compete.
Django’s since come out with our own spin on this set of tools. I’m only going to cover doctests in this intro tutorial, so a brief overview of the other tools is in order:
* Unit tests: Django can run tests using Python’s standard `unittest` framework, which is based on Java’s JUnit. Perfect for more formal unit tests like you’d see in Java/C#.
* Fixtures: fixtures are a way of loading preset data into the database for each test, thus letting you test against “real” data.
* The test client: this lets you “fake” a request to your views and inspect the returned response, template, and context.
* Email capture: the test suite will intercept sent email so you can test logic involving email.