Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]
-
Upload
yasha-kramarenko -
Category
Technology
-
view
924 -
download
0
Transcript of Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]
![Page 1: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/1.jpg)
Selenide Alternative in PracticeImplementation & Lessons Learned
![Page 2: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/2.jpg)
Preface…
![Page 3: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/3.jpg)
Implementation & Lessons Learned
Selenide Alternative in Practice
![Page 4: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/4.jpg)
Selenide
![Page 5: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/5.jpg)
Selenide = ?
![Page 6: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/6.jpg)
Selenide = Effectiveweb test automation tool
=
tool to automate web UI tests logic
not browser(it should be already
automated;)
![Page 7: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/7.jpg)
Selenide = Effectiveweb test automation tool
=
tool to automate web UI tests logic
not browser
concise API
…
…
…
![Page 8: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/8.jpg)
Selenide = Effectiveweb test automation tool
=
tool to automate web UI tests logic
not browser
concise API
waiting search
…
…
![Page 9: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/9.jpg)
Selenide = Effectiveweb test automation tool
=
tool to automate web UI tests logic
not browser
concise API
waiting search
waiting asserts
…
![Page 10: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/10.jpg)
Selenide = Effectiveweb test automation tool
=
tool to automate web UI tests logic
not browser
concise API
waiting search
waiting asserts
dynamic elements
![Page 11: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/11.jpg)
Selenide = Effectiveweb test automation tool
=
tool to automate web UI tests logic
not browser
concise API
waiting search
waiting asserts
dynamic elements
![Page 12: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/12.jpg)
Selenide Alternative?
concise API
waiting search
waiting asserts
dynamic elements
![Page 13: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/13.jpg)
Selenide Alternative?
concise API
waiting search
waiting asserts
dynamic elements
How should it work?
![Page 14: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/14.jpg)
Selenide Alternative?
concise API
waiting search
waiting asserts
dynamic elements
How should it work? How to build?
![Page 15: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/15.jpg)
With examples in
![Page 16: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/16.jpg)
ProvisoPartial sacrificing
DRY, privatisation, etc. for simplification of examples
![Page 17: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/17.jpg)
![Page 18: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/18.jpg)
Concise API
![Page 19: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/19.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]"))
# vs
s(with_text('task'))
![Page 20: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/20.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]"))
# vs
s(with_text('task'))
DRY locator helpers
![Page 21: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/21.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]"))
# vs
s(with_text('task'))
![Page 22: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/22.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]"))
# vs
s(with_text('task'))
OOP
![Page 23: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/23.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]"))
# vs
s(with_text('task'))
from selenium import webdriver driver = webdriver.Firefox() # ... OOP
![Page 24: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/24.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]"))
# vs
s(with_text('task'))
Modular
from selenium import webdriver driver = webdriver.Firefox() # ... OOP
![Page 25: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/25.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]"))
# vs
s(with_text('task'))
Modular
from selenium import webdriver driver = webdriver.Firefox() # ...
from selene.tools import set_driver, s set_driver(webdriver.Firefox()) # ...
OOP
![Page 26: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/26.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]")).
# vs
s(with_text('task'))
Modular
OOPfrom selenium import webdriver driver = webdriver.Firefox() driver.get(‘http://todomvc4tasj.herokuapp.com’)
from selene.tools import set_driver, s set_driver(webdriver.Firefox()) visit(‘http://todomvc4tasj.herokuapp.com’)
![Page 27: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/27.jpg)
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs
s(by_xpath("//*[contains(text(),'task')]")).
# vs
s(with_text('task'))
Functions over Methods for main actions
from selenium import webdriver driver = webdriver.Firefox() driver.get(‘http://todomvc4tasj.herokuapp.com’)
from selene.tools import set_driver, s set_driver(webdriver.Firefox()) visit(‘http://todomvc4tasj.herokuapp.com’)
![Page 28: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/28.jpg)
s(by_css(‘#new-todo’))
# vs/or
s('#new-todo')
Convenient defaults
![Page 29: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/29.jpg)
driver.find_element_by_css_selector('#new-todo').clear()
driver.find_element_by_css_selector(‘#new-todo’)\ .send_keys(‘task')
# vs
s(‘#new-todo’).clear().send_keys(‘task’)
![Page 30: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/30.jpg)
driver.find_element_by_css_selector('#new-todo').clear()
driver.find_element_by_css_selector(‘#new-todo’)\ .send_keys(‘task')
# vs
s(‘#new-todo’).clear().send_keys(‘task’)
Chainable methods
![Page 31: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/31.jpg)
driver.find_element_by_css_selector('#new-todo')\
.send_keys('task', Keys.ENTER)
# vs
s('#new-todo').send_keys('task').press_enter()
![Page 32: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/32.jpg)
driver.find_element_by_css_selector('#new-todo')\
.send_keys('task', Keys.ENTER)
# vs
s('#new-todo').send_keys('task').press_enter()
“Short-cut” methods
![Page 33: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/33.jpg)
s(‘#new-todo’).clear().send_keys(‘task’)
# vs
s(‘#new-todo’).set(‘task’)
“Short-cut” methods
![Page 34: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/34.jpg)
Built in Explicit Waits aka Waiting Asserts
WebDriverWait(driver, 4).until( element_to_be_clickable(by_css('#new-todo'))) # vs s('#new-todo').should_be(clickable)
![Page 35: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/35.jpg)
new_todo = by_css('#new-todo')visit('http://todomvc4tasj.herokuapp.com')s(new_todo).set('task 1').press_enter() # ...s(new_todo).set('task 2').press_enter() # vs new_todo = s('#new-todo')visit('http://todomvc4tasj.herokuapp.com')new_todo.set('task 1').press_enter() # ...new_todo.set('task 2').press_enter()
![Page 36: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/36.jpg)
new_todo = by_css('#new-todo')visit('http://todomvc4tasj.herokuapp.com') s(new_todo).set('task 1').press_enter() # ...s(new_todo).set('task 2').press_enter() # vs new_todo = s('#new-todo')visit('http://todomvc4tasj.herokuapp.com') new_todo.set('task 1').press_enter() # ...new_todo.set('task 2').press_enter()
![Page 37: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/37.jpg)
new_todo = by_css('#new-todo')visit('http://todomvc4tasj.herokuapp.com') s(new_todo).set('task 1').press_enter() # ...s(new_todo).set('task 2').press_enter() # vs new_todo = s('#new-todo')visit('http://todomvc4tasj.herokuapp.com') new_todo.set('task 1').press_enter() # ...new_todo.set('task 2').press_enter()
?
![Page 38: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/38.jpg)
Dynamic Elements
![Page 39: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/39.jpg)
Dynamic Elementsaka Lazy Proxy Elements
![Page 40: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/40.jpg)
new_todo = s('#new-todo')
![Page 41: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/41.jpg)
def s(css_selector_or_locator): return SElement(css_selector_or_locator)
Element Factory
![Page 42: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/42.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
![Page 43: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/43.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
![Page 44: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/44.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
![Page 45: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/45.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
![Page 46: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/46.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, config.timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
![Page 47: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/47.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, config.timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
“waiting search”
![Page 48: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/48.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, config.timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
“waiting assert”
![Page 49: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/49.jpg)
def wait_for(entity, condition, timeout): # ... end_time = time.time() + timeout while True: try: value = condition(entity) if value is not None: return value except (WebDriverException,) as exc: # ... time.sleep(config.poll_during_waits) if time.time() > end_time: break raise TimeoutException( """ failed while waiting %s seconds to assert %s%s """ % (timeout, condition.__class__.__name__, str(condition), ...)
![Page 50: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/50.jpg)
def wait_for(entity, condition, timeout): # ... end_time = time.time() + timeout while True: try: value = condition(entity) if value is not None: return value except (WebDriverException,) as exc: # ... time.sleep(config.poll_during_waits) if time.time() > end_time: break raise TimeoutException( """ failed while waiting %s seconds to assert %s%s """ % (timeout, condition.__class__.__name__, str(condition), ...)
![Page 51: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/51.jpg)
def wait_for(entity, condition, timeout): # ... end_time = time.time() + timeout while True: try: value = condition(entity) if value is not None: return value except (WebDriverException,) as exc: # ... time.sleep(config.poll_during_waits) if time.time() > end_time: break raise TimeoutException( """ failed while waiting %s seconds to assert %s%s """ % (timeout, method.__class__.__name__, str(condition), ...)
![Page 52: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/52.jpg)
def wait_for(entity, condition, timeout): # ... end_time = time.time() + timeout while True: try: value = condition(entity) if value is not None: return value except (WebDriverException,) as exc: # ... time.sleep(config.poll_during_waits) if time.time() > end_time: break raise TimeoutException( """ failed while waiting %s seconds to assert %s%s """ % (timeout, method.__class__.__name__, str(condition), ...)
![Page 53: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/53.jpg)
class Visible(object): def __call__(self, selement): self.selement = selement found = selement.finder() return found if found.is_displayed() else None def __str__(self): return """ for element found by: %s... """ % (self.selement.locator, …)
visible = Visible()
![Page 54: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/54.jpg)
class Visible(object): def __call__(self, selement): self.selement = selement found = selement.finder() return found if found.is_displayed() else None def __str__(self): return """ for element found by: %s... """ % (self.selement.locator, …)
visible = Visible()
![Page 55: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/55.jpg)
class Visible(object): def __call__(self, webelement): self.selement = selement found = selement.finder() return webelement.is_displayed() def __str__(self): return """ for element found by: %s... """ % (self.selement.locator, …)
visible = Visible()
Original jSelenide style
with selement.finder() being moved to wait_for
![Page 56: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/56.jpg)
class Visible(object): def __call__(self, webelement): self.selement = selement found = selement.finder() return webelement.is_displayed() def __str__(self): return """ for element found by: %s... """ % (self.selement.locator, …)
visible = Visible()
Original jSelenide style
with selement.finder() being moved to wait_for
more simpleand secure
but less powerful
![Page 57: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/57.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, config.timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
![Page 58: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/58.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, config.timeout) return self insist = assure should = assure should_be = assure should_have = assure def click(self): return self.do(lambda element: element.click())
![Page 59: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/59.jpg)
Speed?
![Page 60: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/60.jpg)
class SElement(...): def __init__(self, css_selector_or_locator, context=...): self.locator = parse(css_selector_or_locator) # ... def finder(self): return self.context.find_element(*self.locator)
def assure(self, condition): wait_for(self, condition, config.timeout) return self
def do(self, command): self.assure(visible) command(self.finder()) return self def click(self): return self.do(lambda element: element.click())
redundant finder call
![Page 61: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/61.jpg)
def finder(self): return self.context.find_element(*self.locator)
def refind(self): self.found = self.finder() return self.found
def assure(self, condition): self.found = wait_for(self, condition, config.timeout) return self
def do(self, command): self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
reusing self.found
![Page 62: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/62.jpg)
def finder(self): return self.context.find_element(*self.locator)
def refind(self): self.found = self.finder() return self.found
def assure(self, condition): self.found = wait_for(self, condition, config.timeout) return self
def do(self, command): self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
even when not neededwait always
![Page 63: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/63.jpg)
def refind(self): self.found = self.finder() return self.found
def assure(self, condition): self.found = wait_for(self, condition, config.timeout) return self
def do(self, command): try: self.refind() command() except (WebDriverException): self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
smarter:)
![Page 64: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/64.jpg)
def refind(self): self.found = self.finder() return self.found
def assure(self, condition): self.found = wait_for(self, condition, config.timeout) return self
def do(self, command): try: self.refind() command() except (WebDriverException): self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
smarter:)
Makes Selene as fast as Selenium “with research” :)
![Page 65: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/65.jpg)
def refind(self): self.found = self.finder() return self.found
def assure(self, condition): self.found = wait_for(self, condition, config.timeout) return self
def do(self, command): try: self.refind() command() except (WebDriverException): self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
![Page 66: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/66.jpg)
def refind(self): self.found = self.finder() return self.found
def assure(self, condition): self.found = wait_for(self, condition, config.timeout) return self
def do(self, command): try: self.refind() command() except (WebDriverException): self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
What if I sometimes…I want “raw selenium” speed?
![Page 67: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/67.jpg)
def cash(self): self.is_cached = True self.finder = lambda: self.found return self f def do(self, command): try: if not self.is_cached: self.refind() command() # ... self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
Introducing simple cashing
![Page 68: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/68.jpg)
def cash(self): self.is_cached = True self.finder = lambda: self.found return self f def do(self, command): try: if not self.is_cached: self.refind() command() # ... self.assure(visible) command() return self def click(self): return self.do(lambda: self.found.click())
Introducing simple cashing
Making Selene almost as fast as raw Selenium :)
![Page 69: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/69.jpg)
Proof Demo
![Page 70: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/70.jpg)
Total Laziness
![Page 71: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/71.jpg)
todo_list = s('#todo-list') active_tasks = todo_list.find_all(‘.active’) first_completed_task = todo_list.find(‘.completed')
visit('http://todomvc4tasj.herokuapp.com')# ...
Usage
![Page 72: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/72.jpg)
tasks = ss(‘#todo-list>li') first_task = tasks.get(1) task_a = tasks.find(exact_text(“a")) visible_tasks = tasks.filter(visible)
visit('http://todomvc4tasj.herokuapp.com')# ...
Usage
![Page 73: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/73.jpg)
visible_tasks = ss(‘#todo-list>li').filter(visible) visit('http://todomvc4tasj.herokuapp.com') # ...
![Page 74: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/74.jpg)
def ss(css_selector_or_locator): return SElementsCollection(css_selector_or_locator)
![Page 75: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/75.jpg)
class SElementsCollection(...): def __init__(self, css_selector_or_locator, ..., ...,): self.locator = parse(css_selector_or_locator) ... def finder(self): return ... def filter(self, condition): return ...
...
![Page 76: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/76.jpg)
class SElementsCollection(...): def __init__(self, css_selector_or_locator, ..., ...,): self.locator = parse(css_selector_or_locator) ... def finder(self): return ... def filter(self, condition): return ...
...
![Page 77: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/77.jpg)
locator = lambda index: '%s[%s]' % (self.locator, index) webelements = self.context.find_elements(*self.locator)
return [SElement(locator(index)).cash_with(element) for index, element in enumerate(webelements)]
SElementsCollection#finder
![Page 78: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/78.jpg)
locator = lambda index: '%s[%s]' % (self.locator, index) webelements = self.context.find_elements(*self.locator)
return [SElement(locator(index)).cash_with(element) for index, element in enumerate(webelements)]
SElementsCollection#finder
![Page 79: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/79.jpg)
locator = lambda index: '%s[%s]' % (self.locator, index) webelements = self.context.find_elements(*self.locator)
return [SElement(locator(index)).cash_with(element) for index, element in enumerate(webelements)]
SElementsCollection#finder
![Page 80: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/80.jpg)
class SElementsCollection(...): def __init__(self, css_selector_or_locator, ..., ...,): self.locator = parse(css_selector_or_locator) ... def finder(self): return ... def filter(self, condition): return FilteredSElementsCollection(self, condition) ...
![Page 81: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/81.jpg)
class FilteredSElementsCollection(SElementsCollection): def __init__(self, selements_collection, condition): self.coll = selements_collection self.condition = condition # ... def finder(self): filtered_elements = ... return filtered_elements
![Page 82: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/82.jpg)
class FilteredSElementsCollection(SElementsCollection): def __init__(self, selements_collection, condition): self.coll = selements_collection self.condition = condition # ... def finder(self): filtered_elements = ... return filtered_elements
![Page 83: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/83.jpg)
class FilteredSElementsCollection(SElementsCollection): def __init__(self, selements_collection, condition): self.coll = selements_collection self.condition = condition # ... def finder(self): filtered_elements = ... return filtered_elements
![Page 84: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/84.jpg)
self.coll = selements_collection self.condition = condition locator = "(%s).filter(%s)" % ( self.coll.locator, self.condition.__class__.__name__) SElementsCollection.__init__(self, ('selene', locator)) # ...
FilteredSElementsCollection#__init__
![Page 85: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/85.jpg)
self.coll = selements_collection self.condition = condition locator = "(%s).filter(%s)" % ( self.coll.locator, self.condition.__class__.__name__) SElementsCollection.__init__(self, ('selene', locator)) # ...
FilteredSElementsCollection#__init__
![Page 86: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/86.jpg)
filtered_elements = [selement for selement in self.coll if self.condition(selement)] return filtered_elements
FilteredSElementsCollection#finder
![Page 87: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/87.jpg)
Meta-programming?
![Page 88: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/88.jpg)
class SElement(...): def __init__(self, ..., context=...): # …
def finder(self): return self.context.find_element(*self.locator)
# ...class SElementsCollection(...): def __init__(self, ..., context=..., selement_class=…): # ... # ...
![Page 89: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/89.jpg)
def __init__(self, ..., context=RootSElement()):
![Page 90: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/90.jpg)
class RootSElement(object): def __getattr__(self, item): return getattr(selene.tools.get_driver(), item)
The most innocent example :)
![Page 91: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/91.jpg)
def __getattr__(self, item): return self.do(lambda: getattr(self.found, item))
# VS
def click(self): return self.do(lambda: self.found.click()) def submit(self): return self.do(lambda: self.found.submit()) def clear(self): return self.do(lambda: self.found.clear())
...
Proxying vs Overriding
![Page 92: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/92.jpg)
def __getattr__(self, item): return self.do(lambda: getattr(self.found, item))
# VS
def click(self): return self.do(lambda: self.found.click()) def submit(self): return self.do(lambda: self.found.submit()) def clear(self): return self.do(lambda: self.found.clear())
...
Proxying vs Overriding
![Page 93: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/93.jpg)
Widgets
![Page 94: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/94.jpg)
class Task(SElement): def delete(self): self.hover() self.s(".destroy").click() def test_custom_selement(): given_active("a", "b") Task("#todo-list>li:nth-child(1)").delete()
Just works :)
![Page 95: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/95.jpg)
class Task(SElement): def delete(self): self.hover() self.s(".destroy").click() def test_custom_selement(): given_active("a", "b") Task("#todo-list>li:nth-child(1)").delete()
Just works :)
![Page 96: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/96.jpg)
Because…class SElement(...): def __init__(self, ..., context=RootSElement()): #...
def finder(self): return self.context.find_element(*self.locator) def s(self, css_selector_or_locator): return SElement(css_selector_or_locator, context=self)
#...
![Page 97: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/97.jpg)
Because…class SElement(...): def __init__(self, ..., context=RootSElement()): #...
def finder(self): return self.context.find_element(*self.locator) def s(self, css_selector_or_locator): return SElement(css_selector_or_locator, context=self)
#...
![Page 98: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/98.jpg)
Collection of widgets
class Task(SElement): def delete(self): self.hover() self.s(".destroy").click() def test_selements_collection_of_custom_selements(): given_active("a", "b", "c") for task in ss("#todo-list>li", of=Task): task.delete() ss("#todo-list>li", of=Task).should_be(empty)
![Page 99: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/99.jpg)
Collection of widgets
class Task(SElement): def delete(self): self.hover() self.s(".destroy").click() def test_selements_collection_of_custom_selements(): given_active("a", "b", "c") for task in ss("#todo-list>li", of=Task): task.delete() ss("#todo-list>li", of=Task).should_be(empty)
![Page 100: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/100.jpg)
class SElementsCollection(...): def __init__(self, ..., ...): ... ... ... def finder(self): ... return [ SElement(locator(index)).cash_with(element) for index, element in enumerate(webelements)]
...
recalling basic implementation…
![Page 101: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/101.jpg)
class SElementsCollection(...): def __init__(self, ..., ..., of=SElement): ... self.wrapper_class = of ... def finder(self): ... return [ self.wrapper_class(locator(index)).cash_with(element) for index, element in enumerate(webelements)]
...
needs more…
![Page 102: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/102.jpg)
and sometimes even much more… including meta-programming…
![Page 103: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/103.jpg)
Collection of widgets: selection of one of them
visible_tasks = ss("#todo-list>li", of=Task).filter(visible) ... ... task = visible_tasks.find(exact_text("a")): task.delete() ...
![Page 104: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/104.jpg)
class SElementsCollectionElementByCondition(SElement): def __init__(self, selements_collection, condition): self.coll = selements_collection self.condition = condition locator = "(%s).found_by(%s)" % ( self.coll.locator, self.condition.__class__.__name__) ... def finder(self): for selement in self.coll: if self.condition(selement): return selement.found
find(exact_text("a")) =>
![Page 105: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/105.jpg)
self.coll = selements_collection self.condition = condition locator = "(%s).found_by(%s)" % ( self.coll.locator, self.condition.__class__.__name__) SElementsCollectionElementByCondition.__init__(self, (“selene”, locator)) ...
SElementsCollectionElementByCondition#__init__
![Page 106: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/106.jpg)
self.coll = selements_collection self.condition = condition locator = "(%s).found_by(%s)" % ( self.coll.locator, self.condition.__class__.__name__) SElementsCollectionElementByCondition.__init__(self, (“selene”, locator)) extend(self, self.coll.wrapper_class, ("selene", locator))
SElementsCollectionElementByCondition#__init__
![Page 107: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/107.jpg)
def extend(obj, cls, *init_args, **init_kwargs): obj.__class__ = type(obj.__class__.__name__, (obj.__class__, cls), {}) cls.__init__(obj, *init_args, **init_kwargs)
Dynamic class extension
![Page 108: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/108.jpg)
def extend(obj, cls, *init_args, **init_kwargs): obj.__class__ = type(obj.__class__.__name__, (obj.__class__, cls), {}) cls.__init__(obj, *init_args, **init_kwargs)
Dynamic class extension
![Page 109: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/109.jpg)
def extend(obj, cls, *init_args, **init_kwargs): obj.__class__ = type(obj.__class__.__name__, (obj.__class__, cls), {}) cls.__init__(obj, *init_args, **init_kwargs)
Dynamic class extension
e.g. to initialise probable widget’s subelements
![Page 110: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/110.jpg)
class Task(SElement): def init(self): self.destroy_button = self.s(".destroy") ... ... task = ss("#todo-list>li", of=Task).find(text("a")): task.hover() task.destroy_button.click() ...
like in this example ;)
![Page 111: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/111.jpg)
__init__ vs init ? o_O
![Page 112: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/112.jpg)
class SElement(...): def __init__(self): ... if hasattr(self, 'init'): self.init()
__init__ vs init ? o_O
![Page 113: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/113.jpg)
Proxying vs dynamic extensionSElement(...) def __getattr__(self, item): return self.do(lambda: getattr(self.found, item))
SElementsCollectionElementByCondition(SElement) __init__ extend(self, self.coll.wrapper_class, ('selene', locator))
# VS
SElement(...) def __getattr__(self, item): return self.do(lambda: getattr(self.found, item))
SElementsCollectionElementByCondition(SElement) __init__ extend(self, self.coll.wrapper_class, ('selene', locator))
![Page 114: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/114.jpg)
Install & Docs
![Page 115: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/115.jpg)
$ pip install selene
![Page 117: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/117.jpg)
visit(‘/questions_and_answers') s('#question').set('<YOUR QUESTION>’).press_enter() ss('.answer').should_not_be(empty)
![Page 118: Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]](https://reader034.fdocuments.in/reader034/viewer/2022042907/586fd51a1a28ab18428b4a75/html5/thumbnails/118.jpg)
github.com/yashaka
github.com/yashaka/selene
@yashaka
Thank You