I'm working on Rest API testing (POST method) for which I'm reading json data from spreadsheet using TestNg Dataprovider.
My Dataprovider returns HashMap with key: Integer Row_Number and value: ArrayList (String) of test data. Below is the sample map returned by DataProvider.
{0=[Sample1, Name1, sample1.name1#example.com, (000) 111-1111], 1=[Sample2, Name2, sample2.name2#example.com, (000) 111-1112]}
My current implementation of Dataprovider is,
#DataProvider
public Object[][] JSONBODY()
{
String test_data = "json_data";
int row = ExcelUtils.getRowNum(test_data, col_num);
int total_col = ExcelUtils.getLastColumnNumber(row);
Map<Integer, ArrayList<String>> map = ExcelUtils.getTableArray(spreadsheet_location,test_data,total_col);
return new Object[][] { { map } };
}
getTableArray implementation
public static Map<Integer, ArrayList<String>> getTableArray(String FilePath, String testdata, int total_Col) throws Exception {
Map<Integer, ArrayList<String>> map = new HashMap<Integer, ArrayList<String>>();
ArrayList<Integer> iTestCaseRow = null;
try
{
FileInputStream ExcelFile = new FileInputStream(FilePath);
ExcelWBook = new XSSFWorkbook(ExcelFile);
ExcelWSheet = ExcelWBook.getSheet(SheetName);
int startCol = 1;
iTestCaseRow = ExcelUtils.getRowContains(testdata ,col_num); // getRowContains returns list of row numbers for value in testdata.
int totalRows = iTestCaseRow.size();
int totalCols = total_Col;
for(int i=0; i<totalRows;i++)
{
ArrayList<String> str = new ArrayList<String>();
for (int j=startCol;j<=totalCols;j++)
{
str.add (ExcelUtils.getCellData(iTestCaseRow.get(i),j));
}
map.put(iTestCaseRow.get(i), str);
}
return map;
}
}
Test Method
#Test(dataProvider = "JSONBODY")
public void TestMethod(Map<Integer, ArrayList<String>> map) throws Exception {
try
{
Log.startTestCase("Start executing Test Case");
Set<Integer> key = map.keySet();
for(Integer row: key)
{
SamplePojo pojo = new SamplePojo();
ArrayList<String> data = map.get(row);
pojo.setFirstName(data.get(0));
pojo.setLastName(data.get(1));
pojo.setEmail(data.get(2));
pojo.setPhone(data.get(3));
Response res = RestAssured.given().contentType(ContentType).body(pojo).when().post(POST_URL);
Log.info(res.asString());
Assert.assertTrue(res.getStatusCode() == 200 , "Test Case failed");
}
}
}
Spreadsheet Test Data is,
Spreadsheet Data
When I execute my #Test method, TestNG executes as one method instead of two as I have 2 rows of test data(value: json_data) in the spreadsheet.
Kindly help me in running the Test method individually for each key:value pair.
Thanks in advance!
The problem is in your data provider.
After you obtain your map, you need to translate that map such that every entry in it is now part of the 2D Object array. In your case, you have basically just added that entire map as one single data item in the 2D object array.
Please see below for a full fledged example that shows what I am referring to. For the sake of convenience I have basically excluded the excel spreadsheet reading logic etc.,
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestClass {
#Test(dataProvider = "dp")
public void testMethod(Map<Integer, List<String>> data) {
Assert.assertTrue(data.size() == 1);
List<String> values = data.values().iterator().next();
System.err.println("Values = " + values);
}
#DataProvider(name = "dp")
public Object[][] getData() {
Map<Integer, List<String>> data = getTableArray();
//Transform the Map into a 2D array such that every key/value
//pair in the map becomes one element in the 2D array
int size = data.size();
Object[][] dataToUse = new Object[size][1];
int i = 0;
for (Map.Entry<Integer, List<String>> entry : data.entrySet()) {
Map<Integer, List<String>> localMap = new HashMap<>();
localMap.put(entry.getKey(), entry.getValue());
dataToUse[i++] = new Object[]{localMap};
}
return dataToUse;
}
static Map<Integer, List<String>> getTableArray() {
Map<Integer, List<String>> data = new HashMap<>();
data.put(1, Arrays.asList("Sample1", "Name1", "sample1.name1#gmail.com", "(000) 111-1111"));
data.put(2, Arrays.asList("Sample2", "Name2", "sample2.name2#gmail.com", "(000) 111-1112"));
data.put(3, Arrays.asList("Sample3", "Name3", "sample3.name3#gmail.com", "(000) 111-1113"));
return data;
}
}
Here's the output
Values = [Sample1, Name1, sample1.name1#gmail.com, (000) 111-1111]
Values = [Sample2, Name2, sample2.name2#gmail.com, (000) 111-1112]
Values = [Sample3, Name3, sample3.name3#gmail.com, (000) 111-1113]
===============================================
Default Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
Two options:
Map<Integer, ArrayList<String>> map = ExcelUtils.getTableArray(spreadsheet_location,test_data,total_col);
Object[][] dataToBeReturned = new Object[map.size()][];
//Loop through map and build your array..code not tested..something to the effect
for(Entry<Integer, Arra..> datum : map.entrySet()) {
dataToBeReturned[i++] = new Object[] {datum.getKey(), datum.getValue()}
}
return dataToBeReturned;
or in your excelreader itself, since you are in any case looping through the data, either put it in an array instead of map - something like
instead of map.put(iTestCaseRow.get(i), str);
use dataToBeReturned[i++] = new Object[] {iTestCaseRow.get(i), str}
Related
I am trying to read a text file and store with a hashmap. The file contains information like this:
1946-01-12;13:00:00;0.3;G
1946-01-12;18:00:00;-2.8;G
1946-01-13;07:00:00;-6.2;G
1946-01-13;13:00:00;-4.7;G
1946-01-13;18:00:00;-4.3;G
1946-01-14;07:00:00;-1.5;G
1946-01-14;13:00:00;-0.2;G
I want to store the dates as keys and then "13:00:00;0.3;G" as value, where 13:00 is time, 0.3 is temperature and G represent a quality code. I wonder if this is even possbile since many rows in the file has the same date? I already wrote a code for storing the data in a list, but now I want to store it in a map instead. My old code looks like this:
/**
* Provides methods to retrieve temperature data from a weather station file.
*/
public class WeatherDataHandler {
private List<Weather> weatherData = new ArrayList<>();
public void loadData(String filePath) throws IOException {
List<String> fileData = Files.readAllLines(Paths.get("filepath"));
for(String str : fileData) {
List<String> parsed = parseData(str);
LocalDate date = LocalDate.parse(parsed.get(0));
LocalTime time = LocalTime.parse(parsed.get(1));
double temperature = Double.parseDouble(parsed.get(2));
String quality = parsed.get(3);
//new Weather object
Weather weather = new Weather(date, time, temperature, quality);
weatherData.add(weather);
}
}
private List<String> parseData(String s) {
return Arrays.asList(s.split(";"));
}
I got stuck when implementing the hashmap. I started with some code below, but I do not know how to loop over a sequence of dates. What is the simplest way to store the data from the file in a map?
public class WeatherDataHandler {
public void loadData(String filePath) throws IOException {
Map<LocalDate, String> map =new HashMap<LocalDate, String>();
BufferedReader br = new BufferedReader(new FileReader("filepath"));
String line="";
int i=0;
while (line != null) {
line = br.readLine();
map.put(i,line);
i++;
}
String date="";
String time="";
String temperature="";
String quality="";
for(int j=0;j<map.size();j++){
if(!(map.get(j)== null)){
String[] getData=map.get(j).toString().split("\\,");
date = getData[0];
time = getData[1];
temperature = getData[2];
quality = getData[3];
}
}
}
Using the stream API you can create a map where the key is the date and the [map] value is a list.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class WeatherDataHandler {
public static void main(String[] args) {
Path path = Paths.get("filepath");
try {
Map<String, List<String>> map = Files.lines(path)
.collect(Collectors.groupingBy(line -> line.split(";", 2)[0]));
map.entrySet()
.stream()
.forEach(entry -> System.out.printf("%s = %s%n", entry.getKey(), entry.getValue()));
}
catch (IOException x) {
x.printStackTrace();
}
}
}
Method lines() in class java.nio.file.Files creates a stream where each stream element is a single line of the file being read.
Method split() splits the line into a two element array (because of the second argument which is the number 2).
The first array element, i.e. the date, becomes the [map] key and the rest of the line becomes the [map] value.
Whenever a duplicate key is encountered, the value is appended to the existing value creating a list. Hence the type parameters for the map are String for the [map] key and List<String> for the [map] value.
Running the above code on your sample data yields:
1946-01-14 = [1946-01-14;07:00:00;-1.5;G, 1946-01-14;13:00:00;-0.2;G]
1946-01-12 = [1946-01-12;13:00:00;0.3;G , 1946-01-12;18:00:00;-2.8;G]
1946-01-13 = [1946-01-13;07:00:00;-6.2;G , 1946-01-13;13:00:00;-4.7;G, 1946-01-13;18:00:00;-4.3;G ]
I am working on a piece of code which has a Hashmap. This hashmap has a string as key and an arraylist as value. I populate arraylist the with values I'm fetching using a DQL. I've three attributes for many users. Then putting the value into the hashmap. What I want is to iterate the Hashmap and fetch the set of 3 attritubes for 1 user. Let me provide the code below
package com;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import xtrim.util.i;
import com.documentum.com.DfClientX;
import com.documentum.com.IDfClientX;
import com.documentum.fc.client.DfQuery;
import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfCollection;
import com.documentum.fc.client.IDfQuery;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfLoginInfo;
import com.documentum.fc.common.IDfLoginInfo;
public class Adlookup {
IDfSessionManager sessionMrg = null;
IDfSession session=null;
IDfClient dfclient = null;
IDfClientX clientX = new DfClientX();
IDfCollection total = null;
int j;
int flag = 0;
WriteToExcel ex = new WriteToExcel();
public void LookupReport(String docbaseName, String username, String password) throws DfException, IOException
{
dfclient = clientX.getLocalClient();
String Docbase = docbaseName;
IDfLoginInfo loginInfo = new DfLoginInfo();
loginInfo.setUser(username);
loginInfo.setPassword(password);
sessionMrg = dfclient.newSessionManager();
sessionMrg.setIdentity(Docbase, loginInfo);
session = sessionMrg.getSession(Docbase);
System.out.println("connection created for adlookup");
String query = Getquery();
IDfQuery dql = new DfQuery();
dql.setDQL(query);
total = dql.execute(session, IDfQuery.DF_EXEC_QUERY);
System.out.println("all good for lookup");
//String[] columnNames = new String[] { "User Name","User Login Name","Email"};
List<String> lstValues = new ArrayList<String>();
Map<Integer, ArrayList<String>> myMap = new HashMap<Integer, ArrayList<String>>();
while (total.next())
{
lstValues.add(total.getString("uname")+","+total.getString("loginname")+","+total.getString("uadd"));
myMap.put(flag, (ArrayList<String>) lstValues);
flag++;
System.out.println("Flag value: " +flag);
// lstValues.clear();
}
Set setofKeys = myMap.keySet();
Iterator itr = setofKeys.iterator();
while(itr.hasNext())
{
Integer key = (Integer) itr.next();
ArrayList<String> value = myMap.get(key);
System.out.println("\nResult :"+value);
}
}
private String Getquery() {
// TODO Auto-generated method stub
String query = "select user_name as uname, user_login_name as loginname, user_address as uadd from dm_user dmu, dm_dbo.MV_V_MIDAS_MERCK_PRSN1 dma where upper(dmu.user_login_name)=upper(dma.isid) and dmu.user_state=0 and directory_display_ind='I'";
return query;
}
}
I'm getting output like this
Result :
[Sayre,Joseph,sayrej,joseph.sayre#abc.com, Kapoor,Rohit,kapoorro,rohit.kapoor#abc.com, Pineiros-Vallejo, Miguel,pineirom,rajendra.baxi#abc.com]
Result :[Sayre,Joseph,sayrej,joseph.sayre#abc.com, Kapoor,Rohit,kapoorro,rohit.kapoor#abc.com, Pineiros-Vallejo, Miguel,pineirom,rajendra.baxi#abc.com]
Result :[Sayre,Joseph,sayrej,joseph.sayre#abc.com, Kapoor,Rohit,kapoorro,rohit.kapoor#abc.com, Pineiros-Vallejo, Miguel,pineirom,rajendra.baxi#abc.com]
but I want something like this :
Result : Sayre,Joseph,sayrej,joseph.sayre#abc.com
Result : Kapoor,Rohit,kapoorro,rohit.kapoor#abc.com
Result : Pineiros-Vallejo, Miguel,pineirom,rajendra.baxi#abc.com
Also I need to print this values in an excelsheet.
Any kind of help will appreciated.
If the content of the ArrayList are attributes of a user, then why don't you create a class UserAttributes having fields to store the values and overrides toString() to output them?
Instead of using toString() on the ArrayList itself, iterate over its contents and print the individual members. Add another loop inside the while(itr.hasNext()) loop.
Use advanced for to display the String value like below,
while(itr.hasNext())
{
Integer key = (Integer) itr.next();
ArrayList<String> value = myMap.get(key);
System.out.print("\nResult : ");
for(String strValue:value){
System.out.println(strValue + ",");
}
}
Thanks
Raju
I'd create an object "user" with fields for each entry:
lstValues.add(total.getString("uname")+","+total.getString("loginname")+","+total.getString("uadd"));
to
lstValues.add(new User(total.getString("uname"), total.getString("loginname"), total.getString("uadd")));
Then override toString() inside the User object.
Tip:
You can also use map.entrySet() to iterate.
Your code:
Set setofKeys = myMap.keySet();
Iterator itr = setofKeys.iterator();
while(itr.hasNext())
{
Integer key = (Integer) itr.next();
ArrayList<String> value = myMap.get(key);
System.out.println("\nResult :"+value);
}
My Code:
Map<Integer, User> map = new HashMap<>();
for( Entry<Integer, User> entry : map.entrySet() ) {
entry.getKey();
entry.getValue(); // the user object you want
}
Instead of
while(itr.hasNext())
{
Integer key = (Integer) itr.next();
ArrayList<String> value = myMap.get(key);
System.out.println("\nResult :"+value);
}
use this
while (total.next) {
System.out.println("\nResult :"
+ itr.getString("uname") + ", "
+ itr.getString("loginname") + ", "
+ itr.getString("uadd") );
}
EDIT: switched from using itr object to total object. I see you are using IDfCollection total for adding some flag which you don't use later anywhere. Lose everything and just loop through collection total. Your code is big mixture of your temporarily ideas that survived when you changed your mind. Change your code. :)
I have two arraylists as follows.
ArrayList<String> keys = new ArrayList<>();
ArrayList<String> values = new ArrayList<>();
keys.add("1","1","1","2","2","3");
values.add("2016-06-22 07:18:45", "2016-06-22 08:18:45", "2016-06-22 09:18:45",
"2016-06-22 03:18:45","2016-06-22 04:18:45","2016-06-22 01:18:45");
Now i need the function
HashMap latestValues(keys, values);
The output should be as follows,
["1"=>"2016-06-22 09:18:45","2"=>"2016-06-22 04:18:45", "3"=>"2016-06-22 01:18:45"]
Returning the latest dated single value for that particular key. Can anyone please suggest how to achieve this.
Thanks and advance!
I think this will do it.
public static void main(String[] args) {
ArrayList<String> keys = new ArrayList<>(Arrays.asList("1", "1", "1", "2", "2", "3"));
ArrayList<String> values = new ArrayList<>(Arrays.asList("2016-06-22 07:18:45", "2016-06-22 08:18:45", "2016-06-22 09:18:45",
"2016-06-22 03:18:45", "2016-06-22 04:18:45", "2016-06-22 01:18:45"));
HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0; keys.size() == values.size() && i < keys.size(); i++) {
String key = keys.get(i);
String value = values.get(i);
if (!map.containsKey(key) || dateAsNo(value) > dateAsNo(map.get(key))) {
map.put(key, value);
}
}
System.out.println(map);
}
public static long dateAsNo(String v) {
return Long.parseLong(v.replaceAll("\\D", ""));
}
It will only work if all the dates have the same format yyyy-MM-dd hh:mm:ss
You can use the following approach. Values will be overwritten only when date is newer (I am assuming you are not changing the date format)
Map<String,String> hashMap = new HashMap<>();
List<String> keys = new ArrayList<>();
List<String> values = new ArrayList<>();
if(keys.size() != values.size())
return null;
for(int i=0; i<keys.size(); i++){
String keyVal = hashMap.get(keys.get(i));
if(keyVal==null || keyVal.compareTo(values.get(i))>0){
// second condition ensures value is only replaced if it is a later date
hashMap.put(keys.get(i), values.get(i));
}
}
return hashMap;
Try the same thing that you would do if you wre doing this manually. set your current key and go through your list till you find different key and put the current key and appropriate value (that is the value with the same index) in your map
public static void main (String [] args) throws IOException{
ArrayList<String> keys = new ArrayList<>();
ArrayList<String> values = new ArrayList<>();
keys.add("1");keys.add("1"); keys.add("1");
keys.add("2");keys.add("2");
keys.add("3");
values.add("2016-06-22 07:18:45");values.add("2016-06-22 08:18:45");values.add("2016-06-22 09:18:45");
values.add("2016-06-22 03:18:45");values.add("2016-06-22 04:18:45");
values.add("2016-06-22 01:18:45");
Map<String,String> myMap = new HashMap<>();
String currentKey = keys.get(0); // set your current key and go through your list till you find the next key and put the current key and appropriate value (that is the value with the same index) in your map
for(int i = 0;i<keys.size();i++){
if(!currentKey.equalsIgnoreCase(keys.get(i))){
myMap.put(currentKey, values.get(i-1));
currentKey = keys.get(i);
}
if(i==keys.size()-1){
myMap.put(currentKey, values.get(i));
}
}
System.out.println(myMap);
}
you can write just like :
package java7.demo;
import java.util.*;
public class MapTest {
public static void main(String args[]){
ArrayList<String> keys = new ArrayList<>();
ArrayList<String> values = new ArrayList<>();
keys.add("1");
keys.add("1");
keys.add("1");
keys.add("2");
keys.add("2");
keys.add("3");
values.add("2016-06-22 07:18:45");
values.add("2016-06-22 08:18:45");
values.add("2016-06-22 09:18:45");
values.add("2016-06-22 03:18:45");
values.add("2016-06-22 04:18:45");
values.add("2016-06-22 01:18:45");
LinkedHashMap<String,String>map = new LinkedHashMap<String,String>();
for(int i =0; i<keys.size();i++){
map.put(keys.get(i),values.get(i));
}
System.out.println(map);
}
}
as Map(include hashmap,linkedhashmap)replace old key value with new key value if old key value and new key value has same value,you will get 1->2016-06-22 09:18:45.at first it will put[ 1,2016-06-22 07:18:45]to map,in second loop,it will replace with [1,2016-06-22 08:18:45].int third time loop,it will replace with [1,09:18:45].to get data according to insertion Order,I use LinkedHashMap.
I have read some data from Excel in array form, and converted into a 2-D array in order to provide the data to a data provider.But now in the #Test when I pass the data it takes on the null value.
Can you please suggest why it's going null? Also my function in #Test is using a map as well - how can I convert the data provider data to map ?
My function in #Test is like below:-
public void testCategorySearch(String vendor_code, Map<Integer, List<String>> seller_sku , String upload_id,Protocol protocol)
throws InvocationTargetException
My code is :
#DataProvider(name = "valid_parameters")
public Object[][] sendValidParameters() {
List<ArrayList> result = td.getExcelData("C:\\Users\\ashish.gupta02\\QAAutomation\\test.xls", 1);
Object[][] a = new String[result.size()][3];
{
for (int i = 0; i < result.size(); i++) {
Object currentObject = result.get(i);
a[i][0] = currentObject.toString();
System.out.println("COnverted" + a[i][0]);
}
}
System.out.println("Printing data" + a);
//return mapper.getProtocolMappedObject(a);
//return Object ;
return a;
}
#Test(dataProvider = "valid_parameters", groups = {"positive"})
public void testCategorySearch(String vendor_code, Map<Integer, List<String>> seller_sku, String upload_id, Protocol protocol)
throws InvocationTargetException {
//Protocol protocol
//set parameter values to the api
System.out.println("Executing the request");
CreateSellerProductUpdateInfoRequest createReq = setRequest(vendor_code, seller_sku, upload_id, protocol);
CreateSellerProductUpdateInfoResponse createResponse = service.createSellerProductUpdateInfo(createReq);
System.out.print("Response is :" + createResponse);
}
public static void main(String[] args)
{
String input="jack=susan,kathy,bryan;david=stephen,jack;murphy=bruce,simon,mary";
String[][] family = new String[50][50];
//assign family and children to data by ;
StringTokenizer p = new StringTokenizer (input,";");
int no_of_family = input.replaceAll("[^;]","").length();
no_of_family++;
System.out.println("family= "+no_of_family);
String[] data = new String[no_of_family];
int i=0;
while(p.hasMoreTokens())
{
data[i] = p.nextToken();
i++;
}
for (int j=0;j<no_of_family;j++)
{
family[j][0] = data[j].split("=")[0];
//assign child to data by commas
StringTokenizer v = new StringTokenizer (data[j],",");
int no_of_child = data[j].replaceAll("[^,]","").length();
no_of_child++;
System.out.println("data from input = "+data[j]);
for (int k=1;k<=no_of_child;k++)
{
family[j][k]= data[j].split("=")[1].split(",");
System.out.println(family[j][k]);
}
}
}
i have a list of family in input string and i seperate into a family and i wanna do it in double array family[i][j].
my goal is:
family[0][0]=1st father's name
family[0][1]=1st child name
family[0][2]=2nd child name and so on...
family[0][0]=jack
family[0][1]=susan
family[0][2]=kathy
family[0][3]=bryan
family[1][0]=david
family[1][1]=stephen
family[1][2]=jack
family[2][0]=murphy
family[2][1]=bruce
family[2][2]=simon
family[2][3]=mary
but i got the error as title: in compatible types
found:java.lang.String[]
required:java.lang.String
family[j][k]= data[j].split("=")[1].split(",");
what can i do?i need help
nyone know how to use StringTokenizer for this input?
Trying to understand why you can't just use split for your nested operation as well.
For example, something like this should work just fine
for (int j=0;j<no_of_family;j++)
{
String[] familySplit = data[j].split("=");
family[j][0] = familySplit[0];
String[] childrenSplit = familySplit[1].split(",");
for (int k=0;k<childrenSplit.length;k++)
{
family[j][k+1]= childrenSplit[k];
}
}
You are trying to assign an array of strings to a string. Maybe this will make it more clear?
String[] array = data.split("=")[1].split(",");
Now, if you want the first element of that array you can then do:
family[j][k] = array[0];
I always avoid to use arrays directly. They are hard to manipulate versus dynamic list. I implemented the solution using a Map of parent to a list of childrens Map<String, List<String>> (read Map<Parent, List<Children>>).
public static void main(String[] args) {
String input = "jack=susan,kathy,bryan;david=stephen,jack;murphy=bruce,simon,mary";
Map<String, List<String>> parents = new Hashtable<String, List<String>>();
for ( String family : input.split(";")) {
final String parent = family.split("=")[0];
final String allChildrens = family.split("=")[1];
List<String> childrens = new Vector<String>();
for (String children : allChildrens.split(",")) {
childrens.add(children);
}
parents.put(parent, childrens);
}
System.out.println(parents);
}
The output is this:
{jack=[susan, kathy, bryan], murphy=[bruce, simon, mary], david=[stephen, jack]}
With this method you can directory access to a parent using the map:
System.out.println(parents.get("jack"));
and this output:
[susan, kathy, bryan]