5 Replies Latest reply on Nov 9, 2007 7:12 AM by julien1

    Portlet Container test framework update

      It is about migrating the portlet container test framework in order to take advantage of Java 5 and make the different tests easier to write (as we plan to add lot of new tests for the JSR 286 implementation). It will only leverage for now annotations which are helpful to describe the sequence of the different methods composing a test case.

      Now we have something like

      package org.jboss.portal.test.portlet.jsr168.tck.portletinterface;
      
      public class PortletInterfaceSequenceBuilder extends PortletTestSuite
      {
       /**
       * @portlet.specification assert="SPEC:4 - After the portlet object is instantiated, the portlet container must
       * initialize the portlet before invoking it to handle requests"
       */
       public void createInitializeBeforeHandleCase(PortletTestDriver registry)
       {
       PortletTest seq = new PortletTest();
       registry.addSequence("InitializeBeforeHandle", seq);
       seq.addAction(0, InitializeBeforeHandlePortlet.RENDER_JOINPOINT, new PortletRenderTestAction()
       {
       protected DriverResponse run(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
       {
       assertTrue(InitializeBeforeHandlePortlet.init);
       return new EndTestResponse();
       }
       });
       }
      }


      Each test case should be migrated to a single class which will help to isolate the test cases from each other and will be constitued of methods annotated with @JoinPoint annotation describing when and where this methods should be executed during a portal request. There will be also the @TCK annotation that will be optional and will annotate methods that test TCK assertions present in the spec.

      package org.jboss.portal.test.portlet.jsr168.tck.portletinterface;
      
      @TCK(4)
      public class InitializeBeforeHandle
      {
       @JoinPoint(count = 0, portletId = InitializeBeforeHandlePortlet.NAME)
       public DriverResponse run(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
       {
       assertTrue(InitializeBeforeHandlePortlet.init);
       return new EndTestResponse();
       }
      }




        • 1. Re: Portlet Container test framework update

          The @JoinPoint annotation would actually contains 4 members:

          /**
           * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
           * @version $Revision: 1.1 $
           */
          public @interface JoinPoint
          {
          
           /**
           * The request count.
           *
           * @return the request count
           */
           int count() default 0;
          
           /**
           * The portlet id.
           *
           * @return the portlet id
           */
           String portletId();
          
           /**
           * The node id.
           *
           * @return the node id
           */
           NodeId node() default NodeId.DEFAULT;
          
           /**
           * The phase id.
           *
           * @return the phase id
           */
           PhaseId phase() default PhaseId.RENDER;
          }



          • 2. Re: Portlet Container test framework update

            The other way to do would be to use some public field which would allow a more typed approach and enforce the contract with the different actions:

            @TCK(4)
            public class InitializeBeforeHandle
            {
             @JoinPoint(portletId = InitializeBeforeHandlePortlet.NAME)
             public PortletRenderTestAction tmp = new PortletRenderTestAction()
             {
             protected DriverResponse run(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context) throws PortletException, IOException
             {
             Assert.assertTrue(InitializeBeforeHandlePortlet.init);
             return new EndTestResponse();
             }
             };
            }


            it is a bit more cluttered but enforces the contract. I remind here that the goal is to provide a way to break down a test spanning several classes (different portlets + servlet) of a same test case into one single place in order to make the test easy to read/write and share a common state.

            Ideas are welcome.

            • 3. Re: Portlet Container test framework update

              Another example of a more complex test case using the "method" style:

              @TCK({5,6,8})
              public class ExceptionsOnInit
              {
              
               @JoinPoint(portletId=PortletExceptionDuringInitPortlet.NAME)
               public DriverResponse a(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
               {
               PortletExceptionDuringInitPortlet.rendered = true;
               return null;
               }
              
               @JoinPoint(portletId= RuntimeExceptionDuringInitPortlet.NAME)
               public DriverResponse b(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
               {
               PortletExceptionDuringInitPortlet.rendered = true;
               return null;
               }
              
               @JoinPoint(portletId= UnavailableExceptionDuringInitPortlet.NAME)
               public DriverResponse c(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
               {
               UnavailableExceptionDuringInitPortlet.rendered = true;
               return null;
               }
              
               @JoinPoint(portletId= UTP1.NAME)
               public DriverResponse d(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
               {
               return new InvokeGetResponse(response.createRenderURL().toString());
               }
              
               @JoinPoint(count=1, portletId=UTP1.NAME)
               public DriverResponse e(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
               {
               return new InvokeGetResponse(response.createRenderURL().toString());
               }
              
               @JoinPoint(count=2, portletId=UTP1.NAME)
               public DriverResponse f(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
               {
               //portlets shouldn't render itself
               assertEquals(false, PortletExceptionDuringInitPortlet.rendered);
               assertEquals(false, UnavailableExceptionDuringInitPortlet.rendered);
               assertEquals(false, RuntimeExceptionDuringInitPortlet.rendered);
              
               //and shouldn't be destroyed as Exceptions on init() were throwed
               assertEquals(false, PortletExceptionDuringInitPortlet.destroyed);
               assertEquals(false, UnavailableExceptionDuringInitPortlet.destroyed);
               assertEquals(false, RuntimeExceptionDuringInitPortlet.destroyed);
              
               //
               return new EndTestResponse();
               }
              }



              • 4. Re: Portlet Container test framework update

                So finally I chosed an intermediary solution for now and I migrated all test cases to it. A test case looks like

                @TestCase({Assertion.JSR168_ABC,Assertion.JSR168_XYZ})
                public class MyTestCase
                {
                 public MyTestCase(PortletTest seq)
                 {
                 seq.addAction(0, MyPortlet.RENDER_JOINPOINT, new PortletRenderTestAction()
                 {
                 protected DriverResponse run(Portlet portlet, RenderRequest request, RenderResponse response, PortletTestContext context)
                 {
                 // Code test case here
                 return new EndTestResponse();
                 }
                 });
                 }
                }


                So each test case is now in a single class and it reference (optionally) an Assertion which is an enum class containing all the test case meta data, here is an excerpt:

                public enum Assertion
                {
                
                 JSR168_4(new TCK(4), "After the portlet object is instantiated, the portlet container must" +
                 " initialize the portlet before invoking it to handle requests"),
                
                 JSR168_31(new TCK(31), "", Status.jbossUntestable("why?")),
                
                 JSR168_33(new TCK(33), "", Status.duplicate(JSR168_36, "")),
                
                 JSR168_49(new TCK(49), "", Status.postponed("spec?")),
                
                }


                So each test case has a precise description in one single place which allow to easily make reporting and have a unified view.

                I still need to do a couple of refactorings on it, basically cleaning up up the joinpoint declaration mechanism.

                Also finally I did not chose to have one method per joinpoint and I still use the same old model, but for now it seems enough as it can access the test case state.

                • 5. Re: Portlet Container test framework update

                  I am done for now with that task.