0

So here's the setup, we have tests where we fetch test data from excel sheet and iterate over all the rows within a particular test. So, for example, there are tests that create some user profiles, once they do; there's a success message that appears on the next page, our test uses the "findElement.." method to capture that element and get's the text to verify that 1) it appears and 2) that the message is correct. Now here's the problem, since the test may iterate over and over a lot (because of excel data rows), every so often we notice that the test throws NoSuchElementException while looking for that success message. I was recently told by someone that instantiating that page object class at each iteration would solve this issue. So my main question really is that would instantiating the page object class solve this, or is there something else I'm missing? Following is a sample of the code (not exact code of course)

    SuccessPage successPage = new SuccessPage(driver);
    InputPage inputPage = new InputPage(driver);
    String successMessage = "";
    excelSheetData = someCustomMethodThatFetchesDataFromExcel();
    for (Map<String, String> rows : excelsheetData){
      inputPage.inputElement1.sendKeys(rows.get("columnName1"));
      inputPage.inputElement2.sendKeys(rows.get("columnName2"));
      inputPage.buttonElement.click();
      wait.until(ExpectedConditions(visibilityOf(successPage.successEle)));
      successMessage = successPage.successEle.getText();
      Assert.assertEquals(expectedSuccessMessage, successMessage);
    }

Page object file look something like this

    public class SuccessPage {
    WebDriver driver;
       public SuccessPage(WebDriver driver){
          this.driver = driver;
       }
    @FindBy("someLogicalName")
    public WebElement someElement;

So roughly about 8 out of 10 times the above code works correctly, but those two other times it throws that NoSuchElementException at successMessage = successEle.getText(); What I've been told I should do instead is something like the following

    SuccessPage successPage;
    for(....
      ...
      //create a wrapper clickSubmitBtn() method that returns the page object.
      successPage = inputPage.clickSubmitBtn(driver); //this will instantiate the page object.
      successMessage = successpage.successEle.getText();
      ... }

So,

  1. will this really solve the problem?
  2. is that a good programming practice, should instantiation be done once before the loop?
7
  • I only reinstantiate a page class if I have reason to believe that something has changed since the last instance. It doesn't look like you pass the webdriver instance to your web class, perhaps you should show one of your page class' code. How a page class is initialized can make a big difference. Add it to your original post, please. Commented Sep 20, 2018 at 17:47
  • Hi @BillHileman added the stuff you mentioned. For berevity's sake I left it out earlier, ignoring the fact that that's quite important to know as well.
    – D S
    Commented Sep 21, 2018 at 12:26
  • Are you not using pagefactory? Typically the page would be initialized in the constructor. There are also different ways to initialize the page. Commented Sep 21, 2018 at 12:59
  • Yes, pagefactory is being used in the background as well
    – D S
    Commented Sep 21, 2018 at 13:42
  • In your page class, after the this.driver = driver you should call the pagefactory, and I do mine this way: PageFactory.initElements(new AjaxElementLocatorFactory(driver, 15), this); which gives an implicit wait for elements of 15 seconds. Commented Sep 21, 2018 at 14:12

1 Answer 1

1

Taking your questions in order:

  1. I do not think, changing the structure of your code is going to resolve the issue. In most cases where the tests fail intermittently, the problem will be with some timing issue. Something like the click is not registering. Check your browser console for any errors in the javascript. Try adding some delay after sendKeys().

  2. Most good programming practices are suggestions - without looking at the whole structure it will not be possible to give them :).

1
  • 2
    To add to @Dakshinamurthy's answer, the time between the .click() and the .getText() might not be allowing time for the UI to render the change. Test it is a timing issue by adding a Sleep(), if the flakiness goes away then I would replace the Sleep() with an explicit wait.
    – kirbycope
    Commented Sep 20, 2018 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.