SlideShare uma empresa Scribd logo
1 de 118
Baixar para ler offline
Selenide Alternative in Practice
Implementation & Lessons Learned
Preface…
Implementation & Lessons Learned
Selenide Alternative in Practice
Selenide
Selenide = ?
Selenide = Effective
web test automation tool
=
tool to automate
web UI tests logic
not browser
(it should be already
automated;)
Selenide = Effective
web test automation tool
=
tool to automate
web UI tests logic
not browser
concise API
…
…
…
Selenide = Effective
web test automation tool
=
tool to automate
web UI tests logic
not browser
concise API
waiting search
…
…
Selenide = Effective
web test automation tool
=
tool to automate
web UI tests logic
not browser
concise API
waiting search
waiting asserts
…
Selenide = Effective
web test automation tool
=
tool to automate
web UI tests logic
not browser
concise API
waiting search
waiting asserts
dynamic elements
Selenide = Effective
web test automation tool
=
tool to automate
web UI tests logic
not browser
concise API
waiting search
waiting asserts
dynamic elements
Selenide Alternative?
concise API
waiting search
waiting asserts
dynamic elements
Selenide Alternative?
concise API
waiting search
waiting asserts
dynamic elements
How should it work?
Selenide Alternative?
concise API
waiting search
waiting asserts
dynamic elements
How should it work? How to build?
With examples in
Proviso
Partial sacrificing
DRY, privatisation, etc.
for simplification of examples
Concise API
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")

# vs


s(by_xpath("//*[contains(text(),'task')]"))

# vs


s(with_text('task'))
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")

# vs


s(by_xpath("//*[contains(text(),'task')]"))

# vs


s(with_text('task'))
DRY locator helpers
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")

# vs


s(by_xpath("//*[contains(text(),'task')]"))

# vs


s(with_text('task'))
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")

# vs


s(by_xpath("//*[contains(text(),'task')]"))

# vs


s(with_text('task'))
OOP
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
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
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
driver.find_element(By.XPATH, "//*[contains(text(),'task')]")
# vs


s(by_xpath("//*[contains(text(),'task')]")).

# vs


s(with_text('task'))
Modular
OOP
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’)
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’)
s(by_css(‘#new-todo’))
# vs/or

s('#new-todo')
Convenient defaults


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’)


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


driver.find_element_by_css_selector('#new-todo')

.send_keys('task', Keys.ENTER)

# vs


s('#new-todo').send_keys('task').press_enter()


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
s(‘#new-todo’).clear().send_keys(‘task’)


# vs


s(‘#new-todo’).set(‘task’)
“Short-cut” methods
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)


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()


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()


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()
?
Dynamic Elements
Dynamic Elements
aka Lazy Proxy Elements
new_todo = s('#new-todo')
def s(css_selector_or_locator):

return SElement(css_selector_or_locator)
Element Factory
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())
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())
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())
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())
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())
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”
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”


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), ...)


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), ...)


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), ...)


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), ...)
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()
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()
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
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 simple

and secure

but 

less powerful
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())
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())
Speed?
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


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


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 needed
wait always
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:)
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” :)
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())
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?


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


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 :)
Proof Demo
Total Laziness
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
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
visible_tasks = ss(‘#todo-list>li').filter(visible)



visit('http://todomvc4tasj.herokuapp.com')

# ...
def ss(css_selector_or_locator):

return SElementsCollection(css_selector_or_locator)
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 ...
...
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 ...
...
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
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
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
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)
...
class FilteredSElementsCollection(SElementsCollection):

def __init__(self, selements_collection, condition):

self.coll = selements_collection

self.condition = condition

# ...



def finder(self):

filtered_elements = ...

return filtered_elements
class FilteredSElementsCollection(SElementsCollection):

def __init__(self, selements_collection, condition):

self.coll = selements_collection

self.condition = condition

# ...



def finder(self):

filtered_elements = ...

return filtered_elements
class FilteredSElementsCollection(SElementsCollection):

def __init__(self, selements_collection, condition):

self.coll = selements_collection

self.condition = condition

# ...



def finder(self):

filtered_elements = ...

return filtered_elements
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__
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__
filtered_elements = [selement for selement in self.coll

if self.condition(selement)]


return filtered_elements
FilteredSElementsCollection#finder
Meta-programming?
class SElement(...):

def __init__(self, ..., context=...):
# …
def finder(self):

return self.context.find_element(*self.locator)
# ...



class SElementsCollection(...):

def __init__(self, ..., context=..., selement_class=…):
# ...

# ...
def __init__(self, ..., context=RootSElement()):
class RootSElement(object):

