From c25450f6288748782ad60cc7c4b8e0e0bdc52c1c Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Sun, 31 May 2015 13:53:08 +1000 Subject: Better code, based off ParentRunner among other things --- .../java/au/id/zancanaro/PropertyTestRunner.java | 164 ++++++++++++--------- 1 file changed, 95 insertions(+), 69 deletions(-) (limited to 'src/main/java/au/id/zancanaro/PropertyTestRunner.java') diff --git a/src/main/java/au/id/zancanaro/PropertyTestRunner.java b/src/main/java/au/id/zancanaro/PropertyTestRunner.java index fc90b8e..8df9b2a 100644 --- a/src/main/java/au/id/zancanaro/PropertyTestRunner.java +++ b/src/main/java/au/id/zancanaro/PropertyTestRunner.java @@ -2,97 +2,115 @@ package au.id.zancanaro; import au.id.zancanaro.annotations.Property; import au.id.zancanaro.annotations.Seed; -import junit.framework.AssertionFailedError; import org.junit.AssumptionViolatedException; +import org.junit.Ignore; import org.junit.runner.Description; -import org.junit.runner.Runner; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; +import org.junit.runners.ParentRunner; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.InitializationError; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Random; +import java.util.*; + +public class PropertyTestRunner extends ParentRunner { -public class PropertyTestRunner extends Runner { private final Class classUnderTest; - public PropertyTestRunner(Class classUnderTest) { + public PropertyTestRunner(Class classUnderTest) throws InitializationError{ + super(classUnderTest); this.classUnderTest = classUnderTest; } @Override - public Description getDescription() { - return Description.createSuiteDescription(classUnderTest); + protected boolean isIgnored(FrameworkMethod child) { + return child.getAnnotation(Ignore.class) != null; } - private long getSeed(Method method) { - Seed seed = method.getAnnotation(Seed.class); - if (seed == null) { - return System.currentTimeMillis(); - } else { - return seed.value(); + @Override + protected List getChildren() { + List result = new ArrayList<>(); + for (Method method : classUnderTest.getDeclaredMethods()) { + if (method.isAnnotationPresent(Property.class) + && !method.isAnnotationPresent(Ignore.class)) { + result.add(new FrameworkMethod(method)); + } } + return result; } @Override - public void run(RunNotifier notifier) { - Method[] methods = classUnderTest.getMethods(); - for (Method method : methods) { - Property details = method.getAnnotation(Property.class); - if (details != null) { - Description description = Description.createTestDescription(classUnderTest, method.getName()); - boolean failed = false; - int assumptionsFailed = 0; - - long seed = getSeed(method); - Random random = new Random(seed); - int numRuns = details.runs(); - for (int i = 0; i < numRuns && !failed; ++i) { - int size = details.size(); - notifier.fireTestStarted(description); - Object obj; - try { - obj = classUnderTest.getConstructor().newInstance(); - } catch (Throwable ex) { // HACKY - System.out.println(ex); - return; - } - RoseTree generated = generateArgs(random, size, - method.getGenericParameterTypes(), - method.getParameterAnnotations()); - try { - method.invoke(obj, generated.getValue()); - } catch (InvocationTargetException ex) { - if (ex.getTargetException() instanceof AssumptionViolatedException) { - assumptionsFailed++; + protected Description describeChild(FrameworkMethod child) { + return Description.createTestDescription(classUnderTest, child.getName()); + } + + @Override + protected void runChild(FrameworkMethod child, RunNotifier notifier) { + try { + Property details = child.getAnnotation(Property.class); + Description description = Description.createTestDescription(classUnderTest, child.getName()); + boolean failed = false; + int assumptionsFailed = 0; + + long seed = getSeed(child.getMethod()); + Random random = new Random(seed); + int numRuns = details.runs(); + for (int i = 0; i < numRuns && !failed; ++i) { + int size = details.size(); + notifier.fireTestStarted(description); + Object obj; + try { + obj = classUnderTest.getConstructor().newInstance(); + } catch (Throwable ex) { // HACKY + System.out.println(ex); + return; + } + RoseTree generated = generateArgs(random, size, + child.getMethod().getGenericParameterTypes(), + child.getMethod().getParameterAnnotations()); + try { + child.getMethod().invoke(obj, generated.getValue()); + } catch (InvocationTargetException ex) { + if (ex.getTargetException() instanceof AssumptionViolatedException) { + assumptionsFailed++; + i--; + } else { + System.out.println("Test failed with seed: " + seed); + System.out.println("Failing arguments: " + Arrays.asList(generated.getValue())); + Object[] shrinkResult = shrink(child.getMethod(), obj, generated); + if (shrinkResult == null) { + System.out.println("Arguments could not be shrunk any further"); } else { - notifier.fireTestFailure(new Failure(description, ex.getTargetException())); - System.out.println("Test failed with seed: " + seed); - System.out.println("Failing arguments: " + Arrays.asList(generated.getValue())); - Object[] shrinkResult = shrink(method, obj, generated); - if (shrinkResult == null) { - System.out.println("Arguments could not be shrunk any further"); - } else { - System.out.println("Arguments shrunk to: " + Arrays.asList(shrinkResult)); - } - failed = true; + System.out.println("Arguments shrunk to: " + Arrays.asList(shrinkResult)); } - } catch (IllegalAccessException ex) { - notifier.fireTestFailure(new Failure(description, ex)); + notifier.fireTestFailure(new Failure(description, ex.getTargetException())); failed = true; } + } catch (IllegalAccessException ex) { + notifier.fireTestFailure(new Failure(description, ex)); + failed = true; } + } - if (assumptionsFailed > 0) { - System.out.println("Failed " + assumptionsFailed + " assumptions"); - } - notifier.fireTestFinished(description); + if (assumptionsFailed > 0) { + System.out.println("Failed " + assumptionsFailed + " assumptions"); } + notifier.fireTestFinished(description); + } catch (Throwable ex) { + ex.printStackTrace(); + } + } + + private long getSeed(Method method) { + Seed seed = method.getAnnotation(Seed.class); + if (seed == null) { + return System.currentTimeMillis(); + } else { + return seed.value(); } } @@ -103,12 +121,18 @@ public class PropertyTestRunner extends Runner { RoseTree tree = trees.next(); try { method.invoke(obj, tree.getValue()); - } catch (Throwable ex) { - Iterator> children = tree.getChildren(); - if (children.hasNext()) { - trees = children; + } catch (InvocationTargetException ex) { + if (!(ex.getTargetException() instanceof AssumptionViolatedException)) { + smallest = tree.getValue(); + Iterator> children = tree.getChildren(); + if (children.hasNext()) { + trees = children; + } else { + break; + } } - smallest = tree.getValue(); + } catch (IllegalAccessException ex) { + System.out.println(ex); } } return smallest; @@ -135,14 +159,16 @@ public class PropertyTestRunner extends Runner { generators[i] = getGeneratorFromType(types[i]); // } } - return Generators.arrayGenerator(generators).generate(random, size); + @SuppressWarnings("unchecked") + Generator[] argsGenerators = (Generator[]) generators; + return Generator.tuple(argsGenerators).generate(random, size); } private Generator getGeneratorFromType(Type type) { if (type instanceof Class) { Class clazz = (Class) type; if (clazz.isPrimitive() && clazz == Integer.TYPE) { - return Generators.integerGenerator(); + return Generators.integer(); } else { throw new RuntimeException("Unknown type for generator (atm only int is supported)"); } -- cgit v1.2.3