********************************************************************************
*                                                                              *
*                                   P A T A N G                         *
*                                                                              *
********************************************************************************

Patang is a framework for testing server-side code. Patang intends to simplify
writing and executing acceptance and unit integration tests for server-side code.
It implements an in-container testing strategy, meaning that the tests are
executed inside the container.

Patang provides the infrastructure/framework to run fit tests inside the container.
What type of fit tests you write will determine which type of testing you can do
with Patang.

Why another framework?

Several kinds of functional and unit testing frameworks are available for testing enterprise applications. They can be broadly categorized into 3 types: 1. Unit isolation testing. State based or interaction based testing frameworks such as JUnit or Mock objects seem to fit well. 2. Unit integration testing. These tests will exercise the interactions with the container. Frameworks like Cactus, JUnitEE, etc suite this category. 3. Functional unit integration testing. Frameworks which let you test full use cases which can be composed of several requests/responses cycles. Some times these are also referred to as unit acceptance tests. HttpUnit, Fit, etc fit into this category. Mostly on enterprise projects, three or more, different frameworks are used just to test the functionality of the code. Patang proposes to use Ward Cunningham's FIT framework to achieve second and third category of testing. This can be easily achieved by running FIT inside the container by having a FitServlet, which can execute the fit tests. As of now Patang works with fitnesse. But the vision is to make it generic enough so that we can run plain FIT tests.

Advantages of this approach:

1. Reuse of tests. Usually there is an overlap between acceptance tests and integration tests. We can use pretty much same/similar fit tests for both. 2. EJB References, JNDI lookups, transaction management, container security, data sources and other container provided facilities can be used the same way in test environment as in development environment. 3. Test First Development: Helps in driving development with a failing tests. These are mostly black box tests at different layers of the architecture. 4. Easy of deployment and maintenance of test and development environments. All you need is the servlet and the fit framework running. 5. Remote debugging: It is very easy to debug your server side code by driving it through tests and stepping through the code in your favorite IDE 6. Bringing test environment much closer to production environment: In most of the enterprise web applications you have a web front end running inside a web container calling business components running in an application server. Executing FIT tests using patang, simulates the web front end and hence is much closer to the real world.

How does fitnesse work currently?

When you click on the test button on the fitnesse page, the following steps occur 1. The TestResponder class gets invoked a. Based on the !path variable defined on the root page, it builds the classpath b. It uses the TEST_RUNNER variable to figure out the class that needs to be invoked to run the fit tests. It defaults to fit.FitServer c. Spawns a new thread and invokes the fit.FitServer class in a new java process with the classpath it just built. It passes 3 parameters to this class. i. Host on which fitnesse is running. ii. Port on which fitnesse is running. iii. Socket token or id, to identify d. Declares itself as the socket listener and waits for socket connection from fit.FitServer class based on the socket token 2. Inside the FitServer class, a. it establishes a socket connection with the fitnesse server based on the host and port given to it b. On this socket connection, it makes a http request as follows "GET /?responder=socketCatcher&ticket="+socketToken+" HTTP/1.1\r\n\r\n" c. This will help to connect back to the TestResponder class, which then returns the fit test page [html] as a string d. It creates a parse object from this string and invokes the doTable() on a new fit fixture. Eg: newFixture().doTables(tables); e. It then publishes the results back on the wiki page thru the TestResponder 3. The TestResponder class waits on the thread in which it invoked the FitServer class. Once the FitServer class has terminated, it does all the publishing stuff and stops.

Issues with this approach:

1. EJB Refs and other container provided features won't work : If you are trying to tests EJBs which are been looked up using EJB Refs, then they won't work. Let's say you are doing your EJB lookup inside your business delegate classes. In this case, you would write a fixture class which calls the business delegate, which in turn calls your EJB. But your fixture classes and business delegate classes are running in a new JVM [FitServer space] and they cannot resolve the EJB refs as they are not running inside the container [Application server space] 2. Remote debugging won't work : If your fit tests are testing some J2EE components, it is not possible to use the remote debugging options provided by the IDEs coz we have 3 different JVMs involved. [fitnesse, FitServer, Application Server]. Also you need to look at 2 different logs for trace statements. So debugging gets very tricky. 3. Difference in test and production environment : In production env, you would have a web front end running inside a web container which calls the EJBs residing inside the EJB container thru the Business Delegates. Hence you would have the EJBs being invoked from the web container and you would probably want something similar in your fit tests. You don't want EJBs been called directly from outside the container. 4. Managing classpath mess : Defining the classpaths on the .root page can get very cryptic and error prone. Development teams tend to waste a lot of time setting up classpath and maintaining it. 5. Setting up and maintaining another environment : If you trying to run tests from Fitnesse, then you need to configure and maintain a lot of other stuff for your enterprise app to work properly. I have seen a lot of teams struggling with properties, log files, security, etc