def __getattr__(self, item):

return getattr(selene.tools.get_driver(), item)
The most innocent example :)
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
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
Widgets
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 :)
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 :)
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)
#...
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)
#...
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)
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)
class SElementsCollection(...):


def __init__(self, ..., ...):

...

...

...



def finder(self):
...

return [
SElement(locator(index)).cash_with(element)

for index, element in enumerate(webelements)]

...
recalling basic implementation…
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…
and sometimes even much more…
including meta-programming…
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()
...
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")) =>
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__
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__
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
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
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
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 ;)
__init__ vs init ? o_O
class SElement(...):

def __init__(self):
...

if hasattr(self, 'init'):

self.init()
__init__ vs init ? o_O
Proxying vs dynamic extension
SElement(...)
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))
Install & Docs
$ pip install selene
https://github.com/yashaka/selene
visit(‘/questions_and_answers')


s('#question').set('<YOUR QUESTION>’).press_enter()


ss('.answer').should_not_be(empty)
github.com/yashaka
github.com/yashaka/selene
yashaka@gmail.com
@yashaka
Thank You

Mais conteúdo relacionado

Mais procurados

Webdriver cheatsheets summary
Webdriver cheatsheets summaryWebdriver cheatsheets summary
Webdriver cheatsheets summaryAlan Richardson
 
Test automation & Seleniun by oren rubin
Test automation & Seleniun by oren rubinTest automation & Seleniun by oren rubin
Test automation & Seleniun by oren rubinOren Rubin
 
Nightwatch at Tilt
Nightwatch at TiltNightwatch at Tilt
Nightwatch at TiltDave King
 
ForwardJS 2017 - Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 -  Fullstack end-to-end Test Automation with node.jsForwardJS 2017 -  Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 - Fullstack end-to-end Test Automation with node.jsMek Srunyu Stittri
 
20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testing20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testingVladimir Roudakov
 
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...Alan Richardson
 
Introduction to Selenium and Ruby
Introduction to Selenium and RubyIntroduction to Selenium and Ruby
Introduction to Selenium and RubyYnon Perek
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJSPeter Drinnan
 
Join the darkside: Selenium testing with Nightwatch.js
Join the darkside: Selenium testing with Nightwatch.jsJoin the darkside: Selenium testing with Nightwatch.js
Join the darkside: Selenium testing with Nightwatch.jsSeth McLaughlin
 
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015Codemotion
 
Selenium withnet
Selenium withnetSelenium withnet
Selenium withnetVlad Maniak
 
Introduction to Protractor
Introduction to ProtractorIntroduction to Protractor
Introduction to ProtractorJie-Wei Wu
 
Automation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and BeyondAutomation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and BeyondAlan Richardson
 
Automation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and BeyondAutomation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and BeyondTechWell
 
Lets make a better react form
Lets make a better react formLets make a better react form
Lets make a better react formYao Nien Chung
 
Automated Testing with Ruby
Automated Testing with RubyAutomated Testing with Ruby
Automated Testing with RubyKeith Pitty
 
Enhance react app with patterns - part 1: higher order component
Enhance react app with patterns - part 1: higher order componentEnhance react app with patterns - part 1: higher order component
Enhance react app with patterns - part 1: higher order componentYao Nien Chung
 

Mais procurados (20)

Webdriver cheatsheets summary
Webdriver cheatsheets summaryWebdriver cheatsheets summary
Webdriver cheatsheets summary
 
Test automation & Seleniun by oren rubin
Test automation & Seleniun by oren rubinTest automation & Seleniun by oren rubin
Test automation & Seleniun by oren rubin
 
KISS Automation.py
KISS Automation.pyKISS Automation.py
KISS Automation.py
 
Nightwatch at Tilt
Nightwatch at TiltNightwatch at Tilt
Nightwatch at Tilt
 
ForwardJS 2017 - Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 -  Fullstack end-to-end Test Automation with node.jsForwardJS 2017 -  Fullstack end-to-end Test Automation with node.js
ForwardJS 2017 - Fullstack end-to-end Test Automation with node.js
 
20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testing20160905 - BrisJS - nightwatch testing
20160905 - BrisJS - nightwatch testing
 
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
 
Introduction to Selenium and Ruby
Introduction to Selenium and RubyIntroduction to Selenium and Ruby
Introduction to Selenium and Ruby
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJS
 
Join the darkside: Selenium testing with Nightwatch.js
Join the darkside: Selenium testing with Nightwatch.jsJoin the darkside: Selenium testing with Nightwatch.js
Join the darkside: Selenium testing with Nightwatch.js
 
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
Carmen Popoviciu - Protractor styleguide | Codemotion Milan 2015
 
Night Watch with QA
Night Watch with QANight Watch with QA
Night Watch with QA
 
Selenium withnet
Selenium withnetSelenium withnet
Selenium withnet
 
Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet
 
Introduction to Protractor
Introduction to ProtractorIntroduction to Protractor
Introduction to Protractor
 
Automation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and BeyondAutomation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and Beyond
 
Automation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and BeyondAutomation Abstractions: Page Objects and Beyond
Automation Abstractions: Page Objects and Beyond
 
Lets make a better react form
Lets make a better react formLets make a better react form
Lets make a better react form
 
Automated Testing with Ruby
Automated Testing with RubyAutomated Testing with Ruby
Automated Testing with Ruby
 
Enhance react app with patterns - part 1: higher order component
Enhance react app with patterns - part 1: higher order componentEnhance react app with patterns - part 1: higher order component
Enhance react app with patterns - part 1: higher order component
 

Destaque

Page object with selenide
Page object with selenidePage object with selenide
Page object with selenideCOMAQA.BY
 
You do not need automation engineer - Sqa Days - 2015 - EN
You do not need automation engineer  - Sqa Days - 2015 - ENYou do not need automation engineer  - Sqa Days - 2015 - EN
You do not need automation engineer - Sqa Days - 2015 - ENIakiv Kramarenko
 
Automation is Easy! (python version)
Automation is Easy! (python version)Automation is Easy! (python version)
Automation is Easy! (python version)Iakiv Kramarenko
 
How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)Dave Haeffner
 
Selenium Tips & Tricks
Selenium Tips & TricksSelenium Tips & Tricks
Selenium Tips & TricksDave Haeffner
 
Selenium documentation,
Selenium documentation,Selenium documentation,
Selenium documentation,t7t7uyt
 
Getting maximum from testing automation
Getting maximum from testing automationGetting maximum from testing automation
Getting maximum from testing automationAnton Sirota
 
Better Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternBetter Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternSargis Sargsyan
 
Teaching Automation. How big companies do it.
Teaching Automation. How big companies do it.Teaching Automation. How big companies do it.
Teaching Automation. How big companies do it.Vitali Shulha
 

Destaque (12)

Page object with selenide
Page object with selenidePage object with selenide
Page object with selenide
 
You do not need automation engineer - Sqa Days - 2015 - EN
You do not need automation engineer  - Sqa Days - 2015 - ENYou do not need automation engineer  - Sqa Days - 2015 - EN
You do not need automation engineer - Sqa Days - 2015 - EN
 
Automation is Easy! (python version)
Automation is Easy! (python version)Automation is Easy! (python version)
Automation is Easy! (python version)
 
How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)How To Use Selenium Successfully (Java Edition)
How To Use Selenium Successfully (Java Edition)
 
