How to custom objects from TestNG Dataprovider - java

I have the below DataProvider in TestNG. It has List of custom Objects called
DataSheet[]. I need to pass it to Test method individually but it returns as array.
#DataProvider(name="accountsDetails")
public static Object[][] getData()
{
List<DataSheet> csvValues= CSVReaderUtils.getCSVValues(csvFilePath);
DataSheet[] array = csvValues.toArray(new DataSheet[csvValues.size()]);
return new Object[][]{{array}};
}
#Test(dataProvider="accountsDetails")
public void loginTest(DataSheet data)
{
}
I don't have to iterate in the Test method, It is possible to return ? How to return from data provider method.
Any help is much appreciated.

you can always do something like this:
#DataProvider(name="accountsDetails")
public static Object[][] getData()
{
List<DataSheet> csvValues= CSVReaderUtils.getCSVValues(csvFilePath);
DataSheet[] array = csvValues.toArray(new DataSheet[csvValues.size()]);
Object[][] obj=new Object[numberOfRows][numberOfColumns];
for(int i=0;i< array.length; i++) {
obj[i][0]=array[i];
}
return obj;
}
Please note this is not tested code. but you should get the basic idea.

Related

Data Providers for BeforeMethod capabilities

Is there a way to use Data Providers for BeforeMethod function?
I would like to run parallel tests for number of different devices, so I would like to use parameters to setup capabilities. But I want to have a different way than using testng.xml.
You can get the data passed to the test by the data provider in your BeforeMethod by having Object[] parameter.
#BeforeMethod
public void beforeMethod(Object[] data) {
//.......
}
Assume the following code:
#Test(dataProvider = "dataOne")
public void testMethodOne(String one, int two) {
}
#Test(dataProvider = "dataTwo")
public void testMethodTwo(int one) {
}
#DataProvider
public Object[][] dataOne() {
return new Object[][]{ {"a", 1} };
}
#DataProvider
public Object[][] dataTwo() {
return new Object[][]{ {1} };
}
In order to get the data passed by the data provider before it reaches the test methods, you define a before method as below. I have added Method m parameter as well. This would help to identify the running test case. Object[] data contains the data passed by the data provider. If you have added this argument, then testNG would automatically pass the data to the before method.
#BeforeMethod
public void beforeMethod(Method m, Object[] data) {
if(m.getName().equals("testMethodOne")) {
String x = (String) data[0];
int y = (int) data[1];
} else if(m.getName().equals("testMethodTwo")) {
int x = (int) data[0];
}
}

Selenium java testNG: Is it possible to use dataprovider data partially in testng test method

