Menu

#2 Multi-Inputs and Form Testing

Next_Release
open
8
2002-05-18
2002-05-18
No

Proposal for Form Testing Mechanism for Puffin
----------------------------------------------------
Currently testing forms in puffin is fairly painful.
One of the key reasons
for this is that inputs currently allow for the
passing of only a single
value. I propose that we create a generic input
processor that would allow
you to generate more than one input at one time. This
will be a start on
form handling. More on this specific use of multiple
inputs in a moment.

Here is the (simplest form) format for the multiple
value input processor:

<input name="MULTI_INPUT" type='GET'
processor='multiInput'>
<param
name='inputNameListToken'>ELEMENT_NAME_LIST</param>
<param
name='inputValueListToken'>ELEMENT_VALUE_LIST</param>
</input>

As you can probably guess, the inputNameListToken is
the name of a test
token containing a list of names for inputs. The
inputValueListToken is the
name of a test token containing a list of values for
those same inputs. The
name of the input XML element itself ('MULTI_INPUT')
would likely simply be
ignored in the code.

Let's see an example (we'll see an example of getting
these lists into
tokens to begin with in a moment):

elementNameList = ['id', 'fName', 'lName', 'email']
elementValueList =
['123', 'Keyton', 'Weissinger', 'kw@foo.com']

<testAction name='loadFormLists' noSvrCall='1'>
<output name='ELEMENT_NAME_LIST' processor='MAKELIST'>
<param name='delimitedString'>% id%fName%lName%
email</param>
</output>
<output name='ELEMENT_VALUE_LIST'
processor='MAKELIST'>
<param name='delimitedString'>% 123%Bob%foo%
b@foo.com</param>
</output>
</testAction>

<testAction name='submitToForm'>
<path>formTarget.cgi</path>
<input name='MULTI_INPUT' type='POST'
processor='multiInput'>
<param
name='inputNameListToken'>ELEMENT_NAME_LIST</param>
<param
name='inputValueListToken'>ELEMENT_VALUE_LIST</param>
</input>
</testAction>

Then the test plan would look something like this:

# TEST PLAN
loadFormLists
submitToForm

This would result in the following being sent (as a
POST) to the
formTarget.cgi:

id=123
fName=Bob
lName=foo
email=b@foo.com

OK. We could just as easily have used the following
for the
ELEMENT_VALUE_LIST input:

<output name='ELEMENT_VALUE_LIST'
processor='MAKELIST'>
<param name='delimitedString'>%
$$$CURRENT_ID$$$%Bob%foo%b@foo.com</param>
</output>

This would, of course, substitute the current value of
the CURRENT_ID token
for the value of the ID.

Now I'd like to allow for wildcard pattern templates
as well (using the same
mechanism for as is in the generateRandomString
processor). Here's what I'm
thinking:

<output name='ELEMENT_VALUE_LIST'
processor='MAKELIST'>
<param name='delimitedString'>~%
$$$CURRENT_ID$$$%???%foo%b@foo.com</param>
</output>

The initial '~' would tell puffin to process the
string for wildcard
patterns BEFORE breaking it up into a list of strings.
This is a wee tad
kludgey (note understatement), but it would be pretty
danged powerful....

(This wildcard pattern thing is just an idea I had
while typing this email.
Not sure if it makes sense or not...)

OK. This shortens some typing, but we can do better.

Value Plans VS Value Lists
----------------------------------------------------
Now remember the ability to create a list of lists
from the last email?

I'm going to call this a "plan" in the context of form
testing. You can use
one like this:

<input name="MULTI_INPUT" type='GET'
processor='multiInput'>
<param
name='inputNameListToken'>ELEMENT_NAME_LIST</param>
<param
name='inputValuePlanToken'>ELEMENT_VALUE_PLAN</param>
</input>

The inputValuePlanToken tells the multiInput processor
that we are providing
a list of lists and that it should keep track of where
in the list of lists
we are for each call to test action containing this
input.

Let's see an example:

elementNameList = ['id', 'fName', 'lName', 'email']
elementValuePlan =
[['123', 'Keyton', 'Weissinger', 'kw@foo.com'],

['124', 'Bob', 'Mondela', 'bm@pbs,org'],

['125', 'Bill', 'foo', 'h@foo,org'],

['126', 'gern', 'bar', 'dd@bar,org']]

Assume we have the above two lists (elementNameList
and elementValuePlan) in
two tokens: ELEMENT_NAME_LIST and ELEMENT_VALUE_PLAN,
respectively (again,
we'll see how in a moment, though you probably can
already figure that out).

<testAction name='submitToForm'>
<path>formTarget.cgi</path>
<input name="MULTI_INPUT" type='GET'
processor='multiInput'>
<param
name='inputNameListToken'>ELEMENT_NAME_LIST</param>
<param
name='inputValuePlanToken'>ELEMENT_VALUE_PLAN</param>
</input>
</testAction>

We could then call this test action as many times as
we want:

# TEST PLAN
submitToForm
submitToForm
submitToForm
submitToForm
submitToForm

