[Seaside] onAnswer: problems
Colin Putney
cputney at wiresong.ca
Fri Jun 4 19:45:30 CEST 2004
On Jun 3, 2004, at 8:41 PM, C. David Shaffer wrote:
> Avi Bryant wrote:
>
>> Yup, that'll fix your immediate problem, but I'm not convinced it's a
>> good long term solution either. For example, if the child you hung
>> the onAnswer: block on was two deep (say there was a navigation
>> component like a tab widget in between the parent and the child it
>> was really interested in), then things would still break.
>
>
> OK, here's one that works several levels deep. Before I do any more
> with this kind of thing I need to write some test cases...to do that I
> need a framework for testing seaside apps. Anyone got one (or part of
> one) that they're willing to share? Off to Maine for a week tomorrow
> morning...thanks for all your help Avi.
I too would like to see such a framework.
My Nori templating framework provided a way of testing Seaside
components, but since templating is so passé, I've stopped developing
it. I'm not sure how applicable it is to the current situation, but
here's how it worked.
1. Instead of using HtmlRenderer, components generated a DOM tree which
was then serialized to serve the page.
2. The tests would set up a component, render it, and then make
assertions about the DOM tree. This would be stuff like "has a text
node containing 'Copyright Evil Corporation 1976, all rights reserved'"
or "has an anchor with the label 'Launch Nukes'" or "background color
for a div with id #main is #ffffff".
3. Callbacks were implemented with MessageSends instead of blocks. This
allowed them to be easily examined as well. So tests would also make
assertions like "some element of the page is bound do #doSomething."
That assertion would pass if there was an anchor or form button that
triggered #doSomething when clicked. You could do similar assertions
for value callbacks.
4. Testing of the callbacks themselves was done separately. A component
would be set up, the callback invoked, the resulting component rendered
and assertions made about the resulting DOM tree. So you could make
assertions like #doSomething calls SomeOtherComponent, which then
displays a page containing a link that calls #answer.
The intent of all this was to make is simple to write tests that
capture the spirit of the requirements that usually come up in web
applications. Requests from users often take the form of "There should
be a link on this page that will take me to a page that does X." So to
test this, we can write two tests: one that asserts the link is present
and calls a certain callback (ie, test the rendering), and another that
asserts the callback does what it's supposed to (ie, test the
behaviour).
I wrote a fairly complex real-world application using this kind of
testing (not in Seaside - Nori was a port of that system to Seaside),
and I can't stress enough what a benefit it is to be able to test
application workflow and response to specific user actions.
So where do we go from here? I have some thoughts about how to
implement a framework for testing Seaside apps that doesn't rely on a
templating system the way Nori did.
1. For testing, we use a mock renderer instead of a genuine
HtmlRenderer. The test would set up the MockRenderer with a set of
expectations, which would capture the things we want to be true about
the way the component is rendered. During the render, the MockRenderer
would check each call by the component against its expectations and
fail the test if they aren't met. In some cases, this would have to
wait until the render is finished (such as certain things being
present), but sometimes we could fail the test at the exact point the
render goes wrong.
2. Analysing block callbacks is much trickier than MessageSends, but I
think it could be done using the same sort of techniques that are in
the RefactoringBrowser. We'd parse the source code to the block or
decompile it's bytecodes into an AST which we could then examine. Even
with an AST, it's pretty difficult to predict what code will do without
running it, but I suspect that most blocks passed to the renderer are
pretty simple, so it ought to be possible to use the same sort of
convention that Nori did. We could assert that #doSomething gets called
by the callback, or the value gets stored in an instance variable etc.
3. Alternatively we could modify HtmlRenderer to allow the use of
messages or selectors in place of blocks. This makes rendering a bit
more awkward, but it makes testing easier.
4. I'd like to tie into the halo system as well. There ought to be a
halo that allows the user to view and edit the rendering assertions
that get used in the component's tests, and run the tests. I'm
imagining something a bit like FIT here; this would be aimed at
allowing non-programmers to specify the rendering tests. Ideally this
should be implemented in a way that allows for test-driven development
- ie, we can create the rendering assertions before actually writing
the rendering code.
Thoughts?
Colin
More information about the Seaside
mailing list