1

I am using Selenium to write unit tests for a website to test scientific software. The backend uses Flask to generate a sidebar where each project is clickable with a dropdown menu. You can only open one of the project tabs at once.

I want to loop through the projects in this sidebar and verify that following each of this links generates the correct message (this could be a 403). I am new to Selenium.

This is a MWE of the compiled HTML from Flask (it's quite condensed so please forgive any syntax errors)

<!-- One element from the list -->
<li class="treeview"> <!-- Main Heading -->
  <a href="#">
    <i class="fa fa-code"></i>
    <span name='lst_project_name'>Project1</span>
  </a>
  <ul class="treeview-menu"> <!-- Submenu, visible when clicked -->
    <li><a href="https://git.example.org/project1/code">Gitlab (External)</a></li>
    <li><a href="/4/edit">Edit Project</a></li>
    <li><a href="/4/new_test_session">Submit New Test</a></li>
  </ul>
</li>

<!--- And a second (its identical) -->
<li class="treeview">
  <a href="#">
    <i class="fa fa-code"></i>
    <span name='lst_project_name'>Project1</span>
  </a>
  <ul class="treeview-menu">
    <li><a href="https://git.example.org/project1/code">Gitlab (External)</a></li>
    <li><a href="/4/edit">Edit Project</a></li>
    <li><a href="/4/new_test_session">Submit New Test</a></li>
  </ul>
</li>

At the moment I am interested in the 'Submit New Test' button, but it is hidden until I click on the project. I think I would like a loop of the form

listed_projects = driver.find_elements_by_name("lst_project_name")
for project in listed_projects:
  project.click()
  el = driver.find_element_by_xpath("//a[contains(text(),'Submit New Test')]")
  el.click()
  heading1 = driver.find_element_by_tag_name('h1')
  self.assertEqual(heading1.text,'Not Allowed')
  driver.back()

But this won't work for a few reasons, my main tripping point is that the xpath simply finds the first element. Is there any way to get xpath to search relative to a clicked element? I could use a list elements returned by an xpath query, but then the element I need to click isn't visible.

Also, once I leave the webpage, how do I access the second item in the list.

This question is pretty similar, Click submenu which is dynamicly visible in Selenium WebDriver, I liked the arrow keys solution, but, they don't work in my case. I can edit the source html to fit the test.

1 Answer 1

1

You can locate whole list of elements (like all <li> elements inside treeview_menu class, using CSS locators), loop over them, test other attributes (like .text), and .click() on the item you want. I do it all the time, it is much more robust than creating and maintaining complex XPATH expressions.

You can edit source. Give all submenu items the same name: easy to locate, easy to loop over.

With python, you can drop to debugger with just single line import pdb;pdb.set_trace() just after you located the list, so you can poke around to see what was located and how useful it was. This speeds the code development immensely: I don't waste time crafting XPath, I prefer to spend time in Python, which I mastered to higher level. I love Python, because it saves me lots of time.

BTW what you are writing are UI/integration/system tests. Real unit test will test the internal calls to the system libraries, and you should spend 80% of time on those, as explained recently in answers about test pyramid

2
  • To expand in case anyone else gets stuck on here I used a common name for each submenu and a unique ID. By finding all elements with a name and then storing their ID's I was able to later find the element I was working with once the page had refreshed.
    – Aaron
    Apr 24, 2018 at 16:16
  • @Aaron - exactly. Much more robust than complicated Xpath, isn't it? Apr 24, 2018 at 17:10

Your Answer

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

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