I am writing a code wherein I am operating with an excel file having three sheets. I am using Apache POI and Data provider annotation for data driven approach. I wanted to pass Sheet index number or Sheet name at run time but I was not able to do it setting a parameter to data provider method. So what I did is I wrote a constructor and a static variable as integer. In parameterized constructor, I initialized that static variable and then in my test case, by creating object of the class which had data provider method, I passed an integer that is, sheet index from which I wanted the data to be taken to run the test. But every time, the constructor is taking value as 0. I don't know why. Below is the data driven code and constructor I have written.
public class Excel_Util {
static int fileinitial;
public Excel_Util(int filename) {
fileinitial=filename;
}
@DataProvider(name="testdata")
public static Object[][] readexcelretobj() throws Exception {
FileInputStream f= new FileInputStream("F:\\Eclipse Java new Programs\\shdtestpeopleinteractive\\src\\test\\resources\\Test_data.xls");
HSSFWorkbook workbook = new HSSFWorkbook(f);
HSSFSheet s = workbook.getSheetAt(fileinitial);
HSSFRow row = s.getRow(0);
int rownum=s.getPhysicalNumberOfRows();
int colnum=row.getLastCellNum();
//System.out.println(rownum);
//System.out.println(colnum);
Object data[][] = new Object[rownum][colnum];
List<Object> l = new ArrayList<Object>();
for(int i=0;i<rownum-1;i ) {
row = s.getRow(i 1);
for(int j=0;j<colnum;j ) {
HSSFCell c = row.getCell(j);
//l.add(c.getStringCellValue());
data[i][j]=c.getStringCellValue();
}
}
return data;
}
The test case which I wrote is as follows.
@Test(dataProvider="testdata",dataProviderClass=Excel_Util.class)
public void testsignupdatafields(String email, String password) {
Syncutil.Implicitwait();
try {
Excel_Util ex = new Excel_Util(2);
getdriver().get("https://www." csvreaderutil.csvread().get(0).toString() "/");
Marathishd marathishdpage = PageFactory.initElements(getdriver(), Marathishd.class);
Signuppagemarathishd signup = marathishdpage.letsbeginclick();
signup.emailid.sendKeys(email);
signup.password.sendKeys(password);
}catch(Exception e) {System.out.println("Exception");}
}
}
Here, I have passed 2 at the time of object creation but every time, the values are taken from the first sheet. That is, sheet index 0 is considered every time. I don't want to hard code any value in excelutil class code as I wanted to behave it as generic code. So in test case itself I decided to pass sheet number. I am confused what to do and wanted a reason why this is happening and what is the mistake I am doing. Can anyone please guide me with this ?
CodePudding user response:
I simplified the code to replicate the issue.
Existing code :
@Test
method:
@Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
public void testsignupdatafields(String email, String password) {
System.out.println("Test started");
new Excel_Util(2);
System.out.println("Email: " email " & Passowrd: " password);
}
Excel_Util
:
public class Excel_Util {
static int fileinitial;
public Excel_Util(int filename) {
fileinitial = filename;
System.out.println("Constructor called...");
System.out.println("Sheet number: " fileinitial);
}
@DataProvider(name = "testdata")
public static Object[][] readexcelretobj() throws Exception {
Object[][] object = new Object[1][2];
object[0][0] = "Nandan";
object[0][1] = "123456";
System.out.println("Data provider called...");
System.out.println("Sheet number: " fileinitial);
return object;
}
}
Output:
Data provider called...
Sheet number: 0
Test started
Constructor called...
Sheet number: 2
Email: Nandan & Passowrd: 123456
If you see the above output the DataProvider
code is being called first so your value is passing as 0
. To fix this call the new Excel_Util(2);
object into DataProvider
Updated code :
@Test
method:
@Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
public void testsignupdatafields(String email, String password) {
System.out.println("Test started");
System.out.println("Email: " email " & Passowrd: " password);
}
Excel_Util
:
public class Excel_Util {
static int fileinitial;
public Excel_Util(int filename) {
fileinitial = filename;
System.out.println("Constructor called...");
System.out.println("Sheet number: " fileinitial);
}
@DataProvider(name = "testdata")
public static Object[][] readexcelretobj() throws Exception {
new Excel_Util(2);
Object[][] object = new Object[1][2];
object[0][0] = "Nandan";
object[0][1] = "123456";
System.out.println("Data provider called...");
System.out.println("Sheet number: " fileinitial);
return object;
}
}
Output:
Constructor called...
Sheet number: 2
Data provider called...
Sheet number: 2
Test started
Email: Nandan & Passowrd: 123456
If you see the above output now the constructor is being called first.
Solution#1:
As we discussed if you want to pass the value from Test
class then you can do something like this. Instead of a constructor
use static
block.
Test
class:
public class ClassTestNG {
static int sheetNumber = 2;
@Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
public void testsignupdatafields(String email, String password) {
System.out.println("Test started");
System.out.println("Email: " email " & Passowrd: " password);
}
Excel_Util
:
public class Excel_Util {
static int fileinitial;
static {
fileinitial = ClassTestNG.sheetNumber;
System.out.println("Static called...");
System.out.println("Sheet number: " fileinitial);
}
@DataProvider(name = "testdata")
public static Object[][] readexcelretobj() throws Exception {
Object[][] object = new Object[1][2];
object[0][0] = "Nandan";
object[0][1] = "123456";
System.out.println("Data provider called...");
System.out.println("Sheet number: " fileinitial);
return object;
}
}
Output:
Static called...
Sheet number: 2
Data provider called...
Sheet number: 2
Test started
Email: Nandan & Passowrd: 123456
Solution#2:
You can use @BeforeTest
annotation as well.
Test
class:
@BeforeTest
public void passSheetNumber() {
new Excel_Util().assignSheetNumber(2);
}
@Test(dataProvider = "testdata", dataProviderClass = Excel_Util.class)
public void testsignupdatafields(String email, String password) {
System.out.println("Test started");
System.out.println("Email: " email " & Passowrd: " password);
}
Excel_Util
:
public class Excel_Util {
static int fileinitial;
public void assignSheetNumber(int sheetNumber) {
fileinitial = sheetNumber;
System.out.println("Sheet number: " fileinitial);
}
@DataProvider(name = "testdata")
public static Object[][] readexcelretobj() throws Exception {
Object[][] object = new Object[1][2];
object[0][0] = "Nandan";
object[0][1] = "123456";
System.out.println("Data provider called...");
System.out.println("Sheet number: " fileinitial);
return object;
}
}
Output:
Sheet number: 2
Data provider called...
Sheet number: 2
Test started
Email: Nandan & Passowrd: 123456
CodePudding user response:
fileinitial=filename; It's a wonder you did not get an error message about a static int cannot be assigned from a non static context! Why not simply take static off your global fileinitial. *NB the class with the int problem were the main class and if you were calling from public static void main(String args[]) that would be different and not require assigning by the constructor, so if it is not the main class remove static keyword from variable "fileinitial".
Or build a static class (always nested subclass) to send the "non static filename argument" into (through) a static method and return it as static assignment from that method.