Solution: Patang

We want the FitServer class to be invoked inside the web container. This will help us setup remote debugging on the web container and easily debug the fixture, business delegate and actual EJB code. This also helps us to avail all the EJB ref look ups and other container provided services. With the fit tests running inside the container, we can use the container's class load and hence we do not need to maintain classpaths on .root page.

Setting up Patang for Fit:

1. Add the fit.server.FitServlet definition to the deployment descriptor of your web container [web.xml]. An example is available in the docs/web.xml file. 2. Added the absolute path to the directory containing fit tests and the results directory as init-params to the servlet. 3. Deploy the patang-fit.jar file to you web app by putting patang-fit.jar and fit.jar under the WEB-INF/lib folder. 4. If you plan to call your fit tests during your continuous integration build, use the fit.client.ServletInvoker class, which communicates with the fit.server.FitServlet in the web container. This servlet can be used to run your fit tests inside the container directly from the web browser or from the ant build file. An example of this is available in the docs/build.xml file

Setting up Patang for Fitnesse:

1. Add the following line at the parent fit test page. !define TEST_RUNNER {fitnesse.client.FitServerServletInvoker} This will tell fitnesse [TestResponder class] to invoke fitnesse.client.FitServerServletInvoker class instead of fit.FitServer !define COMMAND_PATTERN {java -cp %p %m http://localhost:port/yourAppName/FitServlet} 2. This helps us pass the URL of the fit servlet that needs to be invoked 3. Add the patang-fitnesse.jar file to fitnesse path. [Add it to the !path property on the root page] 4. The fitnesse.client.FitServerServletInvoker class makes an HttpURLConnection to your web container, call the appropriate Servlet [fitnesse.server.FitServlet] on the container and pass all the arguments it got. [3 parameters: host, port and socketToken] 5. The FitServlet invokes the FitServer class with the parameters it's got. 6. Add the fitnesse.server.FitServlet definition to the deployment descriptor of your web container [web.xml]. An example is available in the docs/web.xml file. 7. If you plan to call your fit tests during your continuous integration build, use the fitnesse.TestRunnerServletInvoker class which uses the TestRunner class instead of the FitServer. This servlet can be used to run your fit tests inside the container directly from the web browser or from the ant build file. An example of this is available in the docs/build.xml file 8. Make sure patang-fitnesse.jar and fitnesse.jar are on the classpath of fitnesse, ant and they are deployed inside your web application by putting them under the WEB-INF/lib dir.

Setting up Patang for SLIM Fitnesse:

1. Add the following line at the parent fit test page. !define TEST_RUNNER {fitnesse.client.SlimServerServletInvoker} This will tell fitnesse [TestResponder class] to invoke fitnesse.client.SlimServerServletInvoker class instead of fit.FitServer !define COMMAND_PATTERN {java -cp %p %m http://localhost:port/yourAppName/SlimServlet} 2. This helps us pass the URL of the slim servlet that needs to be invoked 3. Add the patang-fitnesse.jar file to fitnesse path. [Add it to the !path property on the root page] !define TEST_SYSTEM {slim} !path absolute path to fitnesse.jar !path absolute path to patang-fitnesse.jar 4. The fitnesse.client.SlimServerServletInvoker class makes an HttpURLConnection to your web container, call the appropriate Servlet [fitnesse.server.slim.SlimServlet] on the container and pass all the arguments it got. [parameter: port] 5. The SlimServlet invokes the SlimServer class with the parameters it's got. 6. Add the fitnesse.server.slim.SlimServlet definition to the deployment descriptor of your web container [web.xml]. An example is available in the docs/web.xml file. 7. Make sure patang-fitnesse.jar and fitnesse.jar are on the classpath of fitnesse, ant and they are deployed inside your web application by putting them under the WEB-INF/lib dir. 8. If web container/ application server is on a different machine than where Fitnesse server is running, then configure the following !define SLIM_HOST (ip address of the application server) 9. By defualt, SLIM test system uses the port 8085 to communicate with the SUT. If you want to configure on a different port, add the following definition !define SLIM_PORT (starting port number) 10. For details on SLIM protocol, check out the below links Port Management SLIM Protocol

Download Patang

You can download the latest version of Patang from Patang @ SourceForge