diff --git a/src/main/java/org/easetech/easytest/annotation/Param.java b/src/main/java/org/easetech/easytest/annotation/Param.java
index 3314ac5..ccf25b5 100644
--- a/src/main/java/org/easetech/easytest/annotation/Param.java
+++ b/src/main/java/org/easetech/easytest/annotation/Param.java
@@ -22,16 +22,17 @@
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import org.easetech.easytest.converter.AbstractConverter;
import org.easetech.easytest.converter.Converter;
import org.easetech.easytest.converter.ConverterManager;
import org.easetech.easytest.internal.EasyParamSignature;
import org.easetech.easytest.util.DataContext;
import org.easetech.easytest.util.GeneralUtil;
import org.junit.Assert;
+import org.junit.BeforeClass;
import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
-import org.junit.experimental.theories.ParametersSuppliedBy;
import org.junit.experimental.theories.PotentialAssignment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,48 +45,91 @@
import sun.beans.editors.ShortEditor;
/**
- * An extension of Junit's {@link ParametersSuppliedBy} annotation that converts the data for Junit to consume. This
- * Annotation gives the ability to get the data per method rather than per class. Also Junit will automatically call the
+ * A parameter level optional annotation that converts the data for EasyTest based test methods to consume. This
+ * Annotation gives the ability to pass input parameters to the test method. EasyTest will automatically call the test
* method as many times as there are number of data sets to be run against that particular method. For example, if the
- * user has specified 5 data set for a single junit method, Junit will call the method five times, each time providing
+ * user has specified 5 data set for a single test method, EasyTest will call the method five times, each time providing
* the test data that was provided by the user.
- * The annotation is normally used in conjunction with {@link DataLoader} annotation although it can be used with it as
- * well.
- * The annotation contains a single optional field :
+ * The annotation is used in conjunction with {@link DataLoader} annotation. {@link DataLoader} annotation is
+ * used to provide test data to the test cases.
+ *
+ * The annotation is optional. In case the name of the input parameter provided in the data file(XML, Excel, CSV or custom)
+ * is same as the name of the input parameter type then this annotation can be omitted.
+ * For eg:
+ *
+ * public void testWithStrongParameters(LibraryId id ,
+ *@Param(name="itemid") ItemId
+ * itemId) { .... }
+ *
+ *
+ * In the above example we have not provided @Param annotation to the input paramater LibraryId. In this case the test parameter name in the test file should be LibraryId.
+ * You have to take care that in scenario where the input parameters are of the same type, the
+ * names should be different. Thus if you have two input parameters of type LibraryId then you should
+ * provide atleast @Param annotation on one of the input parameters.
+ *
+ * The annotation contains a single mandatory field :
*
- *
name : the name of the parameter(OPTIONAL) as is present in the input test data file. In case the
- * param name value is not specified and the Parameter type is Map, {@link DataSupplier} simply provides the HashMap
+ * name : the name of the parameter(Mandatory) as is present in the input test data file. In case the
+ * param annotation is not specified and the Parameter type is Map, {@link DataSupplier} simply provides the HashMap
* instance that was created while loading the data. This {@link HashMap} represents a single set of test data for the
- * test method. In case the param name is not specified and the parameter type is a strongly typed Object of
- * the client using this annotation(for eg LibraryId), it will try to search for the parameter with the name which is
- * the class name of the Object parameter. In case the param name is specified the framework will look for the
+ * test method. In case the param name is specified along with the {link @Param} annotation, the framework will look for the
* parameter with the specified name in the loaded test data.
+ *
*
* Moreover, the framework supports PropertyEditors support for strongly typed objects. If you have a custom object and
- * its property editor in the same package, the JUnit framework will convert the String value to your specified custom
+ * its property editor in the same package, the EasyTest framework will convert the String value to your specified custom
* object by calling the right property editor and pass an instance of custom object to your test case. This provides
- * the users facility to write test cases such as this :
+ * the users facility to write test cases such as this :
*
* @Test
- * @DataLoader(filePaths ={ "getItemsData.csv" }) public void testWithStrongParameters(@Param() LibraryId id ,
- * @Param(name="itemid") ItemId itemId) { ....
- *
- * }
- * Example of using Map to get the entire data:
+ * @DataLoader(filePaths ={ "getItemsData.csv" })
public void testWithStrongParameters(LibraryId id ,@Param(name="itemid") ItemId itemId) { ....
+ * }
+ * Example of using Map to get the entire data:
*
* @Test
- * @DataLoader(filePaths= {"getItemsData.csv" })
public void testGetItemsWithoutFileType(@Paramr()
- * Map inputData) {
........
+ *(@)DataLoader(filePaths= {"getItemsData.csv" })
public void testGetItemsWithoutFileType(@Paramr()
+ * Map inputData) {
........
*
* }
+ *
+ *
+ *
+ *The EasyTest framework also supports custom {@link Converter}s. Converters are a mechanism for the user to translate a map of key/value pair into
+ *custom objects that can be passed as input parameters to the test cases.
+ *For example, if you want to pass a complex object as input parameter to a test case then you will simply write a custom converter that extends {@link AbstractConverter}
+ *and will override the {@link AbstractConverter#convert(Map)} method. You can look at example of CustomConverter here :
+ *https://github.com/EaseTech/easytest-core/blob/master/src/test/java/org/easetech/easytest/example/ItemConverter.java
+ *
+ *
+ *If you want to pass a Collection type, then EasyTest framework provides the functionality to instantiate the Collection class for you and pass in the right generic parameter if possible.
+ *For eg. if you have a test method like this :
+ *
+ *
+ * (At)Test
+ * public void testArrayList(@Param(name="items") ArrayList<ItemId> items){
+ * Assert.assertNotNull(items);
+ * for(ItemId item : items){
+ * System.out.println("testArrayList : "+item);
+ * }
+ * }
+ *
+ * then all you have to do is :
+ * pass the list of itemIds as ":" separated list in the test data file(XML, CSV,Excel or custom), for eg: 23:56:908:666
+ * and register an editor or converter for converting the String data to object.
+ * In case the generic type argument to the Collection is a standard Java type(Date, Character, Timestamp, Long, Interger, Float, Double etc)
+ * then you don't have to do anything and the framework will take care of converting the String data to the requested type.
+ *
+ *Finally, even though the EasyTest framework is compiled with JDK 1.5, it does not stop you from using Java 6 Collection Types in case you are running your code on JRE 6.
+ *For using Java 6 Collection type(like Deque , LinkedBlockingDeque etc) in your test cases, all you have to do is register an empty implementation of {@link AbstractConverter} in the {@link BeforeClass} method.
+ *Note that you should pass only the Concrete type as parameter argument while extending the {@link AbstractConverter} and not the Abstract type or the interface type.
+ *You can always override the default implementation of creating a specific type instance for use in your test cases by overriding the {@link AbstractConverter#instanceOfType()} method.
+ *
*
* @author Anuj Kumar
*/
@Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER })
+@Target({ElementType.PARAMETER })
public @interface Param {
-
-
/** The name of the parameter for which value needs to be fetched from the data set */
String name();
@@ -97,8 +141,11 @@
*
*/
static class DataSupplier {
-
- protected final Logger LOG = LoggerFactory.getLogger(DataSupplier.class);
+
+ /**
+ * Logger
+ */
+ protected final static Logger LOG = LoggerFactory.getLogger(DataSupplier.class);
private static final String COLON = ":";
@@ -113,7 +160,6 @@ static class DataSupplier {
PropertyEditorManager.registerEditor(Float.class, FloatEditor.class);
PropertyEditorManager.registerEditor(Byte.class, ByteEditor.class);
PropertyEditorManager.registerEditor(Short.class, ShortEditor.class);
- //PropertyEditorManager.registerEditor(Character.class, CharacterEditor.class);
PropertyEditorManager.registerEditor(Double.class, DoubleEditor.class);
PropertyEditorManager.registerEditor(Boolean.class, BoolEditor.class);
@@ -181,12 +227,14 @@ private List convert(List