8 Replies Latest reply on Jan 28, 2011 10:22 AM by aslak

    JSFUnit integration: still some work to do

    dan.j.allen

      I was hoping to have a demo of using JSFUnit with Arquillian for my Java EE testing talk at NFJS, but I ran out of time trying to make it work. It appears there's still work that needs to be done to make this integration smooth, or work at all.

       

      There are at least two challenges at the moment:

       

      • JSFUnit requires a lot of third-party JAR files and the burden of packaging them falls on the user
      • The protocol servlet can't find the test class for some reason (I'm getting a classloader exception)

       

      I'll document my steps so far.

       

      1. Collect dependent JARs

       

      I needed to grab the dependent JAR files and put them in a place where ShrinkWrap could find them. I used a Maven profile to pull the dependencies from the repository and stick them in the target/test-classes/jsfunit/lib directory. (The target location I choose is a hack to just get past this step).

       

      <dependencies>
         ...
         <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
         </dependency>
      </dependencies>
         
      <profiles>
         <profile>
            <id>jsfunit</id>
            <dependencies>
               <dependency>
                  <groupId>org.jboss.jsfunit</groupId>
                  <artifactId>jboss-jsfunit-core</artifactId>
                  <version>1.2.0.Final</version>
                  <scope>test</scope>
                  <dependency>
                     <groupId>org.apache.ant</groupId>
                     <artifactId>ant</artifactId>
                     <version>1.7.0</version>
                     <scope>test</scope>
                  </dependency>
               </dependency>
            </dependencies>
            <build>
               <plugins>
                  <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <executions>
                      <execution>
                        <id>copy-dependencies</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                          <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                           <outputDirectory>target/test-classes/jsfunit/lib</outputDirectory>
                           <includeScope>test</includeScope> 
                           <includeArtifactIds>
                              jboss-jsfunit-core,aspectjrt,cactus,nekohtml,htmlunit,
                              htmlunit-core-js,cssparser,commons-httpclient,commons-io,
                              sac,commons-lang,commons-codec,commons-logging,
                              commons-collections,cactus-ant,cargo,ant
                           </includeArtifactIds>
                           <stripVersion>true</stripVersion>
                        </configuration>
                      </execution>
                    </executions>
                  </plugin>
               </plugins>
            </build>
         </profile>
      </profiles>
      

       

      2. Write sample code

       

      I created some sample JSF application code to test. I added a simple HelloWorld managed bean under src/test/java. I then created a web page that uses the managed bean under src/test/resources/jsfunit along with a faces-config.xml descriptor (to load JSF).

       

      3. Write Arquillian test

       

      Next, I created an Arquillian test that generates a WAR and adds the sample code and JSFUnit dependencies to it.

       

       

      @RunWith(Arquillian.class)
      public class JsfUnitTest
      {
         private static final ByteArrayAsset EMPTY_BEANS_XML = new ByteArrayAsset(new byte[0]);
      
         private static final String[] JSF_UNIT_LIBS = {
            "jboss-jsfunit-core.jar", "aspectjrt.jar", "cactus.jar", "nekohtml.jar", "htmlunit.jar",
            "htmlunit-core-js.jar", "cssparser.jar", "commons-httpclient.jar", "commons-io.jar",
            "sac.jar", "commons-lang.jar", "commons-codec.jar", "commons-logging.jar",
            "commons-collections.jar", "cactus-ant.jar", "cargo.jar", "ant.jar" 
         };
      
         @Deployment
         public static WebArchive createTestArchive()
         {
            WebArchive war = ShrinkWrap.create("test.war", WebArchive.class)
               .addClasses(HelloWorld.class)
               .addResource("jsfunit/home.xhtml", "home.xhtml")
               .addWebResource("jsfunit/default.xhtml", "templates/default.xhtml")
               .addWebResource("jsfunit/faces-config.xml", "faces-config.xml")
               .addWebResource(EMPTY_BEANS_XML, "beans.xml");
            for (String lib : JSF_UNIT_LIBS) {
               war.addLibrary("jsfunit/lib/" + lib, lib);
            }
            System.out.println(war.toString(true));
            return war;
         }
      
         @Test
         public void shouldExecutePage() throws Exception
         {
            JSFSession jsfSession = new JSFSession("/home.jsf");
      
            JSFServerSession server = jsfSession.getJSFServerSession();
            JSFClientSession client = jsfSession.getJSFClientSession();
      
            System.out.println(client.getPageAsText());
      
            assertEquals("Hello, World!", server.getManagedBeanValue("#{helloWorld.text}"));
         }
      }
      

       

      4. Execute the test

       

      I then executed the test against a remote JBoss AS instance. The result: boom!

       

      mvn test -Pjbossas-remote-60 -Dtest=JsfUnitTest

       

      Arquillian does properly deploy the ShrinkWrap archive and I see JSF startup. But the protocol servlet fails to locate the test class.

       

      I'd like to get this working because this framework is in the circle of the JBoss Testing initiative and therefore should have nice tight integration.

        • 1. Re: JSFUnit integration: still some work to do
          aslak

          The way I did it when i created the prototype was:

           

          • Created a JSFUnit AuxiliaryArchiveAppender that would package up JSFUnit
            • including dependencies
            • and a web-fragment that will bind the JDFUnit filter to the ArquillianServletProtocol url
            • and standard faces-config from jsfunit
          • Changed the ServletProtocol  AuxiliaryArchiveAppender to use web-fragments, so it will be found/deployed
          • Created a new Packager that only supported WebArchive as a @Deployment. It would add all the  AuxiliaryArchives to the users WebArchive

           

          The issues that came up was:

           

          • The JSFUnitAuxillaryArchiveAppender is a bit of a beast.
            • same goes for any 'framework' integration. better way to 'merge' them in then a complete shrinkwrapification.
          • The new Protocol  AuxiliaryArchiveAppender is only supported in EE 6 containers due to the use of fragments
          • For Glassfish Embedded the ServletContainerInitializer is found on the 'client' side but fails to execute
          • 2. Re: JSFUnit integration: still some work to do
            dan.j.allen

            Aslak Knutsen wrote:

             

            The way I did it when i created the prototype was:

             

            • Created a JSFUnit AuxiliaryArchiveAppender that would package up JSFUnit
              • including dependencies
              • and a web-fragment that will bind the JDFUnit filter to the ArquillianServletProtocol url
              • and standard faces-config from jsfunit
            • Changed the ServletProtocol AuxiliaryArchiveAppender to use web-fragments, so it will be found/deployed
            • Created a new Packager that only supported WebArchive as a @Deployment. It would add all the  AuxiliaryArchives to the users WebArchive

             

            Ah, so that was the special sauce Sounds like something we may want to provide as an extension until there is an easier way.

             

            The issues that came up was:

             

            • The JSFUnitAuxillaryArchiveAppender is a bit of a beast.
              • same goes for any 'framework' integration. better way to 'merge' them in then a complete shrinkwrapification.
            • The new Protocol  AuxiliaryArchiveAppender is only supported in EE 6 containers due to the use of fragments
            • For Glassfish Embedded the ServletContainerInitializer is found on the 'client' side but fails to execute

             

            I'm fine with only supporting EE 6 containers in the spirit of a working prototype. We can go from there (perhaps even get Stan involved) to make it more compatible. In a sense, give him an olive branch so that he is motivated to put some thought into the integration.

            • 3. Re: JSFUnit integration: still some work to do
              aslak

              Ah, so that was the special sauce Sounds like something we may want to provide as an extension until there is an easier way.

              'All' frameworks we want to add support for will need some kind of arquillian bridge code. At the bare minnimum being a  AuxiliaryArchiveAppender.

               

               

              I'm fine with only supporting EE 6 containers in the spirit of a working prototype. We can go from there (perhaps even get Stan involved) to make it more compatible. In a sense, give him an olive branch so that he is motivated to put some thought into the integration.

              The problem is that the ServletProtocol will only run in EE6, which means no EE5 support in Arquillian at all.

               

              I guess we could split them up, ServletProtocol-5 and 6.

              • 4. Re: JSFUnit integration: still some work to do
                dan.j.allen

                Aslak Knutsen wrote:

                 

                Ah, so that was the special sauce Sounds like something we may want to provide as an extension until there is an easier way.

                'All' frameworks we want to add support for will need some kind of arquillian bridge code. At the bare minnimum being a  AuxiliaryArchiveAppender.

                 

                Well, yes and no. I'd say ideally it would be so simple to add libraries to the archive that you could get away with the manual approach. But I understand it must be considered on a case-by-case basis.

                 

                I'm fine with only supporting EE 6 containers in the spirit of a working prototype. We can go from there (perhaps even get Stan involved) to make it more compatible. In a sense, give him an olive branch so that he is motivated to put some thought into the integration.

                The problem is that the ServletProtocol will only run in EE6, which means no EE5 support in Arquillian at all.

                 

                I guess we could split them up, ServletProtocol-5 and 6.

                 

                Sounds like it. JIRA?

                • 5. Re: JSFUnit integration: still some work to do
                  aslak
                  • 6. Re: JSFUnit integration: still some work to do
                    aslak
                    • 7. JSFUnit integration: still some work to do
                      craiggreenhalgh

                      Is there an example of this working with JSFUnit ?

                       

                      Thanks

                       

                      Craig

                      • 8. JSFUnit integration: still some work to do
                        aslak