org.testng.internal.annotations.JDK15TagFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of testng Show documentation
Show all versions of testng Show documentation
A testing framework for the JVM
package org.testng.internal.annotations;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.testng.TestNGException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Factory;
import org.testng.annotations.IAnnotation;
import org.testng.annotations.IDataProviderAnnotation;
import org.testng.annotations.IFactoryAnnotation;
import org.testng.annotations.IListenersAnnotation;
import org.testng.annotations.IObjectFactoryAnnotation;
import org.testng.annotations.IParametersAnnotation;
import org.testng.annotations.ITestAnnotation;
import org.testng.annotations.Listeners;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import org.testng.collections.Lists;
import org.testng.internal.Utils;
import org.testng.internal.collections.Ints;
import org.testng.log4testng.Logger;
/**
* This class creates implementations of IAnnotations based on the JDK5 annotation that was found on
* the Java element.
*/
public class JDK15TagFactory {
public A createTag(
Class cls, Method method, Annotation a, Class annotationClass) {
IAnnotation result = null;
if (a != null) {
if (annotationClass == IDataProviderAnnotation.class) {
result = createDataProviderTag(method, a);
} else if (annotationClass == IFactoryAnnotation.class) {
result = createFactoryTag(cls, a);
} else if (annotationClass == IParametersAnnotation.class) {
result = createParametersTag(a);
} else if (annotationClass == IObjectFactoryAnnotation.class) {
result = createObjectFactoryTag();
} else if (annotationClass == ITestAnnotation.class) {
result = createTestTag(cls, a);
} else if (annotationClass == IListenersAnnotation.class) {
result = createListenersTag(a);
} else if (annotationClass == IBeforeSuite.class
|| annotationClass == IAfterSuite.class
|| annotationClass == IBeforeTest.class
|| annotationClass == IAfterTest.class
|| annotationClass == IBeforeGroups.class
|| annotationClass == IAfterGroups.class
|| annotationClass == IBeforeClass.class
|| annotationClass == IAfterClass.class
|| annotationClass == IBeforeMethod.class
|| annotationClass == IAfterMethod.class) {
result = maybeCreateNewConfigurationTag(a, annotationClass);
} else {
throw new TestNGException("Unknown annotation requested:" + annotationClass);
}
}
//noinspection unchecked
return (A) result;
}
private IAnnotation maybeCreateNewConfigurationTag(Annotation a, Class annotationClass) {
IAnnotation result = null;
if (annotationClass == IBeforeSuite.class) {
BeforeSuite bs = (BeforeSuite) a;
result =
createConfigurationTag(
true,
false,
false,
false,
new String[0],
new String[0],
false,
false,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IAfterSuite.class) {
AfterSuite bs = (AfterSuite) a;
result =
createConfigurationTag(
false,
true,
false,
false,
new String[0],
new String[0],
false,
false,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IBeforeTest.class) {
BeforeTest bs = (BeforeTest) a;
result =
createConfigurationTag(
false,
false,
true,
false,
new String[0],
new String[0],
false,
false,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IAfterTest.class) {
AfterTest bs = (AfterTest) a;
result =
createConfigurationTag(
false,
false,
false,
true,
new String[0],
new String[0],
false,
false,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IBeforeGroups.class) {
BeforeGroups bs = (BeforeGroups) a;
final String[] groups = bs.value().length > 0 ? bs.value() : bs.groups();
result =
createConfigurationTag(
false,
false,
false,
false,
groups,
new String[0],
false,
false,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IAfterGroups.class) {
AfterGroups bs = (AfterGroups) a;
final String[] groups = bs.value().length > 0 ? bs.value() : bs.groups();
result =
createConfigurationTag(
false,
false,
false,
false,
new String[0],
groups,
false,
false,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IBeforeClass.class) {
BeforeClass bs = (BeforeClass) a;
result =
createConfigurationTag(
false,
false,
false,
false,
new String[0],
new String[0],
true,
false,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IAfterClass.class) {
AfterClass bs = (AfterClass) a;
result =
createConfigurationTag(
false,
false,
false,
false,
new String[0],
new String[0],
false,
true,
false,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
false,
bs.timeOut(),
new String[0]);
} else if (annotationClass == IBeforeMethod.class) {
BeforeMethod bs = (BeforeMethod) a;
result =
createConfigurationTag(
false,
false,
false,
false,
new String[0],
new String[0],
false,
false,
true,
false,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
bs.firstTimeOnly(),
false,
bs.timeOut(),
bs.onlyForGroups());
} else if (annotationClass == IAfterMethod.class) {
AfterMethod bs = (AfterMethod) a;
result =
createConfigurationTag(
false,
false,
false,
false,
new String[0],
new String[0],
false,
false,
false,
true,
bs.alwaysRun(),
bs.dependsOnGroups(),
bs.dependsOnMethods(),
bs.description(),
bs.enabled(),
bs.groups(),
bs.inheritGroups(),
false,
bs.lastTimeOnly(),
bs.timeOut(),
bs.onlyForGroups());
}
return result;
}
private IAnnotation createConfigurationTag(
boolean beforeSuite,
boolean afterSuite,
boolean beforeTest,
boolean afterTest,
String[] beforeGroups,
String[] afterGroups,
boolean beforeClass,
boolean afterClass,
boolean beforeMethod,
boolean afterMethod,
boolean alwaysRun,
String[] dependsOnGroups,
String[] dependsOnMethods,
String description,
boolean enabled,
String[] groups,
boolean inheritGroups,
boolean firstTimeOnly,
boolean lastTimeOnly,
long timeOut,
String[] groupFilters) {
ConfigurationAnnotation result = new ConfigurationAnnotation();
result.setFakeConfiguration(true);
result.setBeforeSuite(beforeSuite);
result.setAfterSuite(afterSuite);
result.setBeforeTest(beforeTest);
result.setAfterTest(afterTest);
result.setBeforeTestClass(beforeClass);
result.setAfterTestClass(afterClass);
result.setBeforeGroups(beforeGroups);
result.setAfterGroups(afterGroups);
result.setBeforeTestMethod(beforeMethod);
result.setAfterTestMethod(afterMethod);
result.setAlwaysRun(alwaysRun);
result.setDependsOnGroups(dependsOnGroups);
result.setDependsOnMethods(dependsOnMethods);
result.setDescription(description);
result.setEnabled(enabled);
result.setGroups(groups);
result.setInheritGroups(inheritGroups);
result.setGroupFilters(groupFilters);
result.setFirstTimeOnly(firstTimeOnly);
result.setLastTimeOnly(lastTimeOnly);
result.setTimeOut(timeOut);
return result;
}
private IAnnotation createDataProviderTag(Method method, Annotation a) {
DataProviderAnnotation result = new DataProviderAnnotation();
DataProvider c = (DataProvider) a;
if (c.name().isEmpty()) {
result.setName(method.getName());
} else {
result.setName(c.name());
}
result.setParallel(c.parallel());
result.setIndices(Ints.asList(c.indices()));
return result;
}
private IAnnotation createFactoryTag(Class cls, Annotation a) {
FactoryAnnotation result = new FactoryAnnotation();
Factory c = (Factory) a;
Class dpc =
findInherited(
c.dataProviderClass(), cls, Factory.class, "dataProviderClass", DEFAULT_CLASS);
result.setDataProvider(c.dataProvider());
result.setDataProviderClass(dpc == null || dpc == Object.class ? cls : dpc);
result.setEnabled(c.enabled());
result.setIndices(Ints.asList(c.indices()));
return result;
}
private IAnnotation createObjectFactoryTag() {
return new ObjectFactoryAnnotation();
}
private IAnnotation createParametersTag(Annotation a) {
ParametersAnnotation result = new ParametersAnnotation();
Parameters c = (Parameters) a;
result.setValue(c.value());
return result;
}
private IAnnotation createListenersTag(Annotation a) {
ListenersAnnotation result = new ListenersAnnotation();
Listeners l = (Listeners) a;
result.setValue(l.value());
return result;
}
private IAnnotation createTestTag(Class cls, Annotation a) {
TestAnnotation result = new TestAnnotation();
Test test = (Test) a;
result.setEnabled(test.enabled());
result.setGroups(join(test.groups(), findInheritedStringArray(cls, "groups")));
result.setDependsOnGroups(
join(test.dependsOnGroups(), findInheritedStringArray(cls, "dependsOnGroups")));
result.setDependsOnMethods(
join(
test.dependsOnMethods(),
findInheritedStringArray(cls, "dependsOnMethods")));
result.setTimeOut(test.timeOut());
result.setInvocationTimeOut(test.invocationTimeOut());
result.setInvocationCount(test.invocationCount());
result.setThreadPoolSize(test.threadPoolSize());
result.setSuccessPercentage(test.successPercentage());
result.setDataProvider(test.dataProvider());
result.setDataProviderClass(
findInherited(
test.dataProviderClass(), cls, Test.class, "dataProviderClass", DEFAULT_CLASS));
result.setAlwaysRun(test.alwaysRun());
result.setDescription(
findInherited(test.description(), cls, Test.class, "description", DEFAULT_STRING));
result.setExpectedExceptions(test.expectedExceptions());
result.setExpectedExceptionsMessageRegExp(test.expectedExceptionsMessageRegExp());
result.setSuiteName(test.suiteName());
result.setTestName(test.testName());
result.setSingleThreaded(test.singleThreaded());
result.setRetryAnalyzer(test.retryAnalyzer());
result.setSkipFailedInvocations(test.skipFailedInvocations());
result.setIgnoreMissingDependencies(test.ignoreMissingDependencies());
result.setPriority(test.priority());
result.setAttributes(test.attributes());
return result;
}
private String[] join(String[] strings, String[] strings2) {
List result = Lists.newArrayList(strings);
Set seen = new HashSet<>(Lists.newArrayList(strings));
for (String s : strings2) {
if (!seen.contains(s)) {
result.add(s);
}
}
return result.toArray(new String[0]);
}
/**
* This interface is used to calculate the default value for various annotation return types. This
* is used when looking for an annotation in a hierarchy. We can't use null as a default since
* annotation don't allow nulls, so each type has a different way of defining its own default.
*/
interface Default {
boolean isDefault(T t);
}
private static final Default> DEFAULT_CLASS = c -> c == Object.class;
private static final Default DEFAULT_STRING = Utils::isStringEmpty;
/**
* Find the value of an annotation, starting with the annotation found on the method, then the
* class and then parent classes until we either find a non-default value or we reach the top of
* the hierarchy (Object).
*/
@SuppressWarnings("unchecked")
private T findInherited(
T methodValue,
Class cls,
Class annotationClass,
String methodName,
Default def) {
// Look on the method first and return right away if the annotation is there
if (!def.isDefault(methodValue)) {
return methodValue;
}
// Not found, look on the class and then up the hierarchy
while (cls != null && cls != Object.class) {
Annotation annotation = AnnotationHelper.getAnnotationFromClass(cls, annotationClass);
if (annotation != null) {
T result = (T) invokeMethod(annotation, methodName);
if (!def.isDefault(result)) {
return result;
}
}
cls = cls.getSuperclass();
}
return null;
}
/**
* Find the value of a String[] annotation. The difference with the findInherited method above is
* that TestNG aggregates String[] values across hierarchies. For example, of the method
* annotation has { "a", "b" } and the class has { "c" }, the returned value will be { "a", "b",
* "c" }.
*/
private String[] findInheritedStringArray(Class cls, String methodName) {
if (null == cls) {
return new String[0];
}
List result = Lists.newArrayList();
while (cls != null && cls != Object.class) {
Annotation annotation = AnnotationHelper.getAnnotationFromClass(cls, Test.class);
if (annotation != null) {
String[] g = (String[]) invokeMethod(annotation, methodName);
result.addAll(Arrays.asList(g));
}
cls = cls.getSuperclass();
}
return result.toArray(new String[0]);
}
private Object invokeMethod(Annotation test, String methodName) {
Object result = null;
try {
// Note: we should cache methods already looked up
Method m = test.getClass().getMethod(methodName);
result = m.invoke(test);
} catch (Exception e) {
Logger.getLogger(JDK15TagFactory.class).error(e.getMessage(), e);
}
return result;
}
}