I am new to Page-Object model automation using selenium and java. I am using the Page Object model and have each page as a single class and the actions in that page as methods.Using excel to keep read test data. I have a test for searching for client using various parameters like client number, policy number, surname, firstname, webrefernce, email eand many more...... Now I have to provide all parameters in method signature otherwise test is failing with dataprovider mismatch error. I have a GetData method which provide string array from excelsheet specified.
Is it possible to make parameters optional so that I can specify only the parameters required for that particular test in the test method's signature.? In actual test there are 15 parameters and additional combinations. (If this is not possible, I have to split the data in to 16 different tab and define data providers for each tests separately). Or any other way to achieve this? Thanks
Current code:
#DataProvider(name="ClientSearchData")
public String[][] getTestData() {
String[][] testRecords = getData("TestData_igo4.xlsx","ClientSearch");
return testRecords;
}
#BeforeTest
public void setUp() {
init();
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByClientNumber(String clientnumber, String policynumber, String surname, String webreference, String email) {
//code for search by clientnumber
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByPolicyNumber(String clientnumber, String policynumber, String surname, String webreference, String email) {
//Code for search by policynumber
}
I want something like the following to avoid unnecessary parameters for each tests..
#DataProvider(name="ClientSearchData")
public String[][] getTestData() {
String[][] testRecords = getData("TestData.xlsx","ClientSearch");
return testRecords;
}
#BeforeTest
public void setUp() {
init();
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByClientNumber(String clientnumber) {
//code for search by clientnumber
}
#Test(dataProvider="ClientSearchData")
public void verifyClientSearchByPolicyNumber(String policynumber) {
//Code for search by policynumber
}
I think what you are looking is Varargs.
You can simply do like below
#DataProvider(name = "testData")
public static Object[][] testDataProvider() {
return new Object[][] {new String[]{"a","b","c"}};
}
#Test(priority=3,dataProvider = "testData")
public void test1(String... str1) {
System.out.println("first string"+" "+str1[0]);
}
#Test(priority=4,dataProvider = "testData")
public void test2(String... str2) {
System.out.println("second string"+" " + str2[1]);
}
The above prints
first string a
second string b
In above code just adjust data provider according to your getTestData
Three dots ... is the key here
EDIT:
You can actually do it without Varargs. The below also prints same
#Test(priority=3,dataProvider = "testData")
public void test1(String str1[] ) {
System.out.println("first string"+" "+str1[0]);
}
#Test(priority=4,dataProvider = "testData")
public void test2(String str2[]) {
System.out.println("second string"+" " + str2[1]);
}
You can model your dataprovider based on the method calling it. What I would do is probably write logic based on method name. Pass the Method object to your dataprovider, based on the name of the method, create your Object[][].
say
public Object[][] dp(Method m) {
key = m.getName.replace("verifyClientSearchBy","");
//From excel data, just fetch key column's values or put
//logic here whatever is convenient
//Build your Object[][] with only one value

How can I add a value to an ArrayList from an inner method?

I am currently trying to add a value to an ArrayList object from a method inside of another class.
Here is the class I have created for the ArrayList Object:
public class ArrayClass {
public static ArrayList<String> array = new ArrayList<>();
public static void add_val(String s){
array.add(s);
}
public static int get_size(){
return array.size();
}
public static String get_val(int i){
return array.get(i);
}
}
And the other class where I attempt to edit the ArrayList object:
ArrayClass fill = new ArrayClass();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_explore);
Response.Listener<String> responseListener4 = new Response.Listener<String>(){
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse4 = new JSONObject(response);
boolean success = jsonResponse4.getBoolean("success");
if (success){
int l;
String filled;
int length4 = jsonResponse4.length();
for (l=0;l<length4;l++){
filled = jsonResponse4.getString(l+"");
fill.add_val(filled);
}
}else{
AlertDialog.Builder builder = new AlertDialog.Builder(ExploreActivity.this);
builder.setMessage("Could not retrieve restaurant tables filled")
.setNegativeButton("Retry", null)
.create()
.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
FilledRequest filledRequest = new FilledRequest(responseListener4);
RequestQueue queue4 = Volley.newRequestQueue(ExploreActivity.this);
queue4.add(filledRequest);
If you look in the onResponse method, you can see the attempt to add a value from the jsonResponse into the ArrayClass object. However, when I launch my app, it does not add the value into the object. I'm used to python global variables and not having to deal with the semantics of java, so if you could shed some light on what changes need to be made, I would greatly appreciate it.
Apart from other given answers/solutions to the issue you are facing, let me share a best and optimized way to implement JSON parsing in Android.
I would suggest you to check GSON or Jackson libraries which provides Java serialization/deserialization that can convert Java Objects into JSON and back.
There are some benefits it does provide, one of the main benefits is you do not need to implement parsing manually and less chances of mistakes in implementing parsing, like you may make a mistake in mentioning key "Success" or "success" or any such silly mistakes!
Firstly, since your variable is static, and the methods are static too, you don't have to instantiate the object. You could do something like this:
ArrayClass.add_val("Hello");
But if you want to instantiate then you can do this:
public class ArrayClass {
private ArrayList<String> array;
public ArrayClass() {
array = new ArrayList<>();
}
public void add_val(String s){
array.add(s);
}
public int get_size(){
return array.size();
}
public String get_val(int i){
return array.get(i);
}
}
To make sure the values are filled in, you can check the array size like this:
for (l=0;l<length4;l++){
filled = jsonResponse4.getString(l+"");
fill.add_val(filled);
}
Log.d("TEST", String.valueOf(fill.get_size());
Remove all cases of the static keyword in ArrayClass. Static methods are class level methods, ie. are called on the class itself, rather than an instance of the class.
You can also try this, for ArrayList:
First do some changes in your ArrayClass. Use get And Set method to access your array.
public class ArrayClass {
private ArrayList<String> array = new ArrayList<>();
public ArrayList<String> getArray() {
return array;
}
public void setArray(ArrayList<String> array) {
this.array = array;
}
}
And your other class where you attempt to edit the ArrayList use getArray And SetArray method and some predefined method of ArrayList like this:
Store the data in ArrayList:
for (l=0;l<length4;l++){
filled = jsonResponse4.getString(l+"");
fill.getArray().add(filled);
}
Get Size of ArrayList:
fill.getArray().size();
And also you can store an another ArrayList like
ArrayList<String> tempArrayList = new ArrayList<String>();
tempArrayList.add("string 1");
tempArrayList.add("string 2");
tempArrayList.add("string 3");
tempArrayList.add("string 4");
fill.setArray(tempArrayList)

How can I JUnit test "printlist"?

I have been staring at this code for quite some time now and I really can't figure out how and what to do for its JUnit testing.
static void printList(OrderedIntList list) {
System.out.print("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
System.out.print(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
System.out.print(", ");
}
}
System.out.println("]");
}
This code is from a utility class called orderedIntList, which is an array list.
Well... think about the contracts of this method: What does it promise? It promises to print a list of integers, separated by a comma, and inside of brackets. So, you could specify this in a unit test.
Edit2: Just in case you fancy unit testing whether the list is printed in order: I would not consider this a property of the printList method. This property should be tested in the methods that modify the OrderedIntList.
Write a fixture for some Lists with the string that you expect to be printed. Don't forget the corner case: An empty list. Then, maybe a list of size 1 and one of size 10.
To check what has been printed, you can create a new PrintStream, and set the value of System.out, by calling System.setOut. Do this at the beginning of each test, and don't forget to reset System.out (so don't forget to store its original value). The PrintStream you use need not be fancy: You simply must be able to compare the printed stream. You may want to consider using Mockito for that matter.
Edit:
For example, the following code tests whether the list containing the sole element 4, actually prints the string "[4]\n":
#Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
/* Setup */
final StringBuffer printStream = new StringBuffer();
PrintStream mockedOut = mock(PrintStream.class);
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(any());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString());
return null;
}
}).when(mockedOut).print(anyString());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(any());
Mockito.doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
printStream.append(invocation.getArguments()[0].toString()).append("\n");
return null;
}
}).when(mockedOut).println(anyString());
PrintStream originalOut = System.out;
System.setOut(mockedOut);
/* the actual test */
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
OrderedIntList.printList(list);
MatcherAssert.assertThat(printStream.toString(), is("[4]\n"));
/* Teardown - reset System.out */
System.setOut(originalOut);
}
Note that you probably want to extract the setup- and the teardown part to use it in other tests and to make your test readable. If I am not mistaken, JUnit provides functionality to add code that gets invoked before and after each test execution if you specify it with an #Before and #After annotation.
Obviously, you do not necessarily need Mockito to achieve this. You can also write a class that implements PrintStream and stores the printed strings. In this case, Mockito simply allows you to ignore all the methods you do not care about (i.e., you do not need to implement the whole PrintStream interface)
A small sidenote on the duplication of the stubing: We need to stub both methods, print and println, because both are used. Also, because of overriding, print(String x) is not the same as print(Object x), so we need to stub them both.
#Kulu Limpa answer is correct but much more complicated than the actual implementation, because you need some mocking.
if you refactor your code to
static void printList(OrderedIntList list) {
System.out.println(toString(list));
}
static String toString(OrderedIntList list) {
StringBuilder result = new StringBuilder();
System.out.println(toString(list));
result.append("[");
for (int i = 0; i < list.orderedIntegerList.length; i++) {
result.append(list.orderedIntegerList[i]);
if (i != list.orderedIntegerList.length - 1) {
result.append(", ");
}
}
result.append("]");
return result.toString();
}
testing should be much easier:
#Test
public void aListOfSizeOneShouldPrintTheElementWithinBrackets() {
ArrayList<Integer> listWithOneElement = new ArrayList<Integer>();
listWithOneElement.add(4);
OrderedIntList list = new OrderedIntList(listWithOneElement);
String result = OrderedIntList.toString(list);
MatcherAssert.assertThat(result, is("[4]"));
}
The library System Rules has a JUnit rule called StandardOutputStreamLog. With this rule you are able to test your code, that writes to System.out:
public void MyTest {
#Rule
public final StandardOutputStreamLog log = new StandardOutputStreamLog();
#Test
public void test() {
OrderedIntList list = ...
printList(list);
assertEquals("[1,2,3,4]", log.getLog());
}
}

