summaryrefslogtreecommitdiff
path: root/src/main/java/au/id/zancanaro/PropertyTestRunner.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/au/id/zancanaro/PropertyTestRunner.java')
-rw-r--r--src/main/java/au/id/zancanaro/PropertyTestRunner.java164
1 files changed, 95 insertions, 69 deletions
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<FrameworkMethod> {
-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<FrameworkMethod> getChildren() {
+ List<FrameworkMethod> 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<Object[]> 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<Object[]> 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<Object[]> tree = trees.next();
try {
method.invoke(obj, tree.getValue());
- } catch (Throwable ex) {
- Iterator<RoseTree<Object[]>> children = tree.getChildren();
- if (children.hasNext()) {
- trees = children;
+ } catch (InvocationTargetException ex) {
+ if (!(ex.getTargetException() instanceof AssumptionViolatedException)) {
+ smallest = tree.getValue();
+ Iterator<RoseTree<Object[]>> 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<Object>[] argsGenerators = (Generator<Object>[]) 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)");
}