Problematic parsing of html table with selenium webdriver - java

I am using selenium webdriver with java to test a web application in my company and I face a very strange problem. The web application after logging in displays this table with the values as shown in the picture in the link below:
https://drive.google.com/file/d/0B0i_2gNTlx1Sek9EQVQ1ZlY1a0E/view?usp=sharing
I have wrote this code that parses the table with xpath because the table's rows and td cells are id-less.
//Parsing the table.
int increment = 0;
int i = 0;
for(increment=1; increment <= 16; increment++){
StringBuilder nsb = new StringBuilder("");
StringBuilder sb = new StringBuilder("");
for(i=1; i <= 6; i++){
try {
WebElement f = wd.findElement((By.xpath("/html/body/div[1]/div/div[2]/div/div[2]/div[2]/div[2]/div/div[1]/form/div/div/table/tbody/tr["+increment+"]/td["+i+"]")));
sb.append(f.getText().replaceAll("\\n", " ")).append(" ");
} catch (StaleElementReferenceException ed) {
ed.getSuppressed();
}
}
System.out.println(sb);
}
System.out.println();
The problem now is that when I print the values of each row sometimes and in random order i lose some of the values on the output as shown in the picture i post below(for example if i re-run the program the second field in the second row called SAB will be missing).
Correct output is
https://drive.google.com/file/d/0B0i_2gNTlx1SQmFoZDd0UkgzVXM/view?usp=sharing
I tried instead of getText method the getAttribute("textContent") but i face the same random problem.
Does anyone have any idea why is this happening?
Sorry for the links but I didn't have any alternative to show you my problem..I can also post a random faulty output I got during testing if it's needed..

One thought,
why did you add ?
catch (StaleElementReferenceException ed) {
ed.getSuppressed();
}
Are you getting this exception if not catching?
if yes, then
might be your page or element is getting refreshed
and when you are referring f on second line to getText() you may get StaleElementReferenceException, But as you are suppressing it your loop continues and value is lost because of exception.
you can try replacing
WebElement f = wd.findElement((By.xpath("/html/body/div[1]/div/div[2]/div/div[2]/div[2]/div[2]/div/div[1]/form/div/div/table/tbody/tr["+increment+"]/td["+i+"]")));
sb.append(f.getText().replaceAll("\\n", " ")).append(" ");
with single statement
sb.append(wd.findElement((By.xpath("/html/body/div[1]/div/div[2]/div/div[2]/div[2]/div[2]/div/div[1]/form/div/div/table/tbody/tr["+increment+"]/td["+i+"]"))).getText().replaceAll("\\n", " ")).append(" ");
Probably this will avoid staleElement Exception if issue is caused by it.

Related

Not catching NoSuchElementException

I am scraping fixtures of one website and then using another website to check each team's form. The issue I am having is that not all teams exist on the form website and I am getting a NoSuchElementException for the teams whose xPath clearing doesn't exist on the URL not found page. I am trying to catch the exception but the program still breaks.
I have added a try catch but it doesn't solve my problem, the program breaks as soon as it arrives as a non-found team.
for(int i = 0; i < fixtures.getAwayTeams().size(); i++)
{
driver.navigate().to(FORMURL.concat( (fixtures.getAwayTeams().get(i)).replace( ' ', '+' )));
for (int j = 1; j < 11; j++) {
String xPath = FORMXPATHONE.concat( String.valueOf( j ) ).concat(FORMXPATHTWO);
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xPath)));
forms = driver.findElementsByXPath( xPath );
} catch(NoSuchElementException | StaleElementReferenceException e) {
awayTeamForm.add("No Form for Team");
}
for (WebElement languageElement : forms) {
ArrayList <String> wld = new ArrayList<String>();
wld.add( languageElement.getText() );
String listedForm = String.join(",", wld );
awayTeamForm.add(listedForm);
}
}
}
}
Caused by: org.openqa.selenium.NoSuchElementException: Unable to locate element: //*[#id="results"]/table/tbody/tr[1]/td[6]
You can check that the element is present on the page or not by first fetching the element list and then checking the size of that list, if its greater than 0 then the element is present else the element is not present on the page. By this you don't need to catch the exception as well.
You can do it like:
List<WebElement> elementList = driver.findElements(By.xpath("xPath"));
if(elementList.size()>0){
// Element is present
}
else{
// Element is not present
}
Your try-catch statement looks fine. Which means, the issue has to be somewhere else.
You are using selenium, which means there are two Exceptions called NoSuchElementException available. Check your imports. Most likely the problem you have is, that you do import java.util.NoSuchElementException instead of org.openqa.selenium.NoSuchElementException
Try catch the whole loop body and debug to see if you are catching the right exception and on the right line.
Are you sure that only
forms = driver.findElementsByXPath( xPath );
can raise the exception?
try this :
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(xPath)));
forms = driver.findElementsByXPath( xPath );
} catch(NoSuchElementException | StaleElementReferenceException | TimeoutException e) {
awayTeamForm.add("No Form for Team");
}

BigQuery Pagination through large result set with cloud library

