You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by James Mitchell <jm...@apache.org> on 2003/02/12 18:22:22 UTC

New Tests

Lately, I've been focusing on building tests that cover the entire core
struts taglibs.  I've completed logic and I'm now hacking away on the bean
tags.

I don't claim to be expert with Cactus, but there seem to be 2 different
approaches with respect to testing taglibs.  (There are probably more, but
these 2 really seem to stick out in my mind)

The existing logic tags use the first approach which is programmatically
mimicing what the container will do wrt life cycle calls, the testing the
output or (in the case of boolean results) tag.condition(0, 0).

The second approach is to actually use a jsp to test the tag (this seems
more natural to me, and tests more peices of the puzzle IMHO).  But this
comes at the cost of time for page compilation.  Personnally, I can live
with that cost, for the benefits of using the real thing.  Doing it this way
also covers a long time bullet item that I've been wanting to complete for a
quite some time. (Complete examples of every tag, with every conceivable
configuration)


For example:
When building the tests for the o.a.s.t.b.TestCookieTag, a typical test
looks like this:

...
...
//============================================================
    public void beginCookieName(WebRequest testRequest) {
       testRequest.addCookie(COOKIE_KEY, COOKIE_VAL);
    }

    public void testCookieName()
     throws ServletException,  JspException, IOException {

        CookieTag tag = new CookieTag();
  tag.setPageContext(pageContext);
        tag.setName(COOKIE_KEY);
        tag.setId("theId");
        tag.doStartTag();

        Cookie cookie = (Cookie)pageContext.getAttribute("theId");
        assertEquals("Verify that the cookie was defined properly as a
scripting variable",
           COOKIE_VAL,
           cookie.getValue());




I rewrote this test to call a jsp instead:
   //====================================================
    public void beginCookieName(WebRequest webRequest) {
        webRequest.addCookie(COOKIE_KEY, COOKIE_VAL);
        webRequest.addParameter("cacheId", "1");
    }

    public void testCookieName()
        throws ServletException,  JspException, IOException {

        request.setAttribute("runTest", "testCookieName");

pageContext.forward("/test/org/apache/struts/taglib/bean/TestCookieTag.jsp")
;

    }


then in the jsp, I do this:
-----------------------------------------------------------------
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="junit.framework.Assert"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<bean:define id="COOKIE_KEY"
value="org.apache.struts.taglib.bean.COOKIE_KEY"/>
<bean:define id="COOKIE_VAL" value="Testing"/>

<logic:equal name="runTest" value="testCookieName">
 <bean:cookie id="cookie" name="org.apache.struts.taglib.bean.COOKIE_KEY"/>
 <bean:define id="cookieId" name="cookie" property="value"/>
 <% Assert.assertEquals(COOKIE_VAL, cookieId); %>
</logic:equal>



I wanted to know if any of you have a preference to how we do this.

Comments?



--
James Mitchell







---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: New Tests

Posted by Robert Leland <rl...@apache.org>.
Ignore that last email I haven't

finished working out a digester example yet.

-Rob



---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: New Tests

Posted by Robert Leland <rl...@apache.org>.
James Mitchell wrote:

 > ----- Original Message -----
 > From: "Robert Leland" <rl...@apache.org>
 > To: "Struts Developers List" <st...@jakarta.apache.org>
 > Sent: Wednesday, February 12, 2003 2:00 PM
 > Subject: Re: New Tests
 >
 >
 >
 >> Martin Cooper wrote:
 >>
 >>> I prefer this second approach, because then we're testing the real
 >
 >
 > behaviour
 >
 >>> of the tags in a real container. Using a mock approach makes me nervous
 >>> because of the intricacies of tag lifecycles, and I wouldn't feel as
 >>> confident that the tags would work in the real world just because they
 >>> worked in a mock environment. I too can live with the cost of page
 >>> compilation time, traded against a better assurance that the tags are
 >
 >
 > being
 >
 >>> properly tested.
 >>>
 >>> I do, however, agree with David that we need to test the tags in
 >
 >
 > isolation.
 >
 >> I have 0 experience with Cactus,
 >>
 >> For the 1st. Method, Is there anyway you could harness the digester
 >> to create a testing harness for the tags ?
 >>
 >> The digester xml would populate the Mock session/request, and the Tags
 >> itself ?
 >> It would even have the expected values from JUnit asserts.
 >> That way the java code written hopefully could be minimized.
 >>
 >> And new tests would be cut and paste of java code and some small
 >> changes.
 >>
 >
 >
 > Now that's an interesting idea.  Care to elaborate?


Your conversation made me think of it....
Just that you need to initialize the Mock objects to setup each
test, so why not use the digester to create the mock objects.

You'd have to create the objects that are stored in the session first,
assuming they are simple bean objects creating them is easy.
Next comes the tricky part, mainly because I am not familar with the
digester. You could always use java code to set the request/session 
attributes, but could the digester do that some how ? Taking the
created objects and performing the setAttribute() calls ?
When using the digester is there some way to tag an object that when
it is created referred to by a string identifier ? Then later in the 
digester rules, use that object in a method call to do a setAttribute() ?
{Now modifying a struts-config.xml, and showing my ignorance of Digester}
Take for example
<james-tests>
   <test-beans>
     <test-bean    name="simpleTestBean"
       type="org.apache.struts.test.TestSimpleBean">
       <test-property name="username" type="java.lang.String"/>
       <test-property name="password" type="java.lang.String"/>
     </test-bean>
   </test-beans>

<!-- requests are not nested inside sessions, so they can be reused
      across multiple session tests. When reused across tests they are 
always
      reset to their initial values. Much like JUnit setup and teardown
      operations.  -->
<requests>
    <request name="simpleRequest"
       type="javax.servlet.http.HttpRequest">
       <session-property name="attribute" type="java.lang.String" 
object="simpleTestBean"/>
    <request>
</requests>

<sessions>
    <session name="simpleSession"
       type="javax.servlet.http.HttpSession">
       <session-property name="attribute" type="java.lang.String" 
object="simpleTestBean"/>
     </session>
</sessions>

</james-tests>

The object attribute tells the digester, or code that uses the digester, 
to look at the objects it has already created and call named javabean
setter, in this case setAttribute().


That would seem like at least the drudger of setting up your
unit tests could be automated some. Perhaps Cactus already does
this, it seems like a logical approach, either with digester, or betwixt
or something else. I say betwixt because then the state of the sessions
and requests could then be dumped out to another xml file/stream and the 
results viewed or compared to the expected values.

-Rob







---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: New Tests

Posted by Robert Leland <rl...@apache.org>.
James Mitchell wrote:
> ----- Original Message -----
> From: "Robert Leland" <rl...@apache.org>
> To: "Struts Developers List" <st...@jakarta.apache.org>
> Sent: Wednesday, February 12, 2003 2:00 PM
> Subject: Re: New Tests
> 
> 
> 
>>Martin Cooper wrote:
>>
>>>I prefer this second approach, because then we're testing the real
> 
> behaviour
> 
>>>of the tags in a real container. Using a mock approach makes me nervous
>>>because of the intricacies of tag lifecycles, and I wouldn't feel as
>>>confident that the tags would work in the real world just because they
>>>worked in a mock environment. I too can live with the cost of page
>>>compilation time, traded against a better assurance that the tags are
> 
> being
> 
>>>properly tested.
>>>
>>>I do, however, agree with David that we need to test the tags in
> 
> isolation.
> 
>>I have 0 experience with Cactus,
>>
>>For the 1st. Method, Is there anyway you could harness the digester
>>to create a testing harness for the tags ?
>>
>>The digester xml would populate the Mock session/request, and the Tags
>>itself ?
>>It would even have the expected values from JUnit asserts.
>>That way the java code written hopefully could be minimized.
>>
>>And new tests would be cut and paste of java code and some small
>>changes.
>>
> 
> 
> Now that's an interesting idea.  Care to elaborate?

Your conversation made me think of it....
Just that you need to initialize the Mock objects to setup each
test, so why not use the digester to create the mock objects.

You'd have to create the objects that are stored in the session first,
assuming they are simple bean objects creating them is easy.
Next comes the tricky part, mainly because I am not familar with the
digester. You could always use java code to set the request/session 
attributes, but could the digester do that some how ? Taking the
created objects and performing the setAttribute() calls ?
When using the digester is there some way to tag an object that when
it is created referred to by a string identifier ? Then later in the 
digester rules, use that object in a method call to do a setAttribute() ?
{Now modifying a struts-config.xml, and showing my ignorance of Digester}
Take for example
   <test-beans>
     <test-bean    name="simpleTestBean"
       type="org.apache.struts.test.TestSimpleBean">
       <test-property name="username" type="java.lang.String"/>
       <test-property name="password" type="java.lang.String"/>
     </test-bean>


 >









---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: New Tests

Posted by James Mitchell <jm...@apache.org>.
----- Original Message -----
From: "Robert Leland" <rl...@apache.org>
To: "Struts Developers List" <st...@jakarta.apache.org>
Sent: Wednesday, February 12, 2003 2:00 PM
Subject: Re: New Tests


> Martin Cooper wrote:
> > I prefer this second approach, because then we're testing the real
behaviour
> > of the tags in a real container. Using a mock approach makes me nervous
> > because of the intricacies of tag lifecycles, and I wouldn't feel as
> > confident that the tags would work in the real world just because they
> > worked in a mock environment. I too can live with the cost of page
> > compilation time, traded against a better assurance that the tags are
being
> > properly tested.
> >
> > I do, however, agree with David that we need to test the tags in
isolation.
> I have 0 experience with Cactus,
>
> For the 1st. Method, Is there anyway you could harness the digester
> to create a testing harness for the tags ?
>
> The digester xml would populate the Mock session/request, and the Tags
> itself ?
> It would even have the expected values from JUnit asserts.
> That way the java code written hopefully could be minimized.
>
> And new tests would be cut and paste of java code and some small
> changes.
>

Now that's an interesting idea.  Care to elaborate?


> > My preferred solution to this would be to use JSTL tags for the
surrounding
> > logic, instead of Struts tags. Unfortunately, this would preclude
testing
> > the tags in a JSP 1.1 environment. Personally, I'd be OK with that -
having
> > the tests run only in a JSP 1.2 environment is still way better than
having
>
> +1
>



--
James Mitchell



---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: New Tests

Posted by Robert Leland <rl...@apache.org>.
Martin Cooper wrote:
> I prefer this second approach, because then we're testing the real behaviour
> of the tags in a real container. Using a mock approach makes me nervous
> because of the intricacies of tag lifecycles, and I wouldn't feel as
> confident that the tags would work in the real world just because they
> worked in a mock environment. I too can live with the cost of page
> compilation time, traded against a better assurance that the tags are being
> properly tested.
> 
> I do, however, agree with David that we need to test the tags in isolation.
I have 0 experience with Cactus,

For the 1st. Method, Is there anyway you could harness the digester
to create a testing harness for the tags ?

The digester xml would populate the Mock session/request, and the Tags 
itself ?
It would even have the expected values from JUnit asserts.
That way the java code written hopefully could be minimized.

And new tests would be cut and paste of java code and some small
changes.


> My preferred solution to this would be to use JSTL tags for the surrounding
> logic, instead of Struts tags. Unfortunately, this would preclude testing
> the tags in a JSP 1.1 environment. Personally, I'd be OK with that - having
> the tests run only in a JSP 1.2 environment is still way better than having

+1



---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: New Tests

Posted by James Mitchell <jm...@apache.org>.
----- Original Message -----
From: "Martin Cooper" <ma...@apache.org>

<snip/>


> I prefer this second approach, because then we're testing the real
behaviour
> of the tags in a real container. Using a mock approach makes me nervous
> because of the intricacies of tag lifecycles, and I wouldn't feel as
> confident that the tags would work in the real world just because they
> worked in a mock environment. I too can live with the cost of page
> compilation time, traded against a better assurance that the tags are
being
> properly tested.

Yes, I forgot to mention that this also tests the struts-*.tld files since
they are required for the jsp test page.  But that's a simple change to the
build script.

Also, with the way I've structured the jsp page, it allows me to use 1
TestXXXTAg.jsp page for each TestXXXTag.java, so once the page is compiled,
it runs all the tests for that tag quickly.

I'm not sure doing the precomile within the build would help on time, but
its an option as well.

> I do, however, agree with David that we need to test the tags in
isolation.
> My preferred solution to this would be to use JSTL tags for the
surrounding
> logic, instead of Struts tags. Unfortunately, this would preclude testing
> the tags in a JSP 1.1 environment. Personally, I'd be OK with that -
having
> the tests run only in a JSP 1.2 environment is still way better than
having
> no tests! However, if others are not comfortable with this, then I think
> we'd have to resort to using scriptlets in the test pages to isolate the
tag
> tests.

I don't think relying on JSP 1.1 is a good idea wrt backward compatibility.
Although I do like the idea.

>
> --
> Martin Cooper
>
>



--
James Mitchell



---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org


Re: New Tests

Posted by Martin Cooper <ma...@apache.org>.
"James Mitchell" <jm...@apache.org> wrote in message
news:0cf101c2d2bb$4e5250d0$1f64f80a@atlanta...
> Lately, I've been focusing on building tests that cover the entire core
> struts taglibs.  I've completed logic and I'm now hacking away on the bean
> tags.

Cool!

>
> I don't claim to be expert with Cactus, but there seem to be 2 different
> approaches with respect to testing taglibs.  (There are probably more, but
> these 2 really seem to stick out in my mind)
>
> The existing logic tags use the first approach which is programmatically
> mimicing what the container will do wrt life cycle calls, the testing the
> output or (in the case of boolean results) tag.condition(0, 0).
>
> The second approach is to actually use a jsp to test the tag (this seems
> more natural to me, and tests more peices of the puzzle IMHO).  But this
> comes at the cost of time for page compilation.  Personnally, I can live
> with that cost, for the benefits of using the real thing.  Doing it this
way
> also covers a long time bullet item that I've been wanting to complete for
a
> quite some time. (Complete examples of every tag, with every conceivable
> configuration)

I prefer this second approach, because then we're testing the real behaviour
of the tags in a real container. Using a mock approach makes me nervous
because of the intricacies of tag lifecycles, and I wouldn't feel as
confident that the tags would work in the real world just because they
worked in a mock environment. I too can live with the cost of page
compilation time, traded against a better assurance that the tags are being
properly tested.

I do, however, agree with David that we need to test the tags in isolation.
My preferred solution to this would be to use JSTL tags for the surrounding
logic, instead of Struts tags. Unfortunately, this would preclude testing
the tags in a JSP 1.1 environment. Personally, I'd be OK with that - having
the tests run only in a JSP 1.2 environment is still way better than having
no tests! However, if others are not comfortable with this, then I think
we'd have to resort to using scriptlets in the test pages to isolate the tag
tests.

--
Martin Cooper


>
>
> For example:
> When building the tests for the o.a.s.t.b.TestCookieTag, a typical test
> looks like this:
>
> ...
> ...
> //============================================================
>     public void beginCookieName(WebRequest testRequest) {
>        testRequest.addCookie(COOKIE_KEY, COOKIE_VAL);
>     }
>
>     public void testCookieName()
>      throws ServletException,  JspException, IOException {
>
>         CookieTag tag = new CookieTag();
>   tag.setPageContext(pageContext);
>         tag.setName(COOKIE_KEY);
>         tag.setId("theId");
>         tag.doStartTag();
>
>         Cookie cookie = (Cookie)pageContext.getAttribute("theId");
>         assertEquals("Verify that the cookie was defined properly as a
> scripting variable",
>            COOKIE_VAL,
>            cookie.getValue());
>
>
>
>
> I rewrote this test to call a jsp instead:
>    //====================================================
>     public void beginCookieName(WebRequest webRequest) {
>         webRequest.addCookie(COOKIE_KEY, COOKIE_VAL);
>         webRequest.addParameter("cacheId", "1");
>     }
>
>     public void testCookieName()
>         throws ServletException,  JspException, IOException {
>
>         request.setAttribute("runTest", "testCookieName");
>
>
pageContext.forward("/test/org/apache/struts/taglib/bean/TestCookieTag.jsp")
> ;
>
>     }
>
>
> then in the jsp, I do this:
> -----------------------------------------------------------------
> <%@ page contentType="text/html;charset=UTF-8" language="java" %>
> <%@ page import="junit.framework.Assert"%>
> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
>
> <bean:define id="COOKIE_KEY"
> value="org.apache.struts.taglib.bean.COOKIE_KEY"/>
> <bean:define id="COOKIE_VAL" value="Testing"/>
>
> <logic:equal name="runTest" value="testCookieName">
>  <bean:cookie id="cookie"
name="org.apache.struts.taglib.bean.COOKIE_KEY"/>
>  <bean:define id="cookieId" name="cookie" property="value"/>
>  <% Assert.assertEquals(COOKIE_VAL, cookieId); %>
> </logic:equal>
>
>
>
> I wanted to know if any of you have a preference to how we do this.
>
> Comments?
>
>
>
> --
> James Mitchell




---------------------------------------------------------------------
To unsubscribe, e-mail: struts-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-dev-help@jakarta.apache.org