1 package org.testng.junit; 2 3 import org.testng.ITestMethodFinder; 4 import org.testng.ITestNGMethod; 5 import org.testng.collections.Lists; 6 import org.testng.internal.TestNGMethod; 7 import org.testng.internal.annotations.IAnnotationFinder; 8 import org.testng.xml.XmlTest; 9 10 import java.lang.reflect.Constructor; 11 import java.lang.reflect.InvocationTargetException; 12 import java.lang.reflect.Method; 13 import java.util.HashSet; 14 import java.util.List; 15 import java.util.Set; 16 17 18 /** 19 * This class locates all test and configuration methods according to JUnit. 20 * It is used to change the strategy used by TestRunner to locate its test 21 * methods. 22 * 23 * @author Cedric Beust, May 3, 2004 24 * 25 */ 26 public class JUnitMethodFinder implements ITestMethodFinder { 27 private String m_testName = null; 28 private IAnnotationFinder m_annotationFinder = null; 29 30 public JUnitMethodFinder(String testName, IAnnotationFinder finder) { 31 m_testName = testName; 32 m_annotationFinder = finder; 33 } 34 35 private Constructor findConstructor(Class cls, Class[] parameters) { 36 Constructor result = null; 37 38 try { 39 result = cls.getConstructor(parameters); 40 } 41 catch (SecurityException | NoSuchMethodException ex) { 42 // ignore 43 } 44 45 return result; 46 } 47 48 @Override 49 public ITestNGMethod[] getTestMethods(Class cls, XmlTest xmlTest) { 50 ITestNGMethod[] result = 51 privateFindTestMethods(new INameFilter() { 52 @Override 53 public boolean accept(Method method) { 54 return method.getName().startsWith("test") && 55 method.getParameterTypes().length == 0; 56 } 57 }, cls); 58 59 // ppp("====="); 60 // ppp("FIND TEST METHOD RETURNING "); 61 // for (ITestMethod m : result) { 62 // ppp(" " + m); 63 // } 64 // ppp("====="); 65 return result; 66 } 67 68 private ITestNGMethod[] privateFindTestMethods(INameFilter filter, Class cls) { 69 List<ITestNGMethod> vResult = Lists.newArrayList(); 70 71 // We do not want to walk up the class hierarchy and accept the 72 // same method twice (e.g. setUp) which would lead to double-invocation. 73 // All relevant JUnit methods are parameter-less so we store accepted 74 // method names in a Set to filter out duplicates. 75 Set<String> acceptedMethodNames = new HashSet<>(); 76 77 // 78 // Collect all methods that start with test 79 // 80 Class current = cls; 81 while(!(current == Object.class)) { 82 Method[] allMethods = current.getDeclaredMethods(); 83 for(Method allMethod : allMethods) { 84 ITestNGMethod m = new TestNGMethod(/* allMethods[i].getDeclaringClass(), */ allMethod, 85 m_annotationFinder, null, 86 null); /* @@@ */ 87 Method method = m.getMethod(); 88 String methodName = method.getName(); 89 if(filter.accept(method) && !acceptedMethodNames.contains(methodName)) { 90 // if (m.getName().startsWith("test")) { 91 // ppp("Found JUnit test method: " + tm); 92 vResult.add(m); 93 acceptedMethodNames.add(methodName); 94 } 95 } 96 current = current.getSuperclass(); 97 } 98 99 return vResult.toArray(new ITestNGMethod[vResult.size()]); 100 } 101 102 private static void ppp(String s) { 103 System.out.println("[JUnitMethodFinder] " + s); 104 } 105 106 private Object instantiate(Class cls) { 107 Object result = null; 108 109 Constructor ctor = findConstructor(cls, new Class[] { String.class }); 110 try { 111 if (null != ctor) { 112 result = ctor.newInstance(new Object[] { m_testName }); 113 } 114 else { 115 ctor = cls.getConstructor(new Class[0]); 116 result = ctor.newInstance(new Object[0]); 117 } 118 } 119 catch (IllegalArgumentException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | SecurityException ex) { 120 ex.printStackTrace(); 121 } catch (InstantiationException ex) { 122 System.err.println("Couldn't find a constructor with a String parameter on your JUnit test class."); 123 ex.printStackTrace(); 124 } 125 126 return result; 127 } 128 129 130 @Override 131 public ITestNGMethod[] getBeforeTestMethods(Class cls) { 132 ITestNGMethod[] result = privateFindTestMethods(new INameFilter() { 133 @Override 134 public boolean accept(Method method) { 135 return "setUp".equals(method.getName()); 136 } 137 }, cls); 138 139 return result; 140 } 141 142 @Override 143 public ITestNGMethod[] getAfterTestMethods(Class cls) { 144 ITestNGMethod[] result = privateFindTestMethods(new INameFilter() { 145 @Override 146 public boolean accept(Method method) { 147 return "tearDown".equals(method.getName()); 148 } 149 }, cls); 150 151 return result; 152 } 153 154 @Override 155 public ITestNGMethod[] getAfterClassMethods(Class cls) { 156 return new ITestNGMethod[0]; 157 } 158 159 @Override 160 public ITestNGMethod[] getBeforeClassMethods(Class cls) { 161 return new ITestNGMethod[0]; 162 } 163 164 @Override 165 public ITestNGMethod[] getBeforeSuiteMethods(Class cls) { 166 return new ITestNGMethod[0]; 167 } 168 169 @Override 170 public ITestNGMethod[] getAfterSuiteMethods(Class cls) { 171 return new ITestNGMethod[0]; 172 } 173 174 @Override 175 public ITestNGMethod[] getBeforeTestConfigurationMethods(Class testClass) { 176 return new ITestNGMethod[0]; 177 } 178 179 @Override 180 public ITestNGMethod[] getAfterTestConfigurationMethods(Class testClass) { 181 return new ITestNGMethod[0]; 182 } 183 184 @Override 185 public ITestNGMethod[] getBeforeGroupsConfigurationMethods(Class testClass) { 186 return new ITestNGMethod[0]; 187 } 188 189 @Override 190 public ITestNGMethod[] getAfterGroupsConfigurationMethods(Class testClass) { 191 return new ITestNGMethod[0]; 192 } 193 } 194 195 ///////////// 196 197 interface INameFilter { 198 public boolean accept(Method method); 199 } 200