Search code examples
seleniumtestngindexoutofboundsexceptiondata-driven-tests

Unable to read all the data existing in excel sheet using Java/Selenium script


I'm facing an issue with reading the data from an excel file (which basically contains the login credentials in the form of test data) particularly when I am using TestNG. The same code works fine when I run it as a normal java program:

Issue Details: [Utils] [ERROR] [Error]
java.lang.ArrayIndexOutOfBoundsException: 2

Here is the code below:

Note:
a. I read the data from the excel file and then pass it onto the test method via DataProvider annotation. b. Excel contains two columns namely username and password

FetchData.java:

enter code here

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class FetchData {

public Object[][] getData() throws EncryptedDocumentException,
        InvalidFormatException, IOException {
    FileInputStream fis = new FileInputStream(
            "E:\\test.xlsx");
    Workbook wb = WorkbookFactory.create(fis);
    Sheet sh = wb.getSheetAt(0);

    int rowCount = sh.getLastRowNum();
    int colCount = sh.getRow(0).getLastCellNum();

    System.out.println("Row Count: " + rowCount);
    System.out.println("Column Count: " + colCount);

    Object[][] data = new Object[rowCount][colCount];

    for (int i = 0; i <= rowCount; i++) {
        for (int j = 0; j < colCount; j++) {

            data[i][j] = sh.getRow(i).getCell(j).getStringCellValue();
            System.out.print(data[i][j] + "\t");

        }
        System.out.println();
    }
    return data;
}

}

LoginTests.java(Test Class--TestNG):

import java.io.IOException;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.openqa.selenium.By;
import org.openqa.selenium.PageLoadStrategy;
import org.openqa.selenium.UnexpectedAlertBehaviour;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class LoginTests {

static WebDriver driver;
ChromeOptions options;
FetchData fd;

@BeforeMethod
public void setUp() {

}

@DataProvider
public Object[][] testData() throws EncryptedDocumentException,
        InvalidFormatException, IOException {
    fd = new FetchData();
    Object[][] data = fd.getData();
    return data;
}

@Test(dataProvider = "testData")
public void test(String username, String password) {
    System.setProperty("webdriver.chrome.driver",
            "E:\\chromedriver.exe");
    options = new ChromeOptions();
    options.addArguments("--start-maximized");
    driver = new ChromeDriver(options);
    driver.get("https://www.facebook.com");

    WebElement uname = driver.findElement(By
            .xpath("//input[@type='email']"));
    WebElement pwd = driver.findElement(By
            .xpath("(//input[@type='password'])[1]"));
    WebElement submit = driver.findElement(By
            .xpath("//input[@value='Log In']"));

    uname.sendKeys(username);
    pwd.sendKeys(password);
    submit.click();

}

}

Solution

  • You have created data object using rowCount and colCount.

    Object[][] data = new Object[rowCount][colCount];
    

    But in the for loop condition is added like for (int i = 0; i <= rowCount; i++).So, this loop will try to execute one more time and hence ArrayIndexOutOfBoundsException is throwing.

    Please change the condition as below

    for (int i = 0; i < rowCount; i++) 
    

    For Example, If the excel has only three rows and 2 columns, then data Object will be created as Object[][] data = new Object[3][2];. It can hold maximum of 3 rows. But the first for loop will be executed from index 0 to 3 (Totally 4 rows). When it tried to insert 4th row record, then ArrayIndexOutOfBoundsException is throwing.

    Modified Code:

    Object[][] data = new Object[rowCount][colCount];
    
    for (int i = 0; i < rowCount; i++) {
        for (int j = 0; j < colCount; j++) {
    
            data[i][j] = sh.getRow(i).getCell(j).getStringCellValue();
            System.out.print(data[i][j] + "\t");
    
        }
        System.out.println();
    }
    

    Edit:

    getLastRowNum() method is 0 based.Refer the Doc. So, you need to modify your code as below in order to get all the rows data without an ArrayIndexOutOfBoundsException

    Modified Code:

    //Rowcount+1 needs to be added inorder to read the last row
    Object[][] data = new Object[rowCount+1][colCount];
    
    for (int i = 0; i <= rowCount; i++) {
        for (int j = 0; j < colCount; j++) {
    
            data[i][j] = sh.getRow(i).getCell(j).getStringCellValue();
            System.out.print(data[i][j] + "\t");
    
        }
        System.out.println();
    }