I am working on accessing data from Google BigQuery, the data is 500MB which I need to transform as part of the requirement. I am setting Allow Large Results, setting a destination table etc.
I have written a java job in Google's new cloud library since that is recommended now - com.google.cloud:google-cloud-bigquery:0.21.1-beta (I have tried 0.20 beta as well without any fruitful results)
I am having problem with pagination of this data, the library is inconsistent in fetching results page wise. Here is my code snippet,
Code Snippet
System.out.println("Accessing Handle of Response");
QueryResponse response = bigquery.getQueryResults(jobId, QueryResultsOption.pageSize(10000));
System.out.println("Got Handle of Response");
System.out.println("Accessing results");
QueryResult result = response.getResult();
System.out.println("Got handle of Result. Total Rows: "+result.getTotalRows());
System.out.println("Reading the results");
int pageIndex = 0;
int rowId = 0;
while (result != null) {
System.out.println("Reading Page: "+ pageIndex);
if(result.hasNextPage())
{
System.out.println("There is Next Page");
}
else
{
System.out.println("No Next Page");
}
for (List<FieldValue> row : result.iterateAll()) {
System.out.println("Row: " + rowId);
rowId++;
}
System.out.println("Getting Next Page: ");
pageIndex++;
result = result.getNextPage();
}
Output print statements
Accessing Handle of Response
Got Handle of Response
Accessing results
Got handle of Result. Total Rows: 9617008
Reading the results
Reading Page: 0
There is Next Page
Row: 0
Row: 1
Row: 2
Row: 3
:
:
Row: 9999
Row: 10000
Row: 10001
:
:
Row: 19999
:
:
Please note that it never hits/prints - "Getting Next Page: ".
My expectation was that I would get data in chunks of 10000 rows at a time. Please note that if I run the same code on a query which returns 10-15K rows and set the pageSize to be 100 records, I do get the "Getting Next Page:" after every 100 rows. Is this a known issue with this beta library?
This looks very close to a problem I have been struggling with for hours. And I just found the solution, so I will share it here, even though you probably found a solution yourself a long time ago.
I did exactly like the documentation and tutorials said, but my page size were not respected and I kept getting all rows every time, no matter what I did. Eventually I found another example, official I think, right here.
What I learned from that example is that you should only use iterateAll() to get the rest of the rows. To get the current page rows you need to use getValues() instead.

for-loop doesn't work in android try-catch block

I am making database of my school's building and classroom with Realm. But, 'for-loop' in try-catch doesn't work:
public void startCheckRealm() {
// Writing DataBase with Realm
try {
Log.d("Realm", "Init");
InitializeAPI.init_BuildingRoom(getActivity().getApplicationContext());
Log.d("Realm", "Complete");
} catch(Exception e) {
e.printStackTrace();
}
// Trying to check the Database whether it is right or wrong
try {
Log.d("Realm Test", "2nd Try Catch");
Realm.init(getActivity().getApplicationContext());
Realm realm = Realm.getDefaultInstance();
RealmResults<BuildingList> buildingLists = realm.where(BuildingList.class).findAllSorted("buildingCode");
int totalNumber = 0;
for(int i = 0; i < buildingLists.size(); i++) {
Log.d("For", "index = " + i);
RealmResults<RoomList> rooms = buildingLists.get(i).getRoomList().sort("roomCode");
String BuildingName = buildingLists.get(i).getBuildingName();
String BuildingCode = buildingLists.get(i).getBuildingCode();
for(int idx = 0; idx < rooms.size(); idx++) {
totalNumber++;
String RoomCode = rooms.get(idx).getRoomCode();
String RoomName = rooms.get(idx).getRoomName();
Log.d("Realm Test", "Number :: " + String.valueOf(totalNumber) + " BuildingCode :: " + BuildingCode + "\t\t BuildingName :: " + BuildingName + "\t\t RoomCode :: " + RoomCode + "\t\t RoomName :: " + RoomName);
}
}
Log.d("Realm Test", "2nd Try Catch Complete + " + String.valueOf(totalNumber));
} catch(RealmException e) {
e.printStackTrace();
}
}
In the first try-catch, the method, which does making database, is complete without Exception. I was curious whether this database is right or wrong.
So, in 2nd try-catch, I was trying to check realm files with queries.
The problem is "for-loop" doesn't work in 2nd try-catch. Below snippet is my logcat.
D/Realm: Init
I/System.out: bdList getLength :: 52
I/System.out: roomList getLength :: 2376
D/Realm: Complete
D/Realm Test: 2nd Try Catch
D/Realm Test: 2nd Try Catch Complete + 0
I want to check my realm data with Log but, doesn't work as you can see.
If there is no problem, the logcat shows lots of my building and room lists and ends with "D/Realm Test: 2nd Try Catch Complete + 2376".
Could you explain the reason why it doesn't work? I cannot understand the reason why it doesn't work even though there is no Exception.
While in your use-case this doesn't pose a problem, when you're iterating a RealmResults inside a transaction, the results are live in every version <= 0.88.3 and >= 3.0.0.
So in that case,
RealmResults<BuildingList> buildingLists = realm.where(BuildingList.class).findAllSorted("buildingCode");
for(int i = 0; i < buildingLists.size(); i++) {
BuildingList buildingList = buildingLists.get(i); // <-- !!!
will fail (it will skip every second item!)
So you should use iterators instead (3.0.0+! on <= 0.88.3 you'd do reverse iteration)
RealmResults<BuildingList> buildingLists = realm.where(BuildingList.class).findAllSorted("buildingCode");
for(BuildingList buildingList : buildingLists) { // <-- !!!
The reason why this works is because iterators by default create a new snapshot collection (3.0.0+), and iterating by index on a snapshot also works
OrderedRealmCollection<BuildingList> snapshot = buildingLists.createSnapshot();
for(int i = 0; i < ...
Simple: there is no exception thrown; and you only have your print statements inside the loop.
Thus the one and only conclusion: at that point in time when your for loops are executed, the corresponding list is empty. Therefore the loop body is not entered; nothing gets printed. And that has nothing to do with the fact that this loop is within a try-catch block.
That is all there is to this. So, the direct answer is: print the list size directly in front of the loop to avoid such surprises.
(of course, the interesting part is to understand what happens to the list which seems to be non-empty earlier on - but in order to debug that, you would have to add more of your code).
Two inputs:
1.Haven't used realm but looks like the syntax for getting sorted entriesis a bit different Official documentation
2.If the above point is wrong than from your code it looks like buildingList size is zero. Have you tried checking the size?
Let me know the results.
Try logging your catch block. Chances are the rest of the code including the loop didn't complete because your app was caught with the Exception.
You should debug buildingLists.size(); before for loop
Log.d("Building List Size ", buildingLists.size()+"");
In that case you can find the value of buildingLists.size();

I am trying to select a value which is in the 2nd index from dropdown and compare it with the value fetched from excel

List <WebElement> elementCount = dropdown.getOptions();
System.out.println(elementCount.size());
for(int i=0;i<elementCount.size();i++)
{
System.out.println("Value of i is: "+i);
WebDriverWait wait = new WebDriverWait(dri10,500+(elementCount.size()*500));
WebElement element1 = wait.until(ExpectedConditions.elementToBeClickable(By.id("Select Role")));
dropdown.selectByIndex(i); //when the value of i becomes 2 an exception is displayed
Thread.sleep(100+(elementCount.size()*400));
String approle=dri10.findElement(By.id("Select Role")).getText();
String assigrole=s1.getCell(3,16).getContents(); //Fetching data from excel
if(approle.equals(assigrole))
{
dri10.findElement(By.id("Submenu")).click();
}
}
Exception Details: org.openqa.selenium.StaleElementReferenceException: Element not found in the cache - perhaps the page has changed since it was looked up
Command duration or timeout: 146 milliseconds
This exception is thrown when there are js updates on your element.
To avoid this exception, I usually surround my code with :
try{
//some code
}catch (StaleElementReferenceException e){
//retry it
}
I created some functions to avoid it. You can retry multiple time if the app is calling js multiple time also.

Search an element in all pages in Selenium WebDriver (Pagination)

I need to search for particular text in a table on all the pages. Say i have got to search for text (e.g : "xxx") and this text is present at 5th row of table on 3rd page.
I have tried with some code :
List<WebElement> allrows = table.findElements(By.xpath("//div[#id='table']/table/tbody/tr"));
List<WebElement> allpages = driver.findElements(By.xpath("//div[#id='page-navigation']//a"));
System.out.println("Total pages :" +allpages.size());
for(int i=0; i<=(allpages.size()); i++)
{
for(int row=1; row<=allrows.size(); row++)
{
System.out.println("Total rows :" +allrows.size());
String name = driver.findElement(By.xpath("//div[#id='table']/table/tbody/tr["+row+"]/td[1]")).getText();
//System.out.println(name);
System.out.println("Row loop");
if(name.contains("xxxx"))
{
WebElement editbutton = table.findElement(By.xpath("//div[#id='table']/table/tbody/tr["+row+"]/td[3]"));
editbutton.click();
break;
}
else
{
System.out.println("Element doesn't exist");
}
allpages = driver.findElements(By.xpath("//div[#id='page-navigation']//a"));
}
allpages = driver.findElements(By.xpath("//div[#id='page-navigation']//a"));
driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
allpages.get(i).click();
}
Sorry, i missed to describe the error. Well this code gets executed properly, it checks for element "xxx" on each row of every page and clicks on editbutton when its found.
After that it moves to
"allpages.get(i).click();" // code is for click on pages
But its unable to find any pagination, so it displays error of "Element is not clickable at point (893, 731). Other element would receive the click...."
For every page loop you use one table WebElement object. So I assume that after going to the next page you get StaleElementReferenceException. I guess the solution could be with defining table on every page loop. Move this line List<WebElement> allrows = table.findElements(By.xpath("//div[#id='table']/table/tbody/tr")); after for(int i=0; i<=(allpages.size()); i++) too
EDIT: And, btw, at this line allpages.get(i).click() I think you must click the next page link, not the current one as it seems to be

Categories

Resources