Python is emerging as one of today's most popular programming languages. It is extensively used in AI and ML, as well as in developing web applications. Python is employed in creating everything from the simplest to the most complex and sophisticated systems, significantly influencing the QA testing landscape in the IT industry.
This blog follows up on the initial entry of this series, where I shared some of the most frequently used Selenium commands in Python. In this installment, we delve into more complex commands and tests that necessitate a greater degree of thought and ingenuity to navigate and resolve issues via automation.
Test Environment
Selenium Version - 4.22
Python Version - 3.10
Pytest Version - 8.2.2
Test Environment Specifications - Windows 11 + Pycharm Community Edition
Application URL - http://the-internet.herokuapp.com/
Embedded is a link to the execution video of these tests.
We now describe what we try to achieve in each test followed by the respective Selenium Python code snippet:-
This file contains the application URL defined in a single location, eliminating the need to manually enter it across various test cases for each test.
# Some environment details are described in this fixture method like
# Application URL
@pytest.fixture
def environment_details():
url = "http://the-internet.herokuapp.com/"
return url
Add_Remove_Elements.py
This file includes all the Selenium commands to be discussed in this article. The setup and yield commands have been incorporated into a pytest.fixture method. Subsequent to this, the test methods will be presented.
# setup initiates the test environment and selenium webdriver instance
@pytest.fixture
def setup(environment_details):
print("Setting up...")
driver = webdriver.Firefox()
driver.get(environment_details)
yield driver
print("Tearing down...")
driver.close()
Dynamic Content
This test requires navigating to the "Dynamic Content" link and experimenting with capturing attributes of dynamic web elements. Specifically, the test involves identifying the src attribute of images that change upon each page refresh.
# Method to capture src attribute of dynamically appearing images.
def test_dynamic_content(setup):
setup.find_element(By.LINK_TEXT,"Dynamic Content").click()
images = setup.find_elements(By.XPATH,"//*[@class='large-10 columns large-centered']/div/div/child::img")
texts = setup.find_elements(By.XPATH,"//*[@class='large-10 columns large-centered']/div/div/child::img/following::div[@class='large-10 columns']")
size = len(images)
# Capturing src attribute of the images
for img in images:
print(img.get_attribute("src"))
# Capturing text displayed next to each image
for t in texts:
print(t.text)
Dynamic Controls
This test involves navigating to the "Dynamic Controls" link and performing actions according to the current state of web elements. For instance, we verify the status of a checkbox; if it is unchecked, we check it. Subsequently, we activate a disabled text box and employ webdriver wait until it is enabled, allowing us to input text.
# Method to capture attributes of some elements and changing their status
def test_dynamic_controls(setup):
setup.find_element(By.LINK_TEXT,"Dynamic Controls").click()
cbox_status = setup.find_element(By.ID,"checkbox").get_attribute("checked")
# Check whether checkbox is enabled of disabled.
if cbox_status == None:
setup.find_element(By.ID,"checkbox").click()
setup.find_element(By.XPATH,"//button[text()='Remove']").click()
# Checking whether text box is disabled and if yes click to enable it
tbox_status = setup.find_element(By.XPATH,"//*[@id='input-example']/child::input").get_attribute("disabled")
if tbox_status == "true":
setup.find_element(By.XPATH,"//button[text()='Enable']").click()
# Wait for the text box to get enabled
wait = WebDriverWait(setup,20).until(EC.element_to_be_clickable((By.XPATH,"//*[@id='input-example']/child::input")))
setup.find_element(By.XPATH,"//*[@id='input-example']/child::input").click()
setup.find_element(By.XPATH, "//*[@id='input-example']/child::input").send_keys("Entering text")
Dynamic Loading
The test requires navigating to the "Dynamic Loading" link where we navigate to a page with a hidden element on it. The display attribute of the element is then altered using a JavaScript executor to make it visible.
# Method to navigate to a page with hidden element and displaying it
def test_dynamic_loading(setup):
setup.find_element(By.LINK_TEXT,"Dynamic Loading").click()
setup.find_element(By.LINK_TEXT,"Example 1: Element on page that is hidden").click()
hidden_element = setup.find_element(By.XPATH,"//*[@id='finish']")
display_status = setup.find_element(By.XPATH,"//*[@id='finish']").get_attribute("style")
# Check elements display status
display_status == 'display: none;'
if display_status == 'display: none;':
# Use javascript to change the attribute display from none to block
setup.execute_script("arguments[0].setAttribute('style','display: block;')",hidden_element)
wait = WebDriverWait(setup,20).until(EC.presence_of_element_located((By.XPATH,"//*[@id='finish']")))
Exit Viewport
The test requires navigating to the "Exit Intent" link, where a modal dialog appears as soon as the browser viewport is exited. This resembles the subscription boxes commonly seen on websites. Since Selenium lacks the ability to interact outside the browser's viewport, the issue is addressed by employing a combination of AutoIt commands alongside Selenium.
# Method to exit the browser viewport to get a modal dialog appear.
def test_exit_intent(setup):
setup.find_element(By.LINK_TEXT,"Exit Intent").click()
window_size = setup.get_window_size()
# Capturing the window width and height
width = window_size['width']
height = window_size['height']
# Adjusting screen size metrics to move mouse to desired position
width_click = width-1000
height_click = height - (height-5)
# AIT command to move the mouse
ait.move(1000, 5)
modal = setup.find_element(By.XPATH,"//*[@id = 'ouibounce-modal']")
if modal.is_displayed():
print("Modal dialog is opened")
else:
print("Failed")
We execute the tests and redirect the output to an XML file using the following command:
pytest -v --junitxml="results.xml"
Execution run is posted on link below. Feel free to slow it down to check what happens as each test method executes.
The comprehensive code base for the above reference has been checked in @.
priyadarshanipandey/HerokuAutomation: A python selenium commands reference with demo site as https://the-internet.herokuapp.com/ (github.com)
Part 1 of this blog series can be found @
With over 14 years of experience as an automation engineer and a product quality owner, I possess extensive expertise in resolving automation-related challenges. If you encounter quality roadblocks or have business use cases that demand meticulous testing with precision and cost-efficiency, please consider reaching out to me.
You can reach me @
Linkedin - Priyadarshani Pandey | LinkedIn
Comments