From a45d9dde4bc797b71f8a6a09c0a16ea98fd29500 Mon Sep 17 00:00:00 2001 From: Adam Gent Date: Fri, 17 Nov 2023 17:38:49 -0500 Subject: [PATCH] Fix spec test runner --- .../mustache/specs/SpecFrameworkMethod.java | 33 ------ .../samskivert/mustache/specs/SpecRunner.java | 95 --------------- .../samskivert/mustache/specs/SpecTest.java | 112 +++++++++++++++--- 3 files changed, 97 insertions(+), 143 deletions(-) delete mode 100644 src/test/java/com/samskivert/mustache/specs/SpecFrameworkMethod.java delete mode 100644 src/test/java/com/samskivert/mustache/specs/SpecRunner.java diff --git a/src/test/java/com/samskivert/mustache/specs/SpecFrameworkMethod.java b/src/test/java/com/samskivert/mustache/specs/SpecFrameworkMethod.java deleted file mode 100644 index 83c9d19..0000000 --- a/src/test/java/com/samskivert/mustache/specs/SpecFrameworkMethod.java +++ /dev/null @@ -1,33 +0,0 @@ -// -// JMustache - A Java implementation of the Mustache templating language -// http://github.com/samskivert/jmustache/blob/master/LICENSE - -package com.samskivert.mustache.specs; - -import java.lang.reflect.Method; -import org.junit.runners.model.FrameworkMethod; - -/** - * @author Yoryos Valotasios - */ -public class SpecFrameworkMethod extends FrameworkMethod -{ - private final String group; - private final Spec spec; - - public SpecFrameworkMethod (Method method, String group, Spec spec) { - super(method); - this.group = group; - this.spec = spec; - } - - @Override - public Object invokeExplosively (Object target, Object... params) throws Throwable { - return super.invokeExplosively(target, spec); - } - - @Override - public String getName () { - return group + ": " + spec.getName(); - } -} diff --git a/src/test/java/com/samskivert/mustache/specs/SpecRunner.java b/src/test/java/com/samskivert/mustache/specs/SpecRunner.java deleted file mode 100644 index b0315f3..0000000 --- a/src/test/java/com/samskivert/mustache/specs/SpecRunner.java +++ /dev/null @@ -1,95 +0,0 @@ -// -// JMustache - A Java implementation of the Mustache templating language -// http://github.com/samskivert/jmustache/blob/master/LICENSE - -package com.samskivert.mustache.specs; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.junit.After; -import org.junit.Before; -import org.junit.runners.BlockJUnit4ClassRunner; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.InitializationError; - -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.error.YAMLException; - -/** - * @author Yoryos Valotasios - */ -public class SpecRunner extends BlockJUnit4ClassRunner -{ - private final Yaml yaml = new Yaml(); - private final List tests; - - public SpecRunner (Class klass) throws InitializationError { - super(klass); - if (klass != SpecTest.class) throw new IllegalArgumentException( - SpecRunner.class.getSimpleName() + " should only be used with classes of type " + - SpecTest.class.getName()); - this.tests = computeTests(); - } - - @Override - protected List computeTestMethods () { - return tests; - } - - @Override - protected void validateInstanceMethods (List errors) { - validatePublicVoidNoArgMethods(After.class, false, errors); - validatePublicVoidNoArgMethods(Before.class, false, errors); - validateTestMethods(errors); - } - - private List computeTests () throws InitializationError { - String[] groups = new String[] { - "comments", - "delimiters", - "interpolation", - "inverted", - "sections", - "partials" - }; - Method m = getTestClassMethod("test", Spec.class); - List tests = new ArrayList(); - for (String name : groups) { - for (Map test: getTestsForGroup(name)) { - tests.add(new SpecFrameworkMethod(m, name, new Spec(test))); - } - } - return tests; - } - - private Method getTestClassMethod (String name, Class... paramTypes) - throws InitializationError { - try { - return getTestClass().getJavaClass().getDeclaredMethod(name, paramTypes); - } catch (NoSuchMethodException ex) { - throw new InitializationError("Could not find " + name + " " + - getTestClass().getJavaClass()); - } catch (SecurityException ex) { - throw new InitializationError("Could not find " + name + " " + - getTestClass().getJavaClass()); - } - } - - private Iterable> getTestsForGroup (String name) { - String ymlPath = "/specs/specs/" + name + ".yml"; - try { - @SuppressWarnings("unchecked") Map map = - (Map)yaml.load(getClass().getResourceAsStream(ymlPath)); - @SuppressWarnings("unchecked") List> tests = - (List>)map.get("tests"); - return tests; - } catch (YAMLException err) { - System.err.println("*** Error loading: " + ymlPath); - System.err.println("*** You probably need to 'git submodule update'."); - throw err; - } - } -} diff --git a/src/test/java/com/samskivert/mustache/specs/SpecTest.java b/src/test/java/com/samskivert/mustache/specs/SpecTest.java index a505acb..9a64331 100644 --- a/src/test/java/com/samskivert/mustache/specs/SpecTest.java +++ b/src/test/java/com/samskivert/mustache/specs/SpecTest.java @@ -1,22 +1,37 @@ -// -// JMustache - A Java implementation of the Mustache templating language -// http://github.com/samskivert/jmustache/blob/master/LICENSE - package com.samskivert.mustache.specs; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; + import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.YAMLException; import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Template; -/** - * @author Yoryos Valotasios - */ -@RunWith(SpecRunner.class) -public class SpecTest -{ +@RunWith(Parameterized.class) +public class SpecTest { + + private static final Yaml yaml = new Yaml(); + + private final Spec spec; + private final String name; + + public SpecTest(Spec spec, String name) { + super(); + this.spec = spec; + this.name = name; + } + private static Mustache.Compiler compiler; private static SpecAwareTemplateLoader loader; @@ -25,8 +40,10 @@ public static void setUp () { loader = new SpecAwareTemplateLoader(); compiler = Mustache.compiler().defaultValue("").withLoader(loader); } - - public void test (Spec spec) { + + @Test + public void test() throws Exception { + //System.out.println("Testing: " + name); loader.setSpec(spec); String tmpl = spec.getTemplate(); String desc = String.format("Template: '''%s'''\nData: '%s'\n", @@ -34,17 +51,82 @@ public void test (Spec spec) { try { Template t = compiler.compile(spec.getTemplate()); String out = t.execute(spec.getData()); - Assert.assertEquals(desc, uncrlf(spec.getExpectedOutput()), uncrlf(out)); + if (! Objects.equals(uncrlf(spec.getExpectedOutput()), uncrlf(out))) { + System.out.println(""); + System.out.println("----------------------------------------"); + System.out.println(""); + System.out.println("Failed: " + name); + System.out.println(spec); + System.out.println("Expected : \"" + showWhitespace(spec.getExpectedOutput()) + "\""); + System.out.println("Result : \"" + showWhitespace(out) + "\""); + System.out.println("----------------------------------------"); + System.out.println(""); + } + Assert.assertEquals(desc, showWhitespace(spec.getExpectedOutput()), showWhitespace(out)); } catch (Exception e) { + // the specs tests assume that the engine silently ignores invalid delimiter // specifications, but we throw an exception (and rightfully so IMO; this is not a // place where silent failure is helpful), so just ignore those test failures - if (!e.getMessage().contains("Invalid delimiter")) Assert.fail( + if (!e.getMessage().contains("Invalid delimiter")) { + Assert.fail( desc + "\nExpected: " + uncrlf(spec.getExpectedOutput()) + "\nError: " + e); + } } } + + private static String showWhitespace(String s) { + s = s.replace("\r\n", "\u240D"); + s = s.replace('\t', '\u21E5'); + s = s.replace("\n", "\u21B5\n"); + s = s.replace("\u240D", "\u240D\n"); + return s; + } + private static String uncrlf (String text) { return (text == null) ? null : text.replace("\r", "\\r").replace("\n", "\\n"); } -} + + @Parameters(name = "{1}") + public static Collection data() { + String[] groups = new String[] { // + "comments", // + "delimiters", // + "interpolation", // + "inverted", // + "sections", // + "partials" + }; + List tuples = new ArrayList<>(); + int i = 0; + for (String g : groups) { + Iterable specs = getTestsForGroup(g); + for (Spec s : specs) { + Object[] tuple = new Object[] {s, g + "-" + s.getName() + "-" + i++}; + tuples.add(tuple); + } + } + return tuples; + } + + private static Iterable getTestsForGroup(String name) { + String ymlPath = "/specs/specs/" + name + ".yml"; + try { + @SuppressWarnings("unchecked") + Map map = (Map) yaml.load(SpecTest.class.getResourceAsStream(ymlPath)); + @SuppressWarnings("unchecked") + List> tests = (List>) map.get("tests"); + List specs = new ArrayList<>(); + for (Map t : tests) { + specs.add(new Spec(t)); + } + return specs; + } catch (YAMLException err) { + System.err.println("*** Error loading: " + ymlPath); + System.err.println("*** You probably need to 'git submodule update'."); + throw err; + } + } + +} \ No newline at end of file