Selenium Tips & Tricks
Selenium Tips & TricksSelenium Tips & Tricks
Selenium Tips & Tricks
 
Selenium documentation,
Selenium documentation,Selenium documentation,
Selenium documentation,
 
Selenium web driver
Selenium web driverSelenium web driver
Selenium web driver
 
Getting maximum from testing automation
Getting maximum from testing automationGetting maximum from testing automation
Getting maximum from testing automation
 
Selenium
SeleniumSelenium
Selenium
 
Allure Framework
Allure FrameworkAllure Framework
Allure Framework
 
Better Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternBetter Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component Pattern
 
Teaching Automation. How big companies do it.
Teaching Automation. How big companies do it.Teaching Automation. How big companies do it.
Teaching Automation. How big companies do it.
 

Semelhante a Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]

Escape from the automation hell
Escape from the automation hellEscape from the automation hell
Escape from the automation hellNikita Simonovets
 
Let's talk testing with Selenium
Let's talk testing with SeleniumLet's talk testing with Selenium
Let's talk testing with Seleniumanishanarang
 
2010 07-18.wa.rails tdd-6
2010 07-18.wa.rails tdd-62010 07-18.wa.rails tdd-6
2010 07-18.wa.rails tdd-6Marakana Inc.
 
Efficient Rails Test-Driven Development - Week 6
Efficient Rails Test-Driven Development - Week 6Efficient Rails Test-Driven Development - Week 6
Efficient Rails Test-Driven Development - Week 6Marakana Inc.
 
Automation - web testing with selenium
Automation - web testing with seleniumAutomation - web testing with selenium
Automation - web testing with seleniumTzirla Rozental
 