This plan would result in the formTarget.cgi script
being called five times
(by executing the submitToForm test action five
times). Here are the inputs
sent:

Call 1:
id=123
fName=Keyton
lName=Weissinger
email=kw@foo.com

Call 2:
id=124
fName=Bob
lName=Mondela
email=bm@pbs.org

Call 3:
id=125
fName=Bill
lName=foo
email=h@foo.com

Call 4:
id=126
fName=gern
lName=bar
email=dd@bar.com

Call 5 (NOTE it recycles):
id=123
fName=Keyton
lName=Weissinger
email=kw@foo.com

OK. Now the idea for _DEFAULT_ and _NONE_ from my last
attempt at the form
thing was one I, frankly, really liked. To use it we
need a way of providing
a list of default values:

elementDefaultList =
['100', 'Mister', 'Filler', 'MF@Un.org']

We'll store this into a token called
ELEMENT_DEFAULT_LIST and use it like
this:

<testAction name='submitToForm'>
<path>formTarget.cgi</path>
<input name="MULTI_INPUT" type='GET'
processor='multiInput'>
<param
name='inputNameListToken'>ELEMENT_NAME_LIST</param>
<param
name='inputDefaultListToken'>ELEMENT_DEFAULT_LIST</para
m>
<param
name='inputValuePlanToken'>ELEMENT_VALUE_PLAN</param>
</input>
</testAction>

Now we can include a plan that contains some defaults
and nones. Here is the
loading test action for that (we'll also throw in a
list of expected
statuses for Brian as well):

<testAction name='loadLists' noSvrCall='1'>
<output name='ELEMENT_NAME_LIST' processor='MAKELIST'>
<param name='delimitedString'>% id%fName%lName%
email</param>
</output>
<output name='ELEMENT_DEFAULT_LIST'
processor='MAKELIST'>
<param name='delimitedString'>% 100%Brian%Norman%
b@foo.com</param>
</output>
<output name='ELEMENT_VALUE_PLAN'
processor='MAKELIST'>
<param name='delimitedString'>%
_NONE_%_DEFAULT_%_DEFAULT_%_DEFAULT_</param>
<param name='delimitedString'>%
_DEFAULT_%_NONE_%_DEFAULT_%_DEFAULT_</param>
<param name='delimitedString'>%
_DEFAULT_%_DEFAULT_%_NONE_%_DEFAULT_</param>
<param name='delimitedString'>%
_DEFAULT_%_DEFAULT_%_DEFAULT_%_NONE_</param>
</output>
<output name='EXPECTED_STATUS_LIST'
processor='MAKELIST'>
<param name='delimitedString'>% Missing Id%Missing
First Name%Missing
Last Name%Missing Email</param>
</output>
</testAction>

Now to do Brian's test, here is the test action:

<testAction name='submitToForm'>
<path>formTarget.cgi</path>
<input name="MULTI_INPUT" type='GET'
processor='multiInput'>
<param
name='inputNameListToken'>ELEMENT_NAME_LIST</param>
<param
name='inputDefaultListToken'>ELEMENT_DEFAULT_LIST</para
m>
<param
name='inputValuePlanToken'>ELEMENT_VALUE_PLAN</param>
</input>
<output name="ActualStatus" processor="extractRegex">
<param name="expr" eval="0"><![CDATA[class=status>
(.*?)<]]></param>
</output>
<output name="ExpectedStatus"
processor="NEXTLISTITEM">
<param name="listToken">EXPECTED_STATUS_LIST</param>
</output>
<responseAnalyzerList>
<responseAnalyzer src="puffin"
type="EvalResponseAnalyzer">
<param
name='evalExpression'> "$$$ExpectedStatus$$$" =
"$$$ActualStatus$$$" </param>
</responseAnalyzer>
</responseAnalyzerList>
</testAction>

And then we can call this thing as many times as we
like, it will just start
recycling its values, defaults, statuses, etc.

OK. I think this goes a LONG way towards simplifying
the testing of forms.
What problems still remain?

1) As Brian pointed out some time back, if the length
of your various lists
differ, you could be in a world of hurt. My thinking
is -- for now at
least -- "buyer beware." I don't mean to be callous,
but my brain is
starting to hurt with what I am looking down the
barrel about for writing
this stuff... ;-) We will revisit this problem.
2) The various syntax will get confusing. Not much we
can do there.
Documentation will be the saviour in that regard, I'm
thinking.

What about the formProcessor idea?

We could still have it. All it would do is take the
response from a test
action and grab from it a list of element names:

<testAction name='getFormElements'>
<path>showForm.htm</path>
<output name='ELEMENT_NAME_LIST'
processor='formProcessor'>
<param name='formId'>myForm</param>
</output>
</testAction>

NOTE: All mention of defaults etc are pitched. This
will be handled as
detailed above. All this processor will do is look at
a form inside a given
test action response document and generate a list of
element names. If no
'formId' param is given, it will look at the first
form in the test action
response document that it finds. I agree, Brian, most
people using this will
know their forms for testing, but this would allow for
less typing and
possible a skosh more flexibility (branching, etc).

Discussion


Log in to post a comment.