good way to represent a excel sheet value in Java

Consider that I've a excel sheet in below format:
person
age
Foo
29
Bar
27
Now I want to read these values (using POI HSSF) and have to process them. What's the best way to do that?
Note that I do not have a Object Person in my application, becasue the values that may come in excel sheet is arbitrary (i.e. it may not be the person name and age). So, I need to use some kinda HashMap to store these values. In case multiple rows, is it good to have a List !?
public class Grid {
private Row headerColumns;
private List<Row> dataRows;
public Grid() {
dataRows = new LinkedList<Row>();
}
public Grid(int rowCount) {
dataRows = new ArrayList<Row>(rowCount);
}
public void addHeaderRow(List<String> headers) {
this.headerColumns = new Row(headers);
}
public void addDataRow(List<String> data) {
this.dataRows.add( new Row(data) );
}
public List<Row> getAllData() {
List<Row> data = new ArrayList<Row>(1+dataRows.size());
data.add(this.headerColumns);
data.addAll(dataRows);
return data;
}
public Row getHeaderColumns() {
return headerColumns;
}
public List<Row> getDataRows() {
return dataRows;
}
}
class Row {
private List<String> data;
public Row(List<String> data) {
this.data = data;
}
public void addColumn(String columnData) {
data.add(columnData);
}
public List<String> getData() {
return data;
}
}
If the format is defined, make a class that accomodates all those fields.
If the format isn't defined, pass Row-s around, or Lists, or even DOM from excel-to-dom transformation. You have no choice. I'd recommend just stick to POI's native Row and Cell objects.
Yes, you cannot use map if you have multiple key values. And i didn't find some build-in class for this issue. You can try write some kind of wrapper.
If you don't care of speed use simple 2D array like this:
String[][] filter = new String[initial width][initial height];
it can be Object instead of String;

Categories

Resources