Hi, David,

Thanks for taking some time to look at this problem. I'm a little
concerned about the approach, though - should Lift really behave
significantly differently in test mode than it does in production
mode? This seems like it would lend to the possibility of subtle bugs
that don't show up until one is in production.

With respect to unit testing, Lift's singletons depend upon underlying
thread-local variables (via ThreadGlobal) to maintain state. I'm just
musing here, but do you think it might be possible to inject a layer
of indirection between Lift's singletons and the underlying state
mechanism so that the state maintenance layer could be mocked out for
tests?

This brings some other issues I've been wrangling with lately to mind.
Please forgive me for rambling, but I think that the issue of testing
is intimately tied to how Lift deals with state maintenance.

State is sort of becoming a bugbear for me as my Lift app becomes more
complex. I'm not sure whether I'm just doing things wrong or what, but
I'm finding that using RequestVars and StatefulSnippets to maintain
state makes it difficult to build composable editing components. As an
example, I've got a StatefulSnippet that I use to build an object of
type EventTrigger. There are a few possible subclasses of EventTrigger
that can be produced through the workflow managed by the
StatefulSnippet, and switching between the type options and such works
well.

The problem is that an EventTrigger may be associated with some number
of Products, of which there are also a number of subclasses. So, I
also have a similar StatefulSnippet that manages the flow of creating
Products. But how do I pass the state of a newly created (or selected
existing) EventTrigger from one StatefulSnippet to the next? As far as
I can tell, there is no way to hand off control between
StatefulSnippet instances - instead I must populate a RequestVar and
use a redirect in the transition. Both sides of this state transaction
have expectations of the state of the intermediate RequestVar, but
there is no way to enforce that it be populated before the second
snippet attempts to use it. This feels very Model 1 to me. It's the
same case wherever I use RequestVar - some component (say a link) sets
a value, then some other component reads it, and while the ReqestVar
provides type safety for the value type, there is no associated type
safety available for the call, as both links and redirects simply use
strings to define behavior.

This all seems to fall out of the fact that the processing of a
template at a Loc results in reflective invocation of snippet
functions. The template itself, which is outside the type system,
defines the behavior at a Loc. As such, every snippet must be written
to operate correctly in the absence of any piece of the state it
expects. At least in my app, this ends up as an obnoxiously large
amount of boilerplate.

I think that I must be doing something wrong, because the feel of my
app is that it is held together by snot and string, threaded through
RequestVars that I hope will be populated with the correct values at
the correct times and redirects that I hope are pointing to the right
locations. At the same time, I can't figure out how else Lift will
permit me to handle my state. With each new feature I add, I become a
little more dismayed.

Please, how can I handle these problems better?

Thanks,

Kris




On Fri, Jul 3, 2009 at 10:43 AM, David
Pollak<[email protected]> wrote:
> Jeppe,
>
> Once I check in some code (in about 20 minutes), if you run Lift in Test
> mode (-Drun.mode=test), forms, etc. will have stable names which makes
> testing easier.
>
> Thanks,
>
> David
>
> On Thu, Jul 2, 2009 at 1:13 PM, Jeppe Nejsum Madsen <[email protected]>
> wrote:
>>
>> Hi,
>>
>> Having taken the first baby steps and gotten a Lift app running, it's
>> time to bring back some of the old engineering practices to make sure
>> things keep running when new features are added at a rapid pace :-)
>>
>> I'm interested in how people are testing their Lift apps, both at the
>> unit test level (ie. specs/scalatest with no container) and at the
>> integration test level (running in servlet container). Also, how are you
>> doing TDD with Lift (if at all).
>>
>> Specifically, I've run into the following issues:
>>
>> 1) Testing model classes. Many require access to S (ie to read
>> resources) or other static Lift constructs. How can you mock these?
>>
>> 2) Testing snippets. Same issue with S, but more related to the actual
>> request, eg. S.param
>>
>> For in-container testing it seems the practice of generating unique
>> names for form fields, makes it difficult to use tools like Selenium to
>> do browser based testing? How do you handle this?
>>
>> Any input is appreciated
>>
>> /Jeppe
>>
>>
>
>
>
> --
> Lift, the simply functional web framework http://liftweb.net
> Beginning Scala http://www.apress.com/book/view/1430219890
> Follow me: http://twitter.com/dpp
> Git some: http://github.com/dpp
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to