Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 68 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
68
Dung lượng
3,43 MB
Nội dung
TESTING WEB APPLICATIONS WITH HTTPUNIT 307 going to write a few simple WebTest steps. The pages we will walk through are shown in figures 12.3 through 12.5. As mentioned in section 12.6.6, writing HttpUnit tests is a low-level exercise and likely involves rework and recompilation when site navigation changes. WebTest pro- vides a higher-level way to describe functional web tests. Listing 12.6 shows our build file to test these three pages. <!DOCTYPE project [ <!ENTITY properties SYSTEM "file: /properties.xml"> ]> <project name="canoo" default="main"> &properties; <taskdef name="testSpec" classname="com.canoo.webtest.ant.TestSpecificationTask"> Listing 12.6 WebTest example build file Figure 12.3 Login page of our example web application Figure 12.4 The search page of our web application. Note the pow- erful Google-like expression that is used for searching Ant’s documentation. Figure 12.5 The results page of our web application Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 308 CHAPTER 12 DEVELOPING FOR THE WEB <classpath> <fileset dir="${webtest.dist.dir}" includes="*.jar"/> </classpath> </taskdef> <property name="output.dir" location="build/canoo"/> <property name="xsl.file" location="xdocs/stylesheets/canoo.xsl"/> <property name="app.context" value="antbook"/> <property name="app.port" value="8080"/> <property name="app.host" value="localhost"/> <property name="app.username" value="erik"/> <property name="app.password" value="hatcher"/> <property name="query" value="(http AND wait) -title:API"/> <property name="expected" value="WaitFor Task"/> <target name="init"> <mkdir dir="${output.dir}"/> </target> <target name="clean"> <delete dir="${output.dir}"/> </target> <target name="main"> <testSpec name="test our site"> <config host="${app.host}" port="${app.port}" protocol="http" basepath="${app.context}" summary="true" verbose="false" saveresponse="true" resultpath="${output.dir}" haltonerror="true" haltonfailure="true"/> <steps> <invoke stepid="go to login page" url="login.jsp"/> <setinputfield stepid="set user name" name="username" value="${app.username}" /> <setinputfield stepid="set password" name="password" value="${app.password}" /> <clickbutton stepid="login" name="submit"/> <setinputfield stepid="set query" name="query" value="${query}"/> <clickbutton stepid="search" name="submit"/> <verifytext stepid="${expected} found" text="${expected}"/> Defines the WebTest task Defines default query and expected result Begins testing steps Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com TESTING WEB APPLICATIONS WITH HTTPUNIT 309 </steps> </testSpec> <xslt basedir="${output.dir}" destdir="${output.dir}" includes="TestSummary*xml" extension=".html" style="${xsl.file}" /> </target> </project> The <testSpec> task encapsulates a series of steps, and in our case the steps are: 1 Navigate to the login page. 2 Fill in the username and password fields, then submit the form. 3 Enter a query into the search form and submit it. 4 Verify that the results page includes the expected text. Ant properties are used to represent our query (${query}) and a string expected ( ${expected}) to be on the results page. We could easily rerun a test for a different query and expected result, for example: > ant -f canoo.xml -Dquery="+steve +anger" -Dexpected="Ant in Danger" 1 Buildfile: canoo.xml main: BUILD FAILED Failure: Test "test our site" failed at step "Ant in Danger found" with message "Step "Ant in Danger found" (8/9): Text not found in page. Expected <Ant in Danger>" Total time: 3 seconds It is beyond the scope of this book to cover the Canoo’s WebTest task in more detail. The WebTest distribution found at http://webtest.canoo.com contains robust docu- mentation and examples. One of the very handy things that can be done with Web- Test, thanks to Ant’s XML build file format, is to transform another XML file into a complete WebTest build file or build file fragment. A friend of ours, David Eric Pugh, has done this very thing by automating the construction of functional test cases from a DBForms model into WebTest steps. DBForms 2 is an open-source project to 1 The actual document is called “Ant in Anger.” 2 http://www.dbforms.org Transforms results into HTML Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 310 CHAPTER 12 DEVELOPING FOR THE WEB generate Model-View-Controller-style JSP pages from an XML descriptor (which can be generated from database metadata). The <xslt> task, a task we will cover in chapter 13, is used to turn the results writ- ten from the <testSpec> task into an easily navigable HTML file. One of the great benefits to WebTest is its capturing of the pages as it executes the steps. It saves each page it encounters to a separate HTML file in the resultpath directory, allowing you to see exactly what WebTest sees as it is executing. Then, with the <xslt> task, Ant creates an index for all these pages for easy analysis. 12.7 SERVER-SIDE TESTING WITH CACTUS Cactus is the Jakarta project’s J2EE container unit testing framework for unit testing server-side code. It deals with the thorny issues of testing server-side code that is dependent upon container-provided services, ranging from J2EE to SQL database access. It deals with this in a way that is simpler to describe than to implement: by running all the unit tests on the server. For example, we have developed a utility method that returns a specific parameter or attribute from an HttpServletRequest object. This is a useful utility for cases where either the URL (or form POST) contains a parameter or it has been injected into the request scope attributes during server-side forwards. There is no single method to retrieve the parameter regardless of which of these two scopes it is in, so we have to write one: package org.example.antbook; import javax.servlet.http.HttpServletRequest; public class RequestUtil { public static final String getValue (HttpServletRequest request, String key) { String value = request.getParameter(key); if (value != null) { return value; } value = (String) request.getAttribute(key); if (value != null) { return value; } return null; } } Having written a class, we now need to test it. How can we test this class and its getValue method with JUnit? There are two popular methods: Mock Objects and Cactus. Mock Objects are emulations of objects such as the servlet API, which you can then use inside normal <junit> tests to invoke code inside a mock server. They Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com SERVER-SIDE TESTING WITH CACTUS 311 would be handled with <junit> as covered in chapter 4. We are not going to cover Mock Objects, but rather refer you to http://www.mockobjects.com for further exploration. Mock Objects are powerful in their own way. We are going to take a look at Cactus, because its model for server-side unit tests is unique and tightly integrated with Ant. Our coverage of Cactus is intentionally brief. It is a fairly complex framework to explain architecturally, and it has been documented beautifully by Vincent Massol at the Cactus web site (http://jakarta.apache.org/cactus/), as well as in our good friends’ book, Java Tools for Extreme Programming (Hightower & Lesiecki 2001). 12.7.1 Cactus from Ant’s perspective Let’s take a look at what makes Cactus tick from an Ant perspective. To run test cases in a J2EE container, you first need a running container, of course. Yet, we do not want the burden of manually having to deploy, start, and stop our application server. Cactus does this for us with its <runservertests> Ant task. This task is part of the Cactus distribution, and looks quite elegant in our build file. Listing 12.7 shows the build file pieces used to run our Cactus unit tests. Our example was adapted easily from the sample provided with the Cactus distribution with very few changes, mostly in a build.properties file to configure the location of libraries needed for compilation and deployment. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 312 CHAPTER 12 DEVELOPING FOR THE WEB <target name="tests_tomcat_40" depends="prepare_tests_tomcat_40" if="tomcat.home.40"> <runservertests testURL="http://localhost:${test.port}/test" startTarget="start_tomcat_40" stopTarget="stop_tomcat_40" testTarget="tests"/> </target> <target name="start_tomcat_40"> <java classname="org.apache.catalina.startup.Bootstrap" fork="true"> <jvmarg value="-Dcatalina.home=${tomcat.home.40}"/> <arg value="-config"/> <arg value="${out.tomcat40.full.dir}/conf/server.xml"/> <arg value="start"/> <classpath> <pathelement path="${java.class.path}"/> <fileset dir="${tomcat.home.40}"> <include name="bin/bootstrap.jar"/> <include name="server/catalina.jar"/> </fileset> </classpath> </java> </target> <target name="stop_tomcat_40"> <java classname="org.apache.catalina.startup.Bootstrap" fork="true"> <jvmarg value="-Dcatalina.home=${tomcat.home.40}"/> <arg value="stop"/> <classpath> <pathelement path="${java.class.path}"/> <fileset dir="${tomcat.home.40}"> <include name="bin/bootstrap.jar"/> <include name="server/catalina.jar"/> </fileset> </classpath> </java> </target> Listing 12.7 Part of a build file to run server-side tests with Cactus Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com SERVER-SIDE TESTING WITH CACTUS 313 12.7.2 How Cactus works Again, we’ll refer you to the Cactus documentation for more details about how it works, but here is a brief description. You write test cases that extend from the Cactus base test case classes: ServletTestCase, JspTestCase, or FilterTestCase. Your test cases are compiled and deployed on an application server and also remain on the client where Ant is running. The <runservertests> task is an interesting beast: it accepts other Ant target names as parameters and uses those in a multi- threaded way. First, the target specified by startTarget is executed in its own thread to keep the process from blocking, followed by the testTarget and finally the stopTarget. The startTarget for Tomcat, as shown in listing 12.7, starts Tomcat from our freshly built deployment directory. A configuration file is built dynamically using filtered <copy> tasks to customize the environment for our desired settings. The tests run using the standard <junit> techniques shown in chapter 4. There is no distinction within Ant’s <junit> between a Cactus test case and any other JUnit test case. Figure 12.6 shows what happens under the covers. The client-side (from Ant) test case is executed through the <junit> framework. On the client side, methods beginning with begin and end are invoked before and after executing the actual test method on the server side. The proxy invokes the stan- dard setUp and tearDown methods on the server side. The begin-prefixed method is used for configuring the HTTP request parameters, such as cookies, HTTP headers, and URLs to simulate. The end-prefixed method is more complex in that it can have one of two different method signatures. There is a Cactus Web- Response and an HttpUnit WebResponse class. This lets you use HttpUnit, as de- scribed earlier in this chapter, to do sophisticated, test-generated, HTML results cont ent testing. If your test does not require HttpUnit testing, then simply use the Cactus WebResponse class in the endXXX method signature. The beginXXX, endXXX, setUp, and tearDown methods are all optional. Web Container beginXXX endXXX setUp testXXX tearDown Server-side classes OurTest Redirector Proxy OurTest Figure 12.6 Cactus unit tests run server-side, using a proxy servlet to bind them to the Ant-hosted tests. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 314 CHAPTER 12 DEVELOPING FOR THE WEB 12.7.3 And now our test case To t e st our getValue method using Cactus, we create two test methods. One tests that a parameter is obtained from the URL parameters. Another tests that, if a param- eter exists in both request scope and part of the URL parameters, the URL parameter overrides the one from request scope. Listing 12.8 shows our test case to exercise the getValue method. The ServletTestCase provides access to the HttpServletRe- quest object as the member variable request. package org.example.antbook; import org.apache.cactus.ServletTestCase; import org.apache.cactus.WebRequest; public class RequestUtilTest extends ServletTestCase { public RequestUtilTest(String theName) { super(theName); } public void beginGetValueParam(WebRequest theRequest) { theRequest.setURL("localhost:8080", "/antbook", "/test/test.jsp", null, "param=url"); } public void testGetValueParam() { request.setAttribute("param", "request"); assertEquals("url", RequestUtil.getValue(request, "param")); } public void testGetValueAttribute() { request.setAttribute("param", "request"); assertEquals("request", RequestUtil.getValue(request, "param")); } } One of the easily misunderstood facets of Cactus is that it does not actually make a connection to the URL provided, as shown in the beginGetValueParam of list- ing 12.8. The connection is made to one of the Cactus redirectors. 12.7.4 Cactus summary Cactus is the premiere way to test server-side objects through a J2EE web container. It takes care of all the hard work involved in starting and stopping application servers. There are many application servers with Cactus support already provided, but it can be Listing 12.8 Cactus test case Adds ?param=url to URL Ensures value is from URL Ensures request-scope value works when no URL parameter is present Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com SUMMARY 315 easy to add new vendor support if your vendor is not one of them. All J2EE-compliant application servers should work with Cactus tests. The trick is how to start, stop, and deploy to them automatically from Ant. We tested using Tomcat 4 (a.k.a. Catalina), which of course has excellent Cactus support. Much of Cactus is web related, and it communicates to the server through a web container. Cactus also can be used to test EJB container code, although that is a bit more difficult and beyond the scope for this chapter. We recommend that you separate Cactus tests and pure client-side tests in your directory and package structure, or do so by naming conventions. This lets you run tests in environments where the container is not accessible or configured, and having the option to run only the client-side tests is nice. Consider also using Cactus tests as part of a continuous integration process, such that your in-container tests are executed with the latest integrated codebase on a periodic basis. Cactus tests tag libraries, Struts actions, servlets, and any other server-side classes that are accessible. As with pure client-side JUnit tests, there are techniques and base classes that you can use to make testing of server-side APIs easier. For example, there is a StrutsTestCase base class available that facilitates testing Struts actions by asserting that you get an ActionForward that was expected. 12.8 SUMMARY This chapter has explored some of the web application specific issues of Java develop- ment, and shown how Ant can integrate with other open source tools to automate the development and test process for web applications. Writing JSP tag libraries is much easier with the XDoclet <webdoclet> task, which can extract tag declaration data from the javadoc comments in the code. You can also use this task for the conditional inclusion of content into the web.xml deploy- ment descriptor, which is convenient when you need to distinguish between develop- ment and release versions of your application, or configure multiple servers’ versions differently. To compile JSP pages before deployment, you can use the <jspc> task. This task converts JSP pages into Java source files, which a normal <javac> task can compile. Of the two uses for this task, validation and actual precompilation, we are most com- fortable with the former. Feel free, however, to experiment with inclusion of the gen- erated servlets into your application. We have introduced HttpUnit for functional testing of web sites, and shown how to use it from Ant, validating web applications the moment that deployment has com- pleted. Together, the automated generation of deployment metadata, JSP precompi- lation, and postdeployment testing can raise your Ant-based builds far beyond what an IDE-based build process can accomplish. It may seem that we have turned a fairly simple build process into a complex one, and certainly for the size of our example application it does seem overkill. However, we now have a build process that can cope Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com 316 CHAPTER 12 DEVELOPING FOR THE WEB with a larger project: as new taglibs and JSP pages are added, all we need to do is add new HttpUnit tests. Finally, we have presented the Cactus in-container JUnit testing framework. It takes the hard work out of the issues involved with automating the start, stop, and deploy to J2EE application servers. Cactus is a great way to test code that relies on con- tainer-managed classes like HttpServletRequest. Not only can testing your code with Cactus ensure that it works, Cactus gives you regressions tests for when you need to run on a new application server, or simply a new version of your current server. For your own projects, we recommend that you gradually adopt these advanced build process techniques as the need arises. The need for functional testing will prob- ably arise first, but compiling JSP pages can make JSP page development a lot faster. Tag libraries are always going to be tricky to write and test: the moment you write a taglib you should adopt the XDoclet-based TLD generation process to save time and effort. Cactus does take time to understand and work with, and you do need to invest the effort in writing the tasks to start and stop your server. However, once you have your Cactus test framework working, it soon becomes an integral part of servlet and EJB testing. No other mechanism lets you run detailed unit tests upon the internal components of your server-side application. Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com [...]... a normal Ant 1.5 installation of Ant comes with the Xerces XML parser, which can be used for parsing and validating XML If you 318 CHA PTE R 13 WORKING WITH XML Simpo PDF Merge and Split Unregistered Version - http://www.simpopdf.com want to perform any XSLT transforms in Ant, you also need version 2 of Xalan;1 you can download it from http://xml.apache.org/ Prior to Ant 1.5, Ant shipped with Crimson... Obviously, an Ant task to create the classes is the way to integrate this with an Ant- based build process We would expect such a task to appear shortly after Sun finally releases JAXB There is also an open source project, Castor, (at exolab.org), that, among other things, creates Java classes from an XSD schema We use Castor in our projects, simply with a call; it’s good, but needs an Ant task with dependency... 333 A simple EJB build 335 Using Ant s EJB tasks 3 36 Using 337 Using XDoclet for EJB development 340 14 .6 Middlegen 345 14.7 Deploying to J2EE application servers 348 14.8 A complete EJB example 349 14.9 Best practices in EJB projects 354 14.10 Summary 354 Building Enterprise JavaBeans applications is a complex Java development process The sheer volume of Java code needed for each entity bean... Working with XML 13.1 13.2 13.3 13.4 Preamble: all about XML libraries 318 Validating XML 319 Transforming XML with XSLT 323 Generating an XML build log 327 13.5 Loading XML data into Ant properties 331 13 .6 Next steps in XML processing 13.7 Summary 332 332 XML is rapidly becoming a language that most Java projects have to work with in one way or another It hosts the configuration data for so much of Java, ... want to keep helper build files in a subdirectory, controlling directory clutter The output log indicates that the build file did locate the files we wanted: Buildfile: tasklib\create-html-log.xml default: [style] Processing C:\AntBook\app\log\deploy-log.xml to C:\AntBook\app\log\deploy.html [style] Loading stylesheet C: \Java\ Apps\jakarta -ant\ etc\log.xsl BUILD SUCCESSFUL 330 CHA PTE R 13 WORKING WITH. .. in ANT_ HOME/etc; it transforms the log files into readable HTML You need to copy this into your destination directory, or tell the listener to use a different stylesheet by setting the Ant property ant. XmlLogger.stylesheet.uri You can use this property to bind directly to the log.xsl file in the Ant directory by pointing the property at it: . Java develop- ment, and shown how Ant can integrate with other open source tools to automate the development and test process for web applications. Writing JSP tag libraries is much easier with. in Ant, you also need version 2 of Xalan; 1 you can download it from http://xml.apache.org/. Prior to Ant 1.5, Ant shipped with Crimson and JAXP libraries. The xalan.jar library must go into ANT_ HOME/lib. Although. site" failed at step " ;Ant in Danger found" with message "Step " ;Ant in Danger found" (8/9): Text not found in page. Expected < ;Ant in Danger>" Total time: