org.testng.internal.TestNGClassFinder 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
Testing framework for Java
package org.testng.internal;
import org.testng.IClass;
import org.testng.IInstanceInfo;
import org.testng.ITestContext;
import org.testng.ITestObjectFactory;
import org.testng.TestNGException;
import org.testng.annotations.IAnnotation;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import org.testng.internal.annotations.AnnotationHelper;
import org.testng.internal.annotations.IAnnotationFinder;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlTest;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This class creates an ITestClass from a test class.
*
* @author Cedric Beust
*/
public class TestNGClassFinder extends BaseClassFinder {
private ITestContext m_testContext = null;
private Map> m_instanceMap = Maps.newHashMap();
public TestNGClassFinder(ClassInfoMap cim,
Map> instanceMap,
XmlTest xmlTest,
IConfiguration configuration,
ITestContext testContext)
{
m_testContext = testContext;
if(null == instanceMap) {
instanceMap= Maps.newHashMap();
}
IAnnotationFinder annotationFinder = configuration.getAnnotationFinder();
ITestObjectFactory objectFactory = configuration.getObjectFactory();
//
// Find all the new classes and their corresponding instances
//
Set> allClasses= cim.getClasses();
//very first pass is to find ObjectFactory, can't create anything else until then
if(objectFactory == null) {
objectFactory = new ObjectFactoryImpl();
outer:
for (Class cls : allClasses) {
try {
if (null != cls) {
for (Method m : cls.getMethods()) {
IAnnotation a = annotationFinder.findAnnotation(m,
org.testng.annotations.IObjectFactoryAnnotation.class);
if (null != a) {
if (!ITestObjectFactory.class.isAssignableFrom(m.getReturnType())) {
throw new TestNGException("Return type of " + m + " is not IObjectFactory");
}
try {
Object instance = cls.newInstance();
if (m.getParameterTypes().length > 0 && m.getParameterTypes()[0].equals(ITestContext.class)) {
objectFactory = (ITestObjectFactory) m.invoke(instance, testContext);
} else {
objectFactory = (ITestObjectFactory) m.invoke(instance);
}
break outer;
}
catch (Exception ex) {
throw new TestNGException("Error creating object factory: " + cls,
ex);
}
}
}
}
} catch (NoClassDefFoundError e) {
Utils.log("[TestNGClassFinder]", 1, "Unable to read methods on class " + cls.getName()
+ " - unable to resolve class reference " + e.getMessage());
for (XmlClass xmlClass : xmlTest.getXmlClasses()) {
if (xmlClass.loadClasses() && xmlClass.getName().equals(cls.getName())) {
throw e;
}
}
}
}
}
for(Class cls : allClasses) {
if((null == cls)) {
ppp("FOUND NULL CLASS IN FOLLOWING ARRAY:");
int i= 0;
for(Class c : allClasses) {
ppp(" " + i + ": " + c);
}
continue;
}
if(isTestNGClass(cls, annotationFinder)) {
List allInstances= instanceMap.get(cls);
Object thisInstance= (null != allInstances) ? allInstances.get(0) : null;
// If annotation class and instances are abstract, skip them
if ((null == thisInstance) && Modifier.isAbstract(cls.getModifiers())) {
Utils.log("", 5, "[WARN] Found an abstract class with no valid instance attached: " + cls);
continue;
}
IClass ic= findOrCreateIClass(m_testContext, cls, cim.getXmlClass(cls), thisInstance,
xmlTest, annotationFinder, objectFactory);
if(null != ic) {
Object[] theseInstances = ic.getInstances(false);
if (theseInstances.length == 0) {
theseInstances = ic.getInstances(true);
}
Object instance= theseInstances[0];
putIClass(cls, ic);
ConstructorOrMethod factoryMethod =
ClassHelper.findDeclaredFactoryMethod(cls, annotationFinder);
if (factoryMethod != null && factoryMethod.getEnabled()) {
FactoryMethod fm = new FactoryMethod( /* cls, */
factoryMethod,
instance,
xmlTest,
annotationFinder,
m_testContext);
ClassInfoMap moreClasses = new ClassInfoMap();
{
// ppp("INVOKING FACTORY " + fm + " " + this.hashCode());
Object[] instances= fm.invoke();
//
// If the factory returned IInstanceInfo, get the class from it,
// otherwise, just call getClass() on the returned instances
//
if (instances.length > 0) {
if (instances[0] != null) {
Class elementClass = instances[0].getClass();
if(IInstanceInfo.class.isAssignableFrom(elementClass)) {
for(Object o : instances) {
IInstanceInfo ii = (IInstanceInfo) o;
addInstance(ii.getInstanceClass(), ii.getInstance());
moreClasses.addClass(ii.getInstanceClass());
}
}
else {
for (int i = 0; i < instances.length; i++) {
Object o = instances[i];
if (o == null) {
throw new TestNGException("The factory " + fm + " returned a null instance" +
"at index " + i);
} else {
addInstance(o.getClass(), o);
if(!classExists(o.getClass())) {
moreClasses.addClass(o.getClass());
}
}
}
}
}
}
}
if(moreClasses.getSize() > 0) {
TestNGClassFinder finder=
new TestNGClassFinder(moreClasses,
m_instanceMap,
xmlTest,
configuration,
m_testContext);
IClass[] moreIClasses= finder.findTestClasses();
for(IClass ic2 : moreIClasses) {
putIClass(ic2.getRealClass(), ic2);
}
} // if moreClasses.size() > 0
}
} // null != ic
} // if not TestNG class
else {
Utils.log("TestNGClassFinder", 3, "SKIPPING CLASS " + cls + " no TestNG annotations found");
}
} // for
//
// Add all the instances we found to their respective IClasses
//
for(Class c : m_instanceMap.keySet()) {
List