Giacomo Pati wrote:
Upayavira wrote:
Steve K wrote:
Upayavira --
- Jakarta Cactus (http://jakarta.apache.org/cactus/) -- This takes a similar approach by setting up a mock servlet environment to test your servlets in. However, it seemed way to big and complicated to do what I thought would be very simple. Also, I think there is a lot to be gained by unit testing at the pipeline level as you suggest, rather than treating Cocoon like just another servlet.
I skimmed it too, but it didn't seem to fit.
Have you guys also looked at Anteater http://aft.sf.net?
My personal experience with HTTPUnit is that is somehow inflexible and way too programmatic, not very declarative as Anteater is.
I've looked into Anteater now, and I'm starting to see how I could make a Cocoon unit test tool with it.
...
I copied this email to Jeff Turner (who is part responsible for Anteater). He said that it was, in his opinion, pretty much dead, as it did what it set out to do, but needed more higher level functionality. He now uses jWebUnit, which extends HttpUnit.
So, how does this proposal read:
CocoonUnit extention to HttpUnit and jWebUnit
-----------------------------------------------
My original proposal was to use the CocoonBean to access Cocoon. However, hacking HttpUnit and then jWebUnit to use the new access method would be a real pain. So....
A new CocoonUnit class can be used alongside HttpUnit or jWebUnit. HttpUnit or jWebUnit continue to make their tests using HTTP to a servlet container.
CocoonUnit
------------
public class MyXMLTestCase extends XMLTestCase {
public MyXMLTestCase(String name) {
super(name);
}
public void testForEquality() throws Exception {
CocoonUnit cocoon = new CocoonUnit("http://localhost:8080/unit-manager");
WebConversation webConversation = new WebConversation();
WebRequest request = new GetMethodWebRequest("/samples/hello-world/hello.html");
cocoon.setCollectStageXML(1);
cocoon.setCollectStageXML(2);
cocoon.informServer();
WebResponse response = webConversation.getResponse(request); String generatorXML = cocoon.getPipelineXML(1);
String transformedXML = cocoon.getPipelineXML(2);assertXpathExists("//para[contains(.,'Cocoon')]", generatorXML);
assertXpathNotExists("//para[contains(.,'Active Server Pages')]", generatorXML);
// further tests on the transformedXML } }
In this way, HttpUnit requires no changes - all instructions to the server are made through this CocoonUnit object.
Cocoon Servlet Changes
---------------------
The cocoon servlet is extended with a single extra init parameter "test" which is set to either 'on' or 'off'. (This could equally be in cocoon.xconf).
When the cocoon.informServer() method is called, an HTTP post is sent to the server, encapsulating details of the stages for which XML must be gathered. A couple of extra matchers placed in a pipeline will use an extension of the StreamGenerator to write the contents of this XML into an object in the transient store.
When the webConversation.getResponse() is called, the server, if the test input parameter is set to on, looks to see if this object is present in the persistent store. If it is, it inserts transformers into the pipeline as required to gather XML. This XML is then stored in the transient store, and the normal response is sent back to the user.
When the cocoon.getPipelineXML(1) method is called, an HTTP request is sent to the server, and the server returns the relevant XML out of the transient store.
The only downside of this as I currently see it is that only one person must be testing a site at any one time, as they cannot share their transient store objects.
This is by far the easiest solution to implement that I've come up with so far. It is not the most elegant internally, but from the user's point of view should be relatively easy to understand.
What do you think?
Regards,. Upayavira
