org.junit.JUnit4Test Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi-dev Show documentation
Show all versions of xapi-dev Show documentation
Everything needed to run a comprehensive dev environment.
Just type X_ and pick a service from autocomplete;
new dev modules will be added as they are built.
The only dev service not included in the uber jar is xapi-dev-maven,
as it includes all runtime dependencies of maven, adding ~4 seconds to build time,
and 6 megabytes to the final output jar size (without xapi-dev-maven, it's ~1MB).
The newest version!
package org.junit;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.reflect.shared.JsMemberPool;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class JUnit4Test {
private class Lifecycle {
Map after = newMap();
Map afterClass = newMap();
Map before = newMap();
Map beforeClass = newMap();
Map tests = newMap();
@SuppressWarnings({
"rawtypes", "unchecked"
})
public Lifecycle(final Class testClass) {
Class init = testClass;
while (init != null && init != Object.class) {
try {
JsMemberPool.getMembers(init);
for (final Method method : init.getDeclaredMethods()) {
if (method.getAnnotation(Test.class) != null) {
assertPublicZeroArgInstanceMethod(method, Test.class);
if (!tests.containsKey(method.getName())) {
tests.put(method.getName(), method);
}
}
maybeAdd(method);
}
} catch (final NoSuchMethodError ignored) {
debug("Class "+init+" is not enhanced", null);
} catch (final Exception e) {
debug("Error getting declared methods for "+init, e);
}
init = init.getSuperclass();
}
}
public List after() {
return newList(after, true);
}
public List afterClass() {
return newList(afterClass, true);
}
public List before() {
return newList(before, true);
}
public List beforeClass() {
return newList(beforeClass, true);
}
public void maybeAdd(final Method method) {
if (method.getAnnotation(Before.class) != null) {
assertPublicZeroArgInstanceMethod(method, Before.class);
if (!before.containsKey(method.getName())) {
before.put(method.getName(), method);
}
}
if (method.getAnnotation(BeforeClass.class) != null) {
assertPublicZeroArgStaticMethod(method, BeforeClass.class);
if (!beforeClass.containsKey(method.getName())) {
beforeClass.put(method.getName(), method);
}
}
if (method.getAnnotation(After.class) != null) {
assertPublicZeroArgInstanceMethod(method, After.class);
if (!after.containsKey(method.getName())) {
after.put(method.getName(), method);
}
}
if (method.getAnnotation(AfterClass.class) != null) {
assertPublicZeroArgStaticMethod(method, AfterClass.class);
if (!afterClass.containsKey(method.getName())) {
afterClass.put(method.getName(), method);
}
}
}
}
public static Method[] findTests(final Class testClass) throws Throwable {
return new JUnit4Test().findAnnotated(testClass);
}
public static void runTest(final Object inst, final Method m) throws Throwable {
new JUnit4Test().run(inst, m);
}
public static void runTests(final Class testClass) throws Throwable {
new JUnit4Test().runAll(testClass);
}
private Method[] findAnnotated(final Class testClass) {
final Lifecycle lifecycle = new Lifecycle(testClass);
return lifecycle.tests.values().toArray(new Method[0]);
}
protected void assertPublicZeroArgInstanceMethod(final Method method, final Class type) {
assertPublicZeroArgMethod(method, type);
if (Modifier.isStatic(method.getModifiers())) {
throw new AssertionError("@" + type.getSimpleName() + " methods must not be static");
}
}
protected void assertPublicZeroArgMethod(final Method method, final Class type) {
if (!Modifier.isPublic(method.getModifiers())) {
throw new AssertionError("@" + type.getSimpleName() + " methods must be public");
}
if (0 != method.getParameterTypes().length) {
throw new AssertionError("@" + type.getSimpleName() + " methods must be zero-arg");
}
}
protected void assertPublicZeroArgStaticMethod(final Method method, final Class type) {
assertPublicZeroArgMethod(method, type);
if (!Modifier.isStatic(method.getModifiers())) {
throw new AssertionError("@" + type.getSimpleName() + " methods must be static");
}
}
protected void debug(final String string, Throwable e) {
if (GWT.isProdMode()) {
GWT.log(string+" ("+e+")");
} else {
System.out.println(string);
}
while (e != null) {
e.printStackTrace(System.err);
e = e.getCause();
}
}
protected void execute(final Object inst, final Map tests, final List beforeClass,
final List before, final List after, final List afterClass)
throws TestsFailed, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodError {
final Map result = new LinkedHashMap();
try {
for (final Method m : beforeClass) {
m.invoke(null);
}
for (final Entry test : tests.entrySet()) {
result.put(test.getValue(), runTest(inst, test.getValue(), before, after));
}
} finally {
for (final Method m : afterClass) {
m.invoke(null);
}
}
for (final Entry e : result.entrySet()) {
if (e.getValue() != null) {
final TestsFailed failure = new TestsFailed(result);
debug("Tests Failed;\n", failure);
throw new AssertionError(failure.toString());
}
}
}
protected List newList(final Map beforeClass, final boolean reverse) {
List list;
if (reverse) {
list = new LinkedList();
for (final Entry e : beforeClass.entrySet()) {
list.add(0, e.getValue());
}
} else {
list = new ArrayList();
for (final Entry e : beforeClass.entrySet()) {
list.add(e.getValue());
}
}
return list;
}
protected Map newMap() {
return new LinkedHashMap();
}
protected void run(final Object inst, final Method m) throws Throwable {
final Lifecycle lifecycle = new Lifecycle(m.getDeclaringClass());
lifecycle.tests.clear();
lifecycle.tests.put(m.getName(), m);
execute(inst, lifecycle.tests,
lifecycle.beforeClass(), lifecycle.before(), lifecycle.after(), lifecycle.afterClass());
}
protected void runAll(final Class testClass) throws Throwable {
final Lifecycle lifecycle = new Lifecycle(testClass);
if (lifecycle.tests.size() > 0) {
final Object inst = testClass.newInstance();
execute(inst, lifecycle.tests, lifecycle.beforeClass(), lifecycle.before(), lifecycle.after(), lifecycle.afterClass());
}
}
protected Throwable runTest(final Object inst, final Method value, final List before, final List after) {
Test test = null;
try {
test = value.getAnnotation(Test.class);
} catch (final Exception e) {
debug("Error getting @Test annotation",e);
}
final Class expected = test == null ? Test.None.class : test.expected();
// We'll have to figure out timeouts in the actual JUnit jvm
try {
debug("Executing "+value+" on "+inst, null);
for (final Method m : before) {
m.invoke(inst);
}
try {
value.invoke(inst);
} catch (final InvocationTargetException e) {
throw e.getCause();
}
if (expected != Test.None.class) {
return new AssertionError("Method "+value+" was supposed to throw "+expected.getName()
+", but failed to do so");
}
return null;
} catch (final Throwable e) {
return expected.isAssignableFrom(e.getClass()) ? null : e;
} finally {
for (final Method m : after) {
try {
m.invoke(inst);
} catch (final Throwable e) {
debug("Error calling after methods", e);
return e;
}
}
}
}
}