diff --git a/src/java/com/samskivert/velocity/VelocityTestCase.java b/src/java/com/samskivert/velocity/VelocityTestCase.java index 5434571a..93d65ae0 100644 --- a/src/java/com/samskivert/velocity/VelocityTestCase.java +++ b/src/java/com/samskivert/velocity/VelocityTestCase.java @@ -21,15 +21,18 @@ package com.samskivert.velocity; import java.io.InputStream; +import java.io.PrintWriter; import java.io.StringWriter; -import junit.framework.Test; import junit.framework.TestCase; import org.apache.commons.io.IOUtils; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeServices; +import org.apache.velocity.runtime.log.LogChute; +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; /** * An abstract base class for easily testing Velocity templates. @@ -41,16 +44,19 @@ public abstract class VelocityTestCase extends TestCase super(name); } - protected VelocityTestCase () - { - this(VelocityTestCase.class.getName()); - } - @Override // from TestCase protected void setUp () { try { - _engine = VelocityUtil.createEngine(); + _engine = new VelocityEngine(); + _engine.setProperty(VelocityEngine.VM_LIBRARY, ""); + _engine.setProperty(VelocityEngine.RESOURCE_LOADER, "classpath"); + _engine.setProperty( + "classpath." + VelocityEngine.RESOURCE_LOADER + ".class", + ClasspathResourceLoader.class.getName()); + _engine.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM, _logger); + _engine.init(); + } catch (Exception e) { fail("Velocity initialization failed " + e); } @@ -59,16 +65,42 @@ public abstract class VelocityTestCase extends TestCase @Override // from TestCase protected void runTest () { + // first simply evaluate all of the templates for (String template : getTemplates()) { try { - runTest(template); + evaluateTemplate(template); + } catch (Exception e) { + fail("Failed to process " + template + ": " + e); + } + } + + // then try to actually merge them with a context + for (String template : getTemplates()) { + try { + mergeTemplate(template); } catch (Exception e) { fail("Failed to process " + template + ": " + e); } } } - protected void runTest (String template) + protected void evaluateTemplate (String template) + throws Exception + { + InputStream tempin = + getClass().getClassLoader().getResourceAsStream(template); + if (tempin == null) { + fail("Missing template '" + template + "'."); + } + + // parse the template + if (!_engine.evaluate(new VelocityContext(), new StringWriter(), + template, tempin)) { + fail("Template parsing failed '" + template + "'."); + } + } + + protected void mergeTemplate (String template) throws Exception { // first load our golden output @@ -76,21 +108,28 @@ public abstract class VelocityTestCase extends TestCase InputStream goldin = getClass().getClassLoader().getResourceAsStream(goldpath); if (goldin == null) { - fail("Missing golden file for " + template + - " [path=" + goldpath + "]."); + // if there is no golden template, we don't test this file + return; } String goldtext = IOUtils.toString(goldin); + // clear out any previous logging output + _logbuf.getBuffer().setLength(0); + // now generate the test output VelocityContext context = new VelocityContext(); populateContext(template, context); StringWriter writer = new StringWriter(); _engine.mergeTemplate(template, context, writer); - // and compare the two - assertEquals("Template output incorrect [template=" + template + - ", golden=" + goldpath + "].", - goldtext, writer.toString()); + // now compare the two + String output = "Template output incorrect [template=" + template + + ", golden=" + goldpath + "]."; + String logout = _logbuf.toString(); + if (logout.length() > 0) { + output = output + "\n" + logout; + } + assertEquals(output, goldtext, writer.toString()); } /** @@ -118,5 +157,36 @@ public abstract class VelocityTestCase extends TestCase return template + ".test"; } + /** Accumulates logging to a buffer for later reporting. */ + protected LogChute _logger = new LogChute() { + public void init (RuntimeServices rs) throws Exception { + // nothing doing + } + public void log (int level, String message) { + switch (level) { + case ERROR_ID: + case WARN_ID: + _logout.println(message); + break; + default: + case INFO_ID: + case DEBUG_ID: + // velocity insists on sending info and debug messages even + // though isLevelEnabled() returns false + break; + } + } + public void log (int level, String message, Throwable t) { + log(level, message); + t.printStackTrace(_logout); + } + public boolean isLevelEnabled (int level) { + return (level == WARN_ID || level == ERROR_ID); + } + }; + protected VelocityEngine _engine; + + protected StringWriter _logbuf = new StringWriter(); + protected PrintWriter _logout = new PrintWriter(_logbuf); }