Well, besides setup scripts the other thing I want to take from Rails
is building testability into the system. But I haven't quite figured
out how to do that. The specific idea I want to take is that of data
fixtures -- data that puts the site into a "known" state that can be
tested against. In the Rails world that's a bunch of rows to be
inserted into the database, which is a particular case I'm interested
in, but of course it should be more general.
That's not too terribly hard; it's mostly grunt work. Not
super-simple, but not hard. I've added the necessary configuration
file hooks to handle different kind of environments running out of the
same directory: include() and load(), both of which have
access to previous files, so you could do:
if debug:
include('database_debug.conf')
else:
include('database.conf')
Or any number of things, like testing if profile == 'debug'. This
kind of flexibility (among other things) makes Python files very
useful; I was skeptical at first about Python syntax (having invested
much time into
an INI-file based configuration), but it makes so many things so
easy.
Oh, but back to the actual testing. One thing I like about how things
have shaped up in Paste is that testing has been pretty easy.
paste.wsgilib
has a function raw_interactive(app, path_info) that is quite
useful, and I use it in paste.tests.fixture in
fake_request(). It lets me do things like:
res = fake_request(p, '/')
res.all_okay() # Asserts status is 200 OK, no errors logged
assert 'Welcome' in res
assert res.header('content-type') == 'text/html'
And so on. There's some things I feel should be tweaked. For
instance, it should normal throw an error for any status besides 200
OK (with a keyword to explicitly say that another status is okay or
expected). Maybe test for compliant HTML (paste.wdg_validate is a start
for this).
It should make requests a little easier to perform --
maybe it should be a wrapper around an application, for instance. But
it's pretty close as it is, it just needs a little loving to get all
the convenience methods in (and a good testing framework is all about
convenience). And then you could do the whole thing in doctest,
maybe like:
>>> app = FakeApp(this_app)
>>> res = app.post('/login', data={'username': 'bob', 'password': 'bob'})
>>> res.element(id='message')
<div id="message">User 'bob' logged in</div>
And so on. You could put this right into your object's docstrings.
Using things like doctest_xml_compare
you can make your test say just what you mean, and no more.
That could be really sweet. Interested? Join paste-users and we'll talk there.