When I wrote my webapp framework last year, I too found that Zope testing was inadequate, and I still do. I ended up writing my own app end-to-end (I could not bear without an autoreload feature for the source code, and all Zope3 facilities for fast development were broken, couldn't use webdav to upload files, had to restart server on every change, there was no way I was going to work like that), and using mechanize for testing it. IMO best testing for the web should be done from a browser's perspective to really be effective. I have found so many problems that would have slipped by without my tests.
One useful idea that I introduced in my app was to return custom meta fields in the head, that reflect some of the internal state of the server app, for example, the currently logged in user, and a return status string. These only show up when the app is in debug mode, and the tests assert that the return statii are what is expected.
Another idea was to add extra test resources/pages in debug mode. For example, when my app sends email to other users, well, in debug mode, it doesn't really send, rather, it puts the emails in a DB table (only the last email for each user) and then the tests can recuperate the last email sent for a particular user, whose contents it then validates. I can parse the email to get some links with tokens, etc. Just trying to do as close to the real processes as possible.
paste.fixture does both of these:
- There's a special key for putting values for use in tests (paste.testing_variables), which takes the place of headers. It's out-of-band with respect to any HTTP information, and values needn't be serialized to strings.
- There's also ways to detect when you are in a debugging environment (paste.testing) -- some people think this is really bad, but I think those people are just scarred from having someone abuse that feature to put workarounds in the code for the tests. The rule of consenting adults say, to me, that the variable belongs there. Though, I suppose, those people want to set up all the mock objects ahead of time using a complicated setup process (e.g., dependency injection). A boolean is easier.# Ian Bicking