How to iterate over child elements using TestObject as XPath envelope

I have made a demo at


How to run the demo

  1. download the zip file of this project from the Releases page, unzip it.
  2. start Katalon Studio, open the project
  3. open Test Cases/TC1_iterate_over_Katalon_Discussions, and run it with any browser

Input to the demo

The TestCase opens https://forum.katalon.com/discussions. There you will find a list of 37 discussions.

Output from the demo

The TestCase iterates over the list of discussions and print the titles like this:

10-07-2018 01:33:23 PM - [INFO]   - >>> 1: Visual Testing In Katalon Studio...10-07-2018 01:33:23 PM - [INFO]   - >>> 37: Query on: Running remotely and paralel thread, Merging teams code in Git,Ex/Import of KatalonProject

How the demo works

TestObjects made

  1. [Page_Recent Discussions/Content.ul_class-Disscussions] with xpath
    //div[@id='Content']/div/ul
  2. [Page_Recent Discussions/Content.(li_Item)] with xpath
    //li
  3. [Page_Recent Discussions/Content.(a_Title)] with xpath
    //div[contains(@class, 'Title')]/a

TestCase made

I made 1 TestCase TC1_iterate_over_Katalon_Discussions. I would copy its portion and past it here:

WebUI.navigateToUrl('https://forum.katalon.com/discussions')
WebDriver driver = DriverFactory.getWebDriver()// read XPath fragments
String ulSelector = 
    findTestObject('Object Repository/Page_Recent Discussions/Content.ul_class-Discussions').findPropertyValue('xpath')
String liSelector = 
    ulSelector + findTestObject('Object Repository/Page_Recent Discussions/Content.(li_Item)').findPropertyValue('xpath')

// obtain the number of Discussion rows
int rowCount = driver.findElements(By.xpath(liSelector)).size()
WebUI.comment(">>> rowCount=${rowCount}")// iterate over Discussions in the Forum

for (int pos = 1; pos <= rowCount; pos++) {
    // selector to the Title of each Discussion
    String titleSelector = liSelector + "[position()=${pos}]" +
        findTestObject('Object Repository/Page_Recent Discussions/Content.(a_Title)').findPropertyValue('xpath')
    TestObject to = new TestObject().addProperty('xpath', ConditionType.EQUALS, titleSelector)    
    WebUI.verifyElementPresent(to, 1)
    String title = WebUI.getText(to)
    WebUI.comment(">>> ${pos}: ${title}")
}
...

The following line is the core part of this script:

String liSelector = 
    ulSelector + 
    findTestObject('Object Repository/Page_Recent Discussions/Content.(li_Item)').findPropertyValue('xpath')
...
for (int pos = 1; pos < rowCount; pos++) {
    String titleSelector = 
        liSelector +
        "[position()=${pos}]" +
        findTestObject('Object Repository/Page_Recent Discussions/Content.(a_Title)').findPropertyValue('xpath')
    ...
}
...

Generated tilesSelectors will be as follows:

  • //div[@id='Content']/div/ul//li[position()=1]//div[contains(@class, 'Title')]/a
  • //div[@id='Content']/div/ul//li[position()=2]//div[contains(@class, 'Title')]/a
  • //div[@id='Content']/div/ul//li[position()=3]//div[contains(@class, 'Title')]/a
  • //div[@id='Content']/div/ul//li[position()=4]//div[contains(@class, 'Title')]/a
  • //div[@id='Content']/div/ul//li[position()=37]//div[contains(@class, 'Title')]/a

Conclusion

  1. In the demo I used TestObject just as an Envelope of XPath selector literal.
  2. TestObject is designed primarilly for the Katalon Studio features: “Record Web” and “Spy Web”. But you can modify/refactor the generated TestObject manually, and it is highly recommended.
  3. I had no XPath literals hard-coded and scattered in the sample TestCase scripts. All the XPath literals are externalized into the Object Repository. This would make code maintenance easier. It is good to have magical values centralized in the Object Repository. It would be nightmare if you scatter XPath literals all over the TestCase scripts.
  4. This sample shows you that you can introduce “searching for child elements” and “something dynamic” by a bit tricky coding. You construct XPath literals dynamically for yourself using the XPath fragments stored in the TestObjects as Envelope.

Beginners might not be able to use this approach, but well-trained programmers like you would easily see this idea.

Thanks to Marek Melocik for the original idea. It was posted at

4 Likes

super +1

In my case, I want to get the child data by using parent Index. So by updating TestObject property i.e.

String dynamicIdPath = “//android.widget.LinearLayout[contains(@index,‘2’)]/*”

child.addProperty(“xpath”,ConditionType.EQUALS,dynamicIdPath,true)

Its is not working in my case. Is there is any way to get child data using parent TestObject i.e. using index attribute

I am not capable of helping you as I have very little experience of Mobile testing. You may ask Mobile testing experts ( specifically @Chris_Trevarthen ) for help.

You shared just 2 lines of code fragment and wrote “it is not working”. That’s not enough. We can not see how your target application looks like. We can not see what you expected to see and what you actually saw. We need to see whole lines of your test script rather than 2 lines of code fragment. We need to see the log you got.

Please have a look at the following post and provide more information about your issue.

[TIP] How To Help Us Help You!

Hi @preeti.dodani,

The best way I’ve found to get a child element is to build on the xpath of its parent. I think you’re on the right path.

For some more info on xpath syntax, you can check out this site:

https://www.w3schools.com/xml/xpath_syntax.asp

You can also try out various xpaths against your document with this xpath tester:

https://www.freeformatter.com/xpath-tester.html

To get the XML as Katalon/Appium sees it, you can follow these instructions:

Hope this helps,

Chris