Hi, I'd like to get your comments on the approach to Unit testing I have used in developing my Cocoon components. I think that this approach can be extended to provide unit tests for all Cocoon components - and I'd like to help write these. For example, as Cocoon depends on many other projects it would be great to have a suite of tests that we can automatically run to test new versions of these other components. We could take the guesswork out of testing new versions of Xalan/XSLTC!
Anyhow, attached is a .zip file with an eclipse project containing: 1. My MIDIGenerator and the unit testing TestMIDIGenerator. 2. Some cocoon helper classes I have created to help with unit testing. These classes implement various cocoon environment interfaces. In org.apache.cocoon.test.components there is a CocoonComponentManager, and in org.apache.cocoon.test.environment there is a CocoonRequest, a CocoonSession and a CocoonSourceResolver. These classes exist to make life easier when you are instantiating and setting up components intended for use in Cocoon outside of the Cocoon environment (e.g. in the Eclipse debug environment). For example, the CocoonRequest allows you to pass request parameters as if from the browser. 3. A sample MIDI file (Bach's Prelude No.1 in C, BWV846a nicely sequenced by B.R.Guillaud and available from http://www.classicalarchives.com/bach.html), and the same file converted into XMidi. See http://www.palserv.com/XMidi/ for Peter Loeb's original java code to convert MIDI to XML, now modified to be SAX-based, and a little about XMidi. The Eclipse project dependencies are: $COCOON_LIB/logkit-1.2.jar $COCOON_LIB/excalibur-sourceresolve-2003071 $COCOON_LIB/excalibur-pool-1.2.jar $COCOON_LIB/excalibur-logger-1.0.1.jar $COCOON_LIB/avalon-framework-4.1.4.jar $COCOON_LIB/excalibur-xmlutil-20030520.jar $COCOON_LIB/excalibur-instrument-1.0.jar $COCOON_LIB/excalibur-component-1.1.jar $COCOON_LIB/cocoon-2.1rc2-dev.jar $JUNIT_JAR $JDOM_JAR To give anyone not familiar with JUnit testing some code to look at, listed below is the source for the TestMIDIGenerator. It also illustrates the use of my cocoon helper classes. Actually, I have only one JUnit test in there - that is: assertTrue(generator != null); but there could be many more to provide a stronger indication that the tested code has worked (counting generated nodes, checksumming the XML output string for a known value etc.). Testing provides a nice way to create a set of fixed and repeatable tests that can be executed automatically. Eclipse has built-in support for it. See http://www.junit.org/index.htm for more on JUnit. Note also the use of JDOM for pithy processing of XML (see http://www.jdom.org). =========================================================================== package org.apache.cocoon.test.generation; //import java.io.FileOutputStream; import java.util.Map; import junit.framework.TestCase; import org.apache.avalon.framework.context.DefaultContext; import org.apache.avalon.framework.logger.ConsoleLogger; //import org.apache.avalon.framework.logger.NullLogger; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.environment.ObjectModelHelper; import org.apache.cocoon.environment.Request; import org.apache.cocoon.generation.MIDIGenerator; import org.apache.cocoon.util.HashMap; import org.jdom.input.SAXHandler; import org.jdom.output.XMLOutputter; import org.apache.cocoon.test.environment.CocoonRequest; import org.apache.cocoon.test.environment.CocoonSourceResolver; /** * @author Mark Leicester */ public class TestMIDIGenerator extends TestCase { public void testGenerate() throws Exception { System.out.println("Testing generate()"); MIDIGenerator generator = new MIDIGenerator(); assertTrue(generator != null); // Cocoon 2.1 Set the logger to NULL // NullLogger logger = new NullLogger(); // Cocoon 2.1 Set the logger to the console ConsoleLogger logger = new ConsoleLogger(); generator.enableLogging(logger); // Globally parameterize the generator Parameters globalParameters = new Parameters(); globalParameters.setParameter("verbose", "true"); generator.parameterize(globalParameters); // Create src string: the URI for the midi file String src = "samples/midi/Prelude.mid"; // Locally parameterize the generator Parameters localParameters = new Parameters(); // Create the parameters (simulating a URL) Map map = new HashMap(); CocoonRequest r = new CocoonRequest(); // r.setParameter("name", "value"); map.put(ObjectModelHelper.REQUEST_OBJECT, (Request) r); // Create the resolver needed to locate the schema file CocoonSourceResolver resolver = new CocoonSourceResolver(); resolver.enableLogging(logger); // Set up the root directory for the source resolver // System.getProperty("user.dir") = project home directory DefaultContext context = new DefaultContext(); context.put("context-dir", System.getProperty("user.dir")); resolver.contextualize(context); // Setup the generator generator.setup(resolver, map, src, localParameters); // Create the JDOM sax handler, and make it the content handler SAXHandler sh = new SAXHandler(); generator.setContentHandler(sh); // Perform the generation generator.generate(); // Get the JDOM document and write it to the System.out XMLOutputter xo = new XMLOutputter(); xo.setNewlines(true); xo.output(sh.getDocument(), System.out); // Alternatively, get the JDOM document and write it to a file // FileOutputStream fileStream = new FileOutputStream("output.xmi"); // xo.output(sh.getDocument(), fileStream); // fileStream.close(); return; } } =========================================================================== If you think this is a good approach then please, treat this code as your own! In due course I shall attempt to create a MIDI block (including the test class itself), but I am thinking that the unit testing helper classes would go into the cocoon project itself so that everyone can use them? As is the case with the attached Eclipse project, I always keep the code to be tested separate from the unit tests so that building .jars remains easy. I usually put my java source into /src/java and my test code into /src/test. I hope this approach will help us make cocoon even more robust! Regards, Mark
apache-cocoon.zip
Description: Binary data