As a member of the SQA Automation team, Marian’s job is to investigate an application that is constantly under development. Most of the time, this implies testing dynamically generated elements.
Due to his experience in using Selenium WebDriver and WebDriverWait for testing such apps, Marian decided to detail how these two solutions simplify testing, hoping that it would help other SQA automation software engineers in their job.
Dynamic applications
Web page elements usually have unique identifiers that help localizing them inside the page. They are implemented using the attributes of HTML tags ID or Name. These attributes can be static, which makes testing very easy. 🙂
However, recent trends forced these attributes to be dynamically generated. This is common for JavaScript applications, for example, the id AU87Dj1VKJasd710N varies, depending on the new elements created in the application.
About Selenium
Selenium WebDriver is an open source-project for testing web applications in different browsers, using different programming languages that allow the automation of browser controls. Selenium’s goal is to supply a well-designed object-oriented API that provides improved support for modern advanced web-app testing.
Hurdle
Testing a dynamic web application gets difficult when repetitive tasks that should be automated do not always receive the same parameters. As a result, the elements that should be transmitted towards these tasks change from one test to the next. This happens because dynamic web applications are database-driven. Every time an element is updated in the database, it affects one or several areas of the application. Still, it’s not like these elements cannot be identified and controlled. 😉
Another difficulty often encountered in web apps is the amount of time you need to wait for the page content to load. Elements only appear after the execution the JavaScript code and after receiving an answer from the server. This time interval cannot be determined because various unexpected events may occur while executing the app. The tests are designed to be run one after another. As soon as one test ends, another test starts without waiting for the HTML elements of the page to load. This will eventually make the tests fail.
Solutions
Selenium efficiently solves all the problems presented above.
Using locators
The WebDriver provides a locator for identifying dynamically generated elements of the same type within a web page. There are 8 types of locators: Id, Name, Identifier, DOM, Link Text, Xpath, CSS, UI.
Using the correct locator ensures faster and reliable tests that can be more easily maintained during app development or frequent app releases. For testing automation you can work only with IDs and Names – they make your work a whole lot easier.
- ID – select element with the specified @id attribute
- Name – select first element with the specified @name attribute
- Identifier – locate element using a tag name
- DOM – locate elements that match a JavaScript expression
- Link Text – select link element which specifies link text
- Xpath – locate an element using an XPath expression
- CSS – select element using CSS selectors
- UI – select well defined element.
Sometimes, choosing a locator can become a nightmare, because there’s no way to tell if it’s the optimal locator or if it will simply disappear during testing. That is why the most frequently used method for identifying dynamic elements implies searching the list of elements for a static locator and then verifying the dynamic attributes, as shown in the example below.
List elements = driver.findElements(By.class("hg-avatar")); for(WebElement element : elements) { System.out.println(String.format("ID of the avatar is: %s", element.getAttribute("id")); element.click(); }
Implicit Wait vs Explicit Wait
Sometimes a new element used in the test cannot be identified. For such situations, Selenium developed WebDriverWait. Since the elements are updated in DOM without reloading the web page, it is recommended to verify a condition every time an element has been modified – either by waiting for a certain amount of time (Implicit Wait), or by checking every second that the condition is met, before following the next step in the script (Explicit Wait).
The Implicit Wait method tells the WebDriver to wait for a certain amount of time, whenever it tries to find one or several elements that are not immediately available, lest an exception is returned. The default value is 0.
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.get("http://demo.hubgetscom/hubgets); WebElement dynamicElement = driver.findElements(By.class("hg-avatar"));
The Explicit Wait method implies waiting for a certain condition to be met before continuing the script. The worst choice would be Thread.sleep (), which waits for the condition to be met only for a limited amount of time. Then there is this more efficient method, which implies waiting for the condition to be met for as long as necessary. The latter requires using both WebDriverWait and ExpectedCondition.
WebDriverWait wait = new WebDriverWait(driver, waitTime); wait.until(ExpectedConditions.presenceOfElementLocated(locator));
The ExpectedCondition Class
The ExpectedCondition class pretty much covers everything, as it helps reducing execution time for tests and finding all the dynamic elements in a page.
Here are the methods of the ExpectedCondition class:
- alert_is_present – expect for an alert to occur (No parameter)
- element_located_selection_state_to_be – expect to locate the element and check if the selection state specified is in that state (param: locator, is_selected)
- element_located_to_be_selected – expect to select the element to be located (param: locator)
- element_selection_state_to_be – expect to check if the given element is selected (param: element, is_selected)
- element_to_be_clickable – expect for the element to become visible and enabled so that you can click it (param: locator)
- element_to_be_selected – expect for the element to be selected (param: element)
- frame_to_be_available_and_switch_to_it – expect to check if the given frame is available for switching to it (param: locator)
- invisibility_of_element_located – expect to check if an element is either invisible or missing from the DOM (param: locator)
- presence_of_all_elements_located – expect to check that at least one element is present on the web page (param: locator)
- presence_of_element_located – expect to check that an element is present on the DOM of a page (param: locator)
- staleness_of – wait until the element is no longer attached to the DOM (param: element)
- text_to_be_present_in_element – expect to check if the given text is present in the specified element (param: locator, text_)
- text_to_be_present_in_element_value – expect to check if the given text is present in the element’s locator, text. (param: locator, text_)
- title_contains – expect to check that the title contains a case-sensitive sub-string (param: title)
- title_is – expect to check the title of a page (param: title)
- visibility_of – expect to check that an element, known to be present on the DOM of a page, is visible (param: element)
- visibility_of_element_located – expect to check that an element is both present and visible on the DOM of a page (param: locator).
Careful though! Combining Implicit Wait and Explicit Wait can cause unwanted timeout. For example, mixing an Implicit Wait of 10 seconds with an Explicit Wait of 15 seconds for the same element can trigger a timeout that may occur 20 seconds later.
Conclusions
Selenium became a viral solution in testing web applications due to the fact that the HTML elements used in development tend to be more and more complicated and diverse. WebDriver allows running tests in any kind of browser as well as identifying application elements.
Are you using Selenium too? If so, feel free to share your experience in the comments below.
Post A Reply