Another Selenium Project: Prague Tourism Website
Testing some basic functionality of prague.eu.
This time I wanted to make improvements on three areas.
- More deliberate use of pytest fixtures
- Moving away from implicit waits to explicit waits
- Wiser use of web element locators
Conftest
Again setup and teardown.
import pytest
from selenium.webdriver import Chrome
# from selenium.webdriver.support.ui import WebDriverWait
# https://www.guru99.com/pytest-tutorial.html
# Fixture to initialize and quit for all tests
# conftest.py spcefifically allows a pytest fixture to be shared among multiple files
@pytest.fixture
def browser(scope="session"):
print("initiating chrome driver")
driver = Chrome()
yield driver
driver.close()
print("quitting chrome driver")
Test daytrips
Selenium clicks the “Day Trips” button in the navbar and asserts that two tabs are now open: the homepage and the daytrips tab. Not that the test does not assert which tab is visible, only which ones are open.
The code:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException
def test_daytrips_tab_functionality(browser):
# GIVEN the user is on The Official Tourist website for Prague
base_url = "https://www.prague.eu/en"
browser.maximize_window()
browser.get(base_url)
try:
assert "Prague" in browser.title
print(browser.current_url)
except AssertionError as e:
print(e)
raise e
# WHEN the user clicks on 'Day Trips' in the navigation bar
day_trip_nav = "//nav/a[contains(@href, 'trips' )]"
wait = WebDriverWait(browser, 20)
try:
wait.until(EC.element_to_be_clickable((By.XPATH, day_trip_nav)))
except TimeoutException as e:
print(e)
print("------------")
print(str(e))
print("------------")
print(e.args)
print("============")
except Exception:
print("FALLBACK EXCEPTION")
try:
day_trip_menu_item = browser.find_element(By.XPATH, day_trip_nav)
day_trip_menu_item.click()
except NoSuchElementException as e:
print(e)
print("------------")
print(str(e))
print("------------")
print(e.args)
print("============")
# THEN the user is on a new tab with information on day trips around Prague
browser_tabs = browser.window_handles
size = len(browser_tabs)
try:
assert size == 2
except AssertionError as e:
print(e)
raise e
browser.switch_to.window(browser_tabs[0])
print(browser.title)
# Assert that this is the main page
try:
assert "Prague" in browser.title
except AssertionError as e:
print(e)
raise e
browser.switch_to.window(browser_tabs[1])
print(browser.title)
# Assert the next tab is the Day Trip page
try:
assert "DayTrips" in browser.title
except AssertionError as e:
print(e)
raise e
Test search bar
This test script enters “Brewery” — a search term that would make much sense to any Prague visitor — in the search bar. The search results are displayed, and the script asserts that the search results contain the search term.
The code:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import TimeoutException, NoSuchElementException
def test_search_bar_functionality(browser):
# GIVEN the user is on the officiaL tourist websire for Prague
base_url = "https://www.prague.eu/en"
browser.maximize_window()
browser.get(base_url)
# WHEN the user searches for 'Brewery' in the search window
search_toggle_xpath = "//div[contains(@class, 'search-toggle')]"
wait = WebDriverWait(browser, 20)
try:
wait.until(EC.element_to_be_clickable((By.XPATH, search_toggle_xpath)))
except TimeoutException as e:
print(e)
raise (e)
except Exception as e:
print(e)
raise e
try:
search_toggle = browser.find_element(By.XPATH, search_toggle_xpath)
search_toggle.click()
except NoSuchElementException as e:
print(e)
raise e
except Exception as e:
print(e)
raise e
# search_window clickable
try:
wait.until(EC.element_to_be_clickable((By.ID, "query")))
except TimeoutException as e:
print(e)
raise e
except Exception as e:
print(e)
raise e
search_window = browser.find_element(By.ID, "query")
search_term = "Brewery"
search_window.send_keys(search_term)
search_window.send_keys(Keys.ENTER)
# THEN the user is on a page that displays
# the search results related to breweries
query_results_url = "https://www.prague.eu/qf/en/ramjet/fulltextSearch"
# Assert correct url
try:
assert browser.current_url == query_results_url
except AssertionError as e:
print(e)
raise e
except Exception as e:
print(e)
raise e
# Assert that the list for results is visible
full_text_list_xpath = "//ul[@id='fulltextListing']"
try:
wait.until(EC.visibility_of_element_located((By.XPATH, full_text_list_xpath)))
except TimeoutException as e:
print(e)
raise e
except Exception as e:
print(e)
raise e
results_xpath = (
f"//ul[@id='fulltextListing']/li//*[contains(text(), '{search_term}')]"
)
# Assert both that a results list exists
# and that the search term is found in the result list
try:
results = browser.find_elements(By.XPATH, results_xpath)
assert len(results) > 0
except AssertionError as e:
print(e)
raise e
Lessons learned
If earlier I used implicit waits where it seemed appropriate, with explicit waits I am much more deliberate about what change in the website I am waiting for.
After learning more about xpath I have improved the locators compared with the first project.
All examples I have seen so far of how to use Chrome driver’s scope parameter are from within a class. Since I am not using classes in this project I am still not sure if so far it made much difference wether I choose “session” or “module”. So in this case I will chosen “session” as the parameter. I have also noticed how I get no printout of “quitting chrome driver” from the last line of code. In the future I will use classes and also build test projects with better understanding of the fixture .