Test automation with selenide
Test automation with selenideTest automation with selenide
Test automation with selenideIsuru Madanayaka
 
Automating Django Functional Tests Using Selenium on Cloud
Automating Django Functional Tests Using Selenium on CloudAutomating Django Functional Tests Using Selenium on Cloud
Automating Django Functional Tests Using Selenium on CloudJonghyun Park
 
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"GeeksLab Odessa
 
Python Testing 101 with Selenium
Python Testing 101 with SeleniumPython Testing 101 with Selenium
Python Testing 101 with SeleniumLeonardo Jimenez
 
Selenium testing
Selenium testingSelenium testing
Selenium testingJason Myers
 
Automation with Selenium Presented by Quontra Solutions
Automation with Selenium Presented by Quontra SolutionsAutomation with Selenium Presented by Quontra Solutions
Automation with Selenium Presented by Quontra SolutionsQuontra Solutions
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e bigAndy Peterson
 
Component Based Unit Testing ADF with Selenium
Component Based Unit Testing ADF with SeleniumComponent Based Unit Testing ADF with Selenium
Component Based Unit Testing ADF with SeleniumRichard Olrichs
 
Breaking the limits_of_page_objects
Breaking the limits_of_page_objectsBreaking the limits_of_page_objects
Breaking the limits_of_page_objectsRobert Bossek
 
Selenide vs. Selenium: The War Of Technologies
Selenide vs. Selenium: The War Of TechnologiesSelenide vs. Selenium: The War Of Technologies
Selenide vs. Selenium: The War Of TechnologiesBugRaptors
 
Better Testing With PHP Unit
Better Testing With PHP UnitBetter Testing With PHP Unit
Better Testing With PHP Unitsitecrafting
 

Semelhante a Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016] (20)

Escape from the automation hell
Escape from the automation hellEscape from the automation hell
Escape from the automation hell
 
Let's talk testing with Selenium
Let's talk testing with SeleniumLet's talk testing with Selenium
Let's talk testing with Selenium
 
2010 07-18.wa.rails tdd-6
2010 07-18.wa.rails tdd-62010 07-18.wa.rails tdd-6
2010 07-18.wa.rails tdd-6
 
Efficient Rails Test-Driven Development - Week 6
Efficient Rails Test-Driven Development - Week 6Efficient Rails Test-Driven Development - Week 6
Efficient Rails Test-Driven Development - Week 6
 
Automation - web testing with selenium
Automation - web testing with seleniumAutomation - web testing with selenium
Automation - web testing with selenium
 
Web driver training
Web driver trainingWeb driver training
Web driver training
 
Test automation with selenide
Test automation with selenideTest automation with selenide
Test automation with selenide
 
Automating Django Functional Tests Using Selenium on Cloud
Automating Django Functional Tests Using Selenium on CloudAutomating Django Functional Tests Using Selenium on Cloud
Automating Django Functional Tests Using Selenium on Cloud
 
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
 
PyUIA 0.3
PyUIA 0.3PyUIA 0.3
PyUIA 0.3
 
Selenium Overview
Selenium OverviewSelenium Overview
Selenium Overview
 
Python Testing 101 with Selenium
Python Testing 101 with SeleniumPython Testing 101 with Selenium
Python Testing 101 with Selenium
 
Selenium testing
Selenium testingSelenium testing
Selenium testing
 
Automation with Selenium Presented by Quontra Solutions
Automation with Selenium Presented by Quontra SolutionsAutomation with Selenium Presented by Quontra Solutions
Automation with Selenium Presented by Quontra Solutions
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
 
Component Based Unit Testing ADF with Selenium
Component Based Unit Testing ADF with SeleniumComponent Based Unit Testing ADF with Selenium
Component Based Unit Testing ADF with Selenium
 
Automated Testing ADF with Selenium
Automated Testing ADF with SeleniumAutomated Testing ADF with Selenium
Automated Testing ADF with Selenium
 
Breaking the limits_of_page_objects
Breaking the limits_of_page_objectsBreaking the limits_of_page_objects
Breaking the limits_of_page_objects
 
Selenide vs. Selenium: The War Of Technologies
Selenide vs. Selenium: The War Of TechnologiesSelenide vs. Selenium: The War Of Technologies
Selenide vs. Selenium: The War Of Technologies
 
Better Testing With PHP Unit
Better Testing With PHP UnitBetter Testing With PHP Unit
Better Testing With PHP Unit
 

Último

Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024The Digital Insurer
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Principled Technologies
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 

Último (20)

Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 

Selenide Alternative in Practice - Implementation & Lessons learned [SeleniumCamp 2016]