Section 3.7. Executing HtmlUnit Tests


3.7. Executing HtmlUnit Tests

Great, you've started a Servlet container! Now you will learn how to use this container to execute functional tests to validate the web subproject's WAR.

3.7.1. How do I do that?

First things first; write an HtmlUnit test. The purpose of this chapter is not to teach you the intricacies of HtmlUnit (see http://htmlunit.sourceforge.net/ for a good tutorial). Instead, this lab will focus on how you can integrate HtmlUnit with Maven and the Jetty plug-in. Without further ado, here's what a test of the QuoteServlet could look like:

package mdn.qotd.acceptance;    import java.net.URL;    import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.HtmlPage;    import junit.framework.TestCase;    public class QuoteServletTest extends TestCase {     public void testMainServletPage( ) throws Exception     {         WebClient webClient = new WebClient( );         URL url = new URL("http://localhost:8081/qotd-web");         HtmlPage page = (HtmlPage) webClient.getPage(url);         String content = page.getWebResponse( ).getContentAsString( );         assertTrue(content.startsWith("\""));         assertTrue(content.endsWith("\""));     } }

You will notice that an HtmlUnit test case is a JUnit test case (it extends JUnit's TestCase class), and this means that you can use the Maven Test plug-in to execute it. Before doing so you need to add all of HtmlUnit's JAR dependencies to the acceptance subproject's project.xml:

<dependency>   <groupId>htmlunit</groupId>   <artifactId>htmlunit</artifactId>   <version>1.3</version> </dependency> <dependency>   <groupId>nekohtml</groupId>   <artifactId>nekohtml</artifactId>   <version>0.9.4</version> </dependency> <dependency>   <groupId>commons-httpclient</groupId>   <artifactId>commons-httpclient</artifactId>   <version>2.0.2</version> </dependency> <dependency>   <groupId>commons-logging</groupId>   <artifactId>commons-logging</artifactId>   <version>1.0.4</version> </dependency>


Tip: What a pain it is to enter all those HtmlUnit dependencies! You should really have to enter only one HtmlUnit dependency and Maven should figure out how to include HtmlUnit's own dependencies. Good news! You can, with a feature called Transitive Dependencies, which is being implemented in Maven 2.

Executing the test:test goal now would fail, because you also need to have a container started. The solution is to start the container in one thread using the Jetty plug-in and to start the Test plug-in in another thread. You can achieve this by writing some custom Jelly code in the acceptance/maven.xml file and using the j:tHRead element of the core Jelly tag library:

<?xml version="1.0"?>    <project default="test:test"     xmlns:j="jelly:core"     xmlns:ant="jelly:ant">      <preGoal name="test:test">     <j:thread>       <attainGoal name="jetty:run"/>     </j:thread>     <ant:waitfor>       <ant:http url="http://localhost:${maven.jetty.port}/qotd-web"/>     </ant:waitfor>   </preGoal>    </project>

Notice that you are using a preGoal, which means that the Jelly scriptlet will be executed whenever the test:test goal is executed. You are also using the waitfor Ant task which waits here for the QOTD web application to be started (you do not want to start executing your test before the QOTD web application is ready to service requests).

Run the tests by executing the test:test goal:

C:\dev\mavenbook\code\qotd\acceptance>maven test:test [...] test:test: jetty:prepare-filesystem:    jetty:config:    jetty:run:     [java] 09:37:54.469 EVENT  Checking Resource aliases     [java] 09:37:54.619 EVENT  Starting Jetty/4.2.17     [java] 09:37:54.639 WARN!! Delete existing temp dir C:\DOCUME~1\[...][/qotd-web, jar:file:/C:/Documents%20and%20Settings/[...]/.maven/repository/mdn/wars/qotd-web-1.0. war!/]     [java] 09:37:54.709 EVENT  Started WebApplicationContext[/qotd-web,jar:file:/C:/ Documents%20and%20Settings/[...]/.maven/repository/mdn/wars/qotd-web-1.0.war!/]     [java] 09:37:54.729 EVENT  jsp: init     [java] 09:37:54.820 EVENT  default: init     [java] 09:37:54.820 EVENT  invoker: init     [java] 09:37:54.850 EVENT  Started SocketListener on 0.0.0.0:8081     [java] 09:37:54.850 EVENT  Started org.mortbay.jetty.Server@117a8bd     [java] 09:37:55.380 EVENT  QuoteServlet: init     [junit] Testsuite: mdn.qotd.acceptance.QuoteServletTest     [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 1,122 sec     [junit] ------------- Standard Error -----------------     [junit] 26 mars 2005 09:37:56 org.apache.commons.httpclient.HttpMethodBase  processRedirectResponse     [junit] INFO: Redirect requested but followRedirects is disabled     [junit] ------------- ---------------- ---------------     [junit]     [junit] Testcase: testMainServletPage took 0,852 sec BUILD SUCCESSFUL Total time: 5 seconds

3.7.2. What just happened?

In the last two labs you have been able to set up automated functional tests of a web application using the HtmlUnit test framework, the Maven Jetty plug-in, and the Maven Test plug-in. You should notice also that you have not had to write code or define much of the process.

3.7.3. What about...

...not hardcoding the 8081 port in QuoteServletTest?

You are right. Hardcoding has to be avoided at all costs! One good solution is to pass the port you've defined in the maven.jetty.port property as a System property to the JUnit test. To do this you would need to make the following changes:

  • Modify the QuoteServletTest to use this maven.jetty.port property:

String port = System.getProperty("maven.jetty.port", "80"); URL url = new URL("http://localhost:" + port + "/qotd-web");

  • Add the following property to acceptance/project.properties so that the Test plug-in can pass the maven.jetty.port property value to your JUnit TestCase:

maven.junit.sysproperties = maven.jetty.port



Maven. A Developer's Notebook
Maven: A Developers Notebook (Developers Notebooks)
ISBN: 0596007507
EAN: 2147483647
Year: 2003
Pages: 125

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net