The presentation starts with raw Selenium code for a basic scenario, discusses the challenges, and how to do better with Arjuna. Useful Arjuna-neutral framework building tips are shared across the slides.
5. Why Do We Need a Framework? Shouldn’t We Directly Use Selenium WebDriver
Consider the following raw Selenium code in Python:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
user_name = "YOUR EMAILID"
password = "YOUR PASSWORD"
svc = Service("/path/to/driver")
svc.start()
driver = webdriver.Remote(svc.svc_url)
driver.get("https://www.app.com")
element = driver.find_element_by_id("email")
element.send_keys(user_name)
element = driver.find_element_by_id("pass")
element.send_keys(password)
element = driver.find_element_by_xpath("//input[contains(text(), 'sub')]")
element.click()
driver.quit()
Framework Tip:
This nature of code
INDICATES to you that
this code will grow very
large.
6. A Better Raw Selenium Script
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
user_name = "YOUR EMAILID"
password = "YOUR PASSWORD"
waiter = WebDriverWait(driver,30)
svc = Service("/path/to/driver")
svc.start()
driver = webdriver.Remote(svc.svc_url)
driver.get("https://www.app.com")
waiter.until(EC.presence_of_element_located((By.ID, "home_elem")))
element = waiter.until(EC.element_to_be_clickable((By.ID, "email")))
element.send_keys(user_name)
element = waiter.until(EC.element_to_be_clickable((By.ID, "pass")))
element.send_keys(password)
element = waiter.until(EC.element_to_be_clickable((By.XPATH, "//input[contains(text(),
'sub')]")))
element.click()
waiter.until(EC.presence_of_element_located((By.ID, "dash_elem")))
driver.quit()
Framework Tip:
This nature of
code ESTABLISHES
the need for a
framework.
8. How We Do It In Arjuna – Selenium Wrapper
from arjuna import *
app = GuiApp()
app.launch()
app.element(id="home_elem")
app.element(id="email").text = C("user.name")
app.element(id="pass").text = C("user.pwd")
app.element(text="sub").click()
app.element(id="dash_elem")
app.quit()
Framework Tip:
Make contextual wait as
default.
9. How We Do It In Arjuna – Let’s Do Better
App.yaml
Externalize the locators and meta data.
load:
anchor: home
labels:
home:
id: home_elem
email:
id: email
pwd:
id: pass
submit:
text: sub
dash:
id: dash_elem
max_wait: 120
Framework Tip:
Find a way to externalize
locators.
Then make it more than
locator externalization.
Framework Tip:
Develop higher level
locators.
Framework Tip:
Avoid binary formats.
10. How We Do It In Arjuna – Let’s Do Better
from arjuna import *
app = GuiApp(label="App")
app.launch()
app.gns.email.text = C("user.name")
app.gns.pwd.text = C("user.pwd")
app.gns.submit.click()
app.gns.dash
app.quit()
Framework Tip:
If you are a Python Coder
and Planning to
Hack the Dot
Be VERY VERY Careful.
11. How We Do It In Arjuna – Localization
App.yaml
$$ Placeholders can use C/L/R prefixes for Config/Localized/Reference Values
load:
anchor: home
labels:
home:
id: home_elem
email:
id: email
pwd:
id: pass
submit:
text: $L.login.submitText$
dash:
id: dash_elem
max_wait: 120
Framework Tip:
Find a way for auto-
configuring the locators.
Saves a lot of code.
12. How We Do It In Arjuna – Localization
from arjuna import *
app = GuiApp(label="App")
app.launch()
app.gns.email.text = L(”user_name") # Or R(“user_name”) if reference is used
app.gns.pwd.text = L("user_pwd”)
app.gns.submit.click()
app.gns.dash
app.quit()
Framework Tip:
Plan localization if your
application is available in
multiple languages. It’s more
complex than you think in UI
Automation.
Automation Tip:
Minimize text based locators. Text
is what gets localized.
14. How We Do It In Arjuna – Test Functions and Resources
@for_module
def home(request, default=True):
app = GuiApp(label="App")
home_page = app.launch()
yield home_page
app.quit()
@for_test
def dashboard(request, default=True):
dashboard = home.login_with_default_creds()
yield dashboard
request.test.space.current_page.top_nav.logout()
@test
def check_some_use_case_1(request):
pass
@test
def check_some_use_case_2(request):
pass
Framework Tip:
Club setup and teardown/cleanup. Grow
beyond traditional meaning of Test
Fixtures.
15. Some Other Salient Features
• A Comprehensive CLI. An advanced rules engine for test selection.
• Advanced Logging Facilities including Auto-Logging and Contextual Logging. Arjuna adds a TRACE
level for logging, which is absent in Python for very low level logging.
• Very powerful Data Driven Testing features.
• Ability to define any number of data and environment configurations
• HTML Reporting with Screenshot on Failure and Detailed Error Traces.
• JUnit-compatible XML reporting. So, it integrates with any CI plugins for reporting.
• A well defined test project structure for consistency across test projects.
• Provision to define your own locators e.g. you can abstract identification for a mat-icon using a
complex XPath and then re-use this definition elsewhere.
• Direct parsing of DOM nodes rather than browser calls. This makes parsing very fast.
• As of now, no other dependency apart from arjuna. Arjuna manages all dependencies. Just do a `pip
install arjuna` and you are ready.
• Uses Python 3.6+, so is aligned with Python’s future.
• Supports execution of tests in Docker-Selenium. Just point selenium.service.url to the docker’s
service.