PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/TestTools/src/org/testng/internal/Parameters.java

http://ravi-project-iptest.googlecode.com/
Java | 435 lines | 315 code | 51 blank | 69 comment | 113 complexity | 0d178acc9bdf5313279a488e4be901fd MD5 | raw file
  1. package org.testng.internal;
  2. import org.testng.ITestContext;
  3. import org.testng.ITestNGMethod;
  4. import org.testng.ITestResult;
  5. import org.testng.TestNGException;
  6. import org.testng.annotations.IConfigurationAnnotation;
  7. import org.testng.annotations.IDataProviderAnnotation;
  8. import org.testng.annotations.IFactoryAnnotation;
  9. import org.testng.annotations.IParameterizable;
  10. import org.testng.annotations.IParametersAnnotation;
  11. import org.testng.annotations.ITestAnnotation;
  12. import org.testng.internal.annotations.AnnotationHelper;
  13. import org.testng.internal.annotations.IAnnotationFinder;
  14. import org.testng.xml.XmlSuite;
  15. import org.testng.xml.XmlTest;
  16. import java.lang.reflect.Constructor;
  17. import java.lang.reflect.Method;
  18. import java.lang.reflect.Modifier;
  19. import java.util.ArrayList;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.Map;
  23. /**
  24. * Methods that bind parameters declared in testng.xml to actual values
  25. * used to invoke methods.
  26. *
  27. * @author <a href="mailto:cedric@beust.com">Cedric Beust</a>
  28. * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
  29. *
  30. * @@ANNOTATIONS@@
  31. */
  32. public class Parameters {
  33. public static final String NULL_VALUE= "null";
  34. /**
  35. * Creates the parameters needed for constructing a test class instance.
  36. * @param finder TODO
  37. */
  38. public static Object[] createInstantiationParameters(Constructor ctor,
  39. String methodAnnotation,
  40. IAnnotationFinder finder,
  41. String[] parameterNames,
  42. Map<String, String> params, XmlSuite xmlSuite)
  43. {
  44. return createParameters(ctor.toString(), ctor.getParameterTypes(),
  45. finder.findOptionalValues(ctor), methodAnnotation, finder, parameterNames, new MethodParameters(params), xmlSuite);
  46. }
  47. /**
  48. * Creates the parameters needed for the specified <tt>@Configuration</tt> <code>Method</code>.
  49. *
  50. * @param m the configuraton method
  51. * @param params
  52. * @param currentTestMethod the current @Test method or <code>null</code> if no @Test is available (this is not
  53. * only in case the configuration method is a @Before/@AfterMethod
  54. * @param finder the annotation finder
  55. * @param xmlSuite
  56. * @return
  57. */
  58. public static Object[] createConfigurationParameters(Method m,
  59. Map<String, String> params,
  60. Object[] parameterValues,
  61. ITestNGMethod currentTestMethod,
  62. IAnnotationFinder finder,
  63. XmlSuite xmlSuite,
  64. ITestContext ctx,
  65. ITestResult testResult)
  66. {
  67. Method currentTestMeth= currentTestMethod != null ?
  68. currentTestMethod.getMethod() : null;
  69. return createParameters(m,
  70. new MethodParameters(params, parameterValues, currentTestMeth, ctx, testResult),
  71. finder, xmlSuite, IConfigurationAnnotation.class, "@Configuration");
  72. }
  73. ////////////////////////////////////////////////////////
  74. /**
  75. * @param optionalValues TODO
  76. * @param finder TODO
  77. * @param parameterAnnotations TODO
  78. * @param m
  79. * @param instance
  80. * @return An array of parameters suitable to invoke this method, possibly
  81. * picked from the property file
  82. */
  83. private static Object[] createParameters(String methodName,
  84. Class[] parameterTypes,
  85. String[] optionalValues,
  86. String methodAnnotation,
  87. IAnnotationFinder finder,
  88. String[] parameterNames, MethodParameters params, XmlSuite xmlSuite)
  89. {
  90. Object[] result = new Object[0];
  91. if(parameterTypes.length > 0) {
  92. List<Object> vResult = new ArrayList<Object>();
  93. checkParameterTypes(methodName, parameterTypes, methodAnnotation, parameterNames);
  94. for(int i = 0, j = 0; i < parameterTypes.length; i++) {
  95. if (Method.class.equals(parameterTypes[i])) {
  96. vResult.add(params.currentTestMethod);
  97. }
  98. else if (ITestContext.class.equals(parameterTypes[i])) {
  99. vResult.add(params.context);
  100. }
  101. else if (XmlTest.class.equals(parameterTypes[i])) {
  102. vResult.add(params.context.getCurrentXmlTest());
  103. }
  104. else if (ITestResult.class.equals(parameterTypes[i])) {
  105. vResult.add(params.testResult);
  106. }
  107. else {
  108. if (j < parameterNames.length) {
  109. String p = parameterNames[j];
  110. String value = params.xmlParameters.get(p);
  111. if(null == value) {
  112. // try SysEnv entries
  113. value= System.getProperty(p);
  114. }
  115. if (null == value) {
  116. if (optionalValues != null) {
  117. value = optionalValues[i];
  118. }
  119. if (null == value) {
  120. throw new TestNGException("Parameter '" + p + "' is required by "
  121. + methodAnnotation
  122. + " on method "
  123. + methodName
  124. + "\nbut has not been marked @Optional or defined "
  125. + (xmlSuite.getFileName() != null ? "in "
  126. + xmlSuite.getFileName() : ""));
  127. }
  128. }
  129. vResult.add(convertType(parameterTypes[i], value, p));
  130. j++;
  131. }
  132. }
  133. }
  134. result = (Object[]) vResult.toArray(new Object[vResult.size()]);
  135. }
  136. return result;
  137. }
  138. // FIXME
  139. private static void checkParameterTypes(String methodName,
  140. Class[] parameterTypes, String methodAnnotation, String[] parameterNames)
  141. {
  142. if(parameterNames.length == parameterTypes.length) return;
  143. for(int i= parameterTypes.length - 1; i >= parameterNames.length; i--) {
  144. Class type = parameterTypes[i];
  145. if(!ITestContext.class.equals(type)
  146. && !ITestResult.class.equals(type)
  147. && !XmlTest.class.equals(type)
  148. && !Method.class.equals(type)
  149. && !Object[].class.equals(type)) {
  150. throw new TestNGException( "Method " + methodName + " requires "
  151. + parameterTypes.length + " parameters but "
  152. + parameterNames.length
  153. + " were supplied in the "
  154. + methodAnnotation
  155. + " annotation.");
  156. }
  157. }
  158. }
  159. //TODO: Cosmin - making this public is not the best solution
  160. public static Object convertType(Class type, String value, String paramName) {
  161. Object result = null;
  162. if(NULL_VALUE.equals(value.toLowerCase())) {
  163. if(type.isPrimitive()) {
  164. Utils.log("Parameters", 2, "Attempt to pass null value to primitive type parameter '" + paramName + "'");
  165. }
  166. return null; // null value must be used
  167. }
  168. if(type == String.class) {
  169. result = value;
  170. }
  171. else if(type == int.class || type == Integer.class) {
  172. result = new Integer(Integer.parseInt(value));
  173. }
  174. else if(type == boolean.class || type == Boolean.class) {
  175. result = Boolean.valueOf(value);
  176. }
  177. else if(type == byte.class || type == Byte.class) {
  178. result = new Byte(Byte.parseByte(value));
  179. }
  180. else if(type == char.class || type == Character.class) {
  181. result = new Character(value.charAt(0));
  182. }
  183. else if(type == double.class || type == Double.class) {
  184. result = new Double(Double.parseDouble(value));
  185. }
  186. else if(type == float.class || type == Float.class) {
  187. result = new Float(Float.parseFloat(value));
  188. }
  189. else if(type == long.class || type == Long.class) {
  190. result = new Long(Long.parseLong(value));
  191. }
  192. else if(type == short.class || type == Short.class) {
  193. result = new Short(Short.parseShort(value));
  194. }
  195. else {
  196. assert false : "Unsupported type parameter : " + type;
  197. }
  198. return result;
  199. }
  200. private static DataProviderHolder findDataProvider(Class clazz, Method m,
  201. IAnnotationFinder finder) {
  202. DataProviderHolder result = null;
  203. String dataProviderName = null;
  204. Class dataProviderClass = null;
  205. ITestAnnotation annotation = AnnotationHelper.findTest(finder, m);
  206. if (annotation == null) {
  207. annotation = AnnotationHelper.findTest(finder, clazz);
  208. }
  209. if (annotation != null) {
  210. dataProviderName = annotation.getDataProvider();
  211. dataProviderClass = annotation.getDataProviderClass();
  212. }
  213. if (dataProviderName == null) {
  214. IFactoryAnnotation factory = AnnotationHelper.findFactory(finder, m);
  215. if (factory != null) {
  216. dataProviderName = factory.getDataProvider();
  217. dataProviderClass = null;
  218. }
  219. }
  220. if (null != dataProviderName && ! "".equals(dataProviderName)) {
  221. result = findDataProvider(clazz, finder, dataProviderName, dataProviderClass);
  222. if(null == result) {
  223. throw new TestNGException("Method " + m + " requires a @DataProvider named : "
  224. + dataProviderName + (dataProviderClass != null ? " in class " + dataProviderClass.getName() : "")
  225. );
  226. }
  227. }
  228. return result;
  229. }
  230. /**
  231. * Find a method that has a @DataProvider(name=name)
  232. */
  233. private static DataProviderHolder findDataProvider(Class cls, IAnnotationFinder finder,
  234. String name, Class dataProviderClass)
  235. {
  236. boolean shouldBeStatic = false;
  237. if (dataProviderClass != null) {
  238. cls = dataProviderClass;
  239. shouldBeStatic = true;
  240. }
  241. for (Method m : ClassHelper.getAvailableMethods(cls)) {
  242. IDataProviderAnnotation dp = (IDataProviderAnnotation) finder.findAnnotation(m, IDataProviderAnnotation.class);
  243. if (null != dp && (name.equals(dp.getName()) || name.equals(m.getName()))) {
  244. if (shouldBeStatic && (m.getModifiers() & Modifier.STATIC) == 0) {
  245. throw new TestNGException("DataProvider should be static: " + m);
  246. }
  247. return new DataProviderHolder(dp, m);
  248. }
  249. }
  250. return null;
  251. }
  252. @SuppressWarnings({"deprecation"})
  253. private static Object[] createParameters(Method m, MethodParameters params,
  254. IAnnotationFinder finder, XmlSuite xmlSuite, Class annotationClass, String atName)
  255. {
  256. List<Object> result = new ArrayList<Object>();
  257. Object[] extraParameters = new Object[0];
  258. //
  259. // Try to find an @Parameters annotation
  260. //
  261. IParametersAnnotation annotation = (IParametersAnnotation) finder.findAnnotation(m, IParametersAnnotation.class);
  262. Class<?>[] types = m.getParameterTypes();
  263. if(null != annotation) {
  264. String[] parameterNames = annotation.getValue();
  265. extraParameters = createParameters(m.getName(), types,
  266. finder.findOptionalValues(m), atName, finder, parameterNames, params, xmlSuite);
  267. }
  268. //
  269. // Else, use the deprecated syntax
  270. //
  271. else {
  272. IParameterizable a = (IParameterizable) finder.findAnnotation(m, annotationClass);
  273. if(null != a && a.getParameters().length > 0) {
  274. String[] parameterNames = a.getParameters();
  275. extraParameters = createParameters(m.getName(), types,
  276. finder.findOptionalValues(m), atName, finder, parameterNames, params, xmlSuite);
  277. }
  278. else {
  279. extraParameters = createParameters(m.getName(), types,
  280. finder.findOptionalValues(m), atName, finder, new String[0], params, xmlSuite);
  281. }
  282. }
  283. // If the method declared an Object[] parameter and we have parameter values, inject them
  284. for (int i = 0; i < types.length; i++) {
  285. Class<?> type = types[i];
  286. if (Object[].class.equals(type)) {
  287. result.add(params.parameterValues);
  288. }
  289. }
  290. //
  291. // Add the extra parameters we found
  292. //
  293. for (Object p : extraParameters) {
  294. result.add(p);
  295. }
  296. return result.toArray(new Object[result.size()]);
  297. }
  298. /**
  299. * If the method has parameters, fill them in. Either by using a @DataProvider
  300. * if any was provided, or by looking up <parameters> in testng.xml
  301. * @return An Iterator over the values for each parameter of this
  302. * method.
  303. */
  304. public static ParameterHolder handleParameters(ITestNGMethod testMethod,
  305. Map<String, String> allParameterNames,
  306. Object instance,
  307. MethodParameters methodParams,
  308. XmlSuite xmlSuite,
  309. IAnnotationFinder annotationFinder,
  310. Object fedInstance)
  311. {
  312. ParameterHolder result;
  313. Iterator<Object[]> parameters = null;
  314. //
  315. // Do we have a @DataProvider? If yes, then we have several
  316. // sets of parameters for this method
  317. //
  318. DataProviderHolder dataProviderHolder =
  319. findDataProvider(testMethod.getTestClass().getRealClass(),
  320. testMethod.getMethod(), annotationFinder);
  321. if (null != dataProviderHolder) {
  322. int parameterCount = testMethod.getMethod().getParameterTypes().length;
  323. for (int i = 0; i < parameterCount; i++) {
  324. String n = "param" + i;
  325. allParameterNames.put(n, n);
  326. }
  327. parameters = MethodHelper.invokeDataProvider(
  328. instance, /* a test instance or null if the dataprovider is static*/
  329. dataProviderHolder.method,
  330. testMethod,
  331. methodParams.context,
  332. fedInstance,
  333. annotationFinder);
  334. result = new ParameterHolder(parameters, ParameterHolder.ORIGIN_DATA_PROVIDER,
  335. dataProviderHolder);
  336. }
  337. else {
  338. //
  339. // Normal case: we have only one set of parameters coming from testng.xml
  340. //
  341. allParameterNames.putAll(methodParams.xmlParameters);
  342. // Create an Object[][] containing just one row of parameters
  343. Object[][] allParameterValuesArray = new Object[1][];
  344. allParameterValuesArray[0] = createParameters(testMethod.getMethod(),
  345. methodParams, annotationFinder, xmlSuite, ITestAnnotation.class, "@Test");
  346. // Mark that this method needs to have at least a certain
  347. // number of invocations (needed later to call AfterGroups
  348. // at the right time).
  349. testMethod.setParameterInvocationCount(allParameterValuesArray.length);
  350. // Turn it into an Iterable
  351. parameters = MethodHelper.createArrayIterator(allParameterValuesArray);
  352. result = new ParameterHolder(parameters,
  353. allParameterValuesArray.length == 0
  354. ? ParameterHolder.ORIGIN_DATA_PROVIDER : ParameterHolder.ORIGIN_XML,
  355. dataProviderHolder);
  356. }
  357. return result;
  358. }
  359. private static void ppp(String s) {
  360. System.out.println("[Parameters] " + s);
  361. }
  362. /** A parameter passing helper class. */
  363. public static class MethodParameters {
  364. private final Map<String, String> xmlParameters;
  365. private final Method currentTestMethod;
  366. private final ITestContext context;
  367. private Object[] parameterValues;
  368. public ITestResult testResult;
  369. public MethodParameters(Map<String, String> params) {
  370. this(params, null, null, null, null);
  371. }
  372. public MethodParameters(Map<String, String> params, Method m) {
  373. this(params, null, m, null, null);
  374. }
  375. public MethodParameters(Map<String, String> params, Object[] pv, Method m, ITestContext ctx,
  376. ITestResult tr) {
  377. xmlParameters = params;
  378. currentTestMethod = m;
  379. context = ctx;
  380. parameterValues = pv;
  381. testResult = tr;
  382. }
  383. }
  384. }