TA Basics: Ruby gems - watir/selenium-webdriver/lapis_lazuli

In the "installation" blogpost, I mentioned that when you install lapis_lazuli, it also installs selenium-webdriver and watir. This blogpost I want to use to explain why I use the lapis_lazuli gem as well as a small comparison between the two to show you this added value. At the moment of writing I'm using lapis_lazuli 2.0.1, watir 6.10.0 and selenium-webdriver 3.7.0

Why I use the lapis_lazuli gem?

First a little background info. This gem is developed and maintained by a QA company called spriteCloud (my former employer). This is how I got introduced to this gem. The gem was first introduced on Mar 30th, 2015. I started to use it around november 2016. And on June 29th, 2017, they posted a blog with the title "Watir, Selenium and Cucumber on steroids". This explains lapis_lazuli in a nutshell, give it a read.
Now we have a basic understanding why lapis_lazuli was created, let's have a look at some of the differences and why I like the lapis_lazuli gem so much. Keep in mind that I'm giving it a "beginners" perspective. So if this is not detailed enough, maybe this blog is more your taste http://watirtight.com/2016/09/11/always-locate.html
Or wait for me to get into more details let say a bunch of blogposts later.

Differences and similarities

Start a browser and navigate to a url

While starting a browser and navigate to a url, there is not much difference. In online examples you will see that for watir usually they refer to the browser and in selenium examples they refer to the driver. 

http://www.seleniumhq.org/docs/03_webdriver.jsp#selenium-webdriver-s-drivers
  require 'selenium-webdriver'
  driver = Selenium::WebDriver.for :firefox #d = Selenium.... for examples below
  driver.navigate.to "http://google.com"

http://watir.com/guides/session/
  require 'watir'
  browser = Watir::Browser.new :firefox #b = Watir.... for examples below
  browser.goto "https://google.com"

http://www.testautomation.info/Lapis_Lazuli:Usage
  require 'lapis_lazuli'
  include LapisLazuli
  browser :firefox #b = browser.... for examples below
  browser.goto "https://google.com"

Finding an element

  d.find_element(:id, "lst-ib")
  d.find_element(:xpath, '//input[@id='/lst-ib']')

Watir find an element

  b.element(id: 'lst-ib')
  b.input(id: 'lst-ib')
  b.element(:xpath,"//*[@id='lst-ib']")

LL find an element

  These all work, but most of the times I use the third example
  b.find({:id => 'lst-ib'})
  b.find(:input => {:id => 'lst-ib'})
  #XPath translation Short notation
  b.find(:like => [:input, :id, 'lst-ib']) 
  # XPath translation Full notation
  b.find(:like => [
    :element => :input, 
    :attribute => :id, 
    :include => 'lst-ib'
  ])

Waiting for an element

Selenium wait for an element
Explicit wait
  wait = Selenium::WebDriver::Wait.new(:timeout => 10) #seconds
  wait.until { d.find_element(:id => "lst-ib") }

Implicit wait
  d.manage.timeouts.implicit_wait = 3 #seconds
  d.find_element(:id => "lst-ib")

Watir wait for an element
Explicit wait
  default timeout is 30 seconds
  b.input(id: 'lst-ib').wait_until_present #wait until something is present
  b.input(id: 'lst-ib').wait_while_present #wait until something disappears

Implicit wait
  b.driver.manage.timeouts.implicit_wait = 3 #seconds
  b.input(id: 'lst-ib').wait_until_present #will now wait for only 3 seconds

LL wait for an element

Although this does work, I don't recommend it because of some issues with :condition and :timeout (which we use later).
  b.wait({:id => 'lst-ib'}) 
Instead use it as shown below

Explicit wait 
  default timeout is 10 seconds
  b.wait(:like => [:input, :id, 'lst-ib']) #wait until something is present

Implicit wait
  b.wait(:like => [:input, :id, 'lst-ib']) :timeout => 3) #seconds

LL Condition => Until / While
The :condition option is only used in wait functions (not in find). The default is :until
  b.wait(:like => [:input, :id, 'lst-ib']) #wait until something is present
  b.wait(:like => [:input, :id, 'lst-ib'], :condition => :until) #same as above
  b.wait(:like => [:input, :id, 'lst-ib'], :condition => :while) #wait while something is present

Context


Sometimes as a tester you find yourself in the position that there are not enough unique attributes to an element to select it directly. Meaning you might need to first select a unique parent element, before you can start selecting/searching for the element you actually need. In lapis_lazuli this is done with the :context option. This is one of my most used options since (again) the Edge browser handles things slightly different than Chrome/FF. 



Selenium

  elm_parent = d.find_element(:class, "jsb")

  target_elm = elm_parent.find_element(:xpath, "//input[@name='btnK']")


Watir
  elm_parent = b.div(class: "jsb")
  target_elm = elm_parent.input(name: "btnK")

LL :context option
  elm_parent = b.find(:div => {:class => 'jsb'}) 
  target_elm = b.find(:like => [:input, :name, 'btnK'], :context => elm_parent)


The only lesson learned I want to add here is that for the Edge browser. There are some "edge" cases (pun intended), a lessons learned blog will follow later, and one of those is with the :context option. For the edge browser you should locate the context element by doing it this way:
  elm_parent = b.find(:like => [:div, :class, 'jsb'])
If you don't, it will not be used as a context (Edge only), but also does not give an error in LL if it finds any element that is matching the target_elm search, so it could select the wrong target element. 

Why I like the lapis_lazuli gem

I've given you some examples and it could be that you are still not convinced why you should use lapis_lazuli over watir or even over selenium-webdriver. So let me try to convince you to try out this gem. 
In the background LL is using Watir and Watir is using Selenium-webdriver. So why not choose selenium-webdriver? If you use Ruby as a language I would already skip selenium-webdriver since it's less readable (at least for me as a non-programmer). Then you might say that Watir is actually readable enough. Fair point and very true. So let me tell you why I like LL over Watir. 
Along the way I started to notice that in some cases for me as a non-developer, LL was just easier. Besides the wording, 'wait' is similar to 'find'. Also it's easy to increase/lower the timeout time for one element which I found super useful for my project. But basically I just liked the extra options >>listed here<< which I find easy to use and more convenient/redeable than Watir's way of doing the same. Another thing that should not hold you back from giving it a try is that while searching on the internet, there will almost be no examples of using lapis_lazuli, but the links from this blog give you most of the help you need. And otherwise just search for a Watir example, which 99/100 times you can easily convert into the lapis_lazuli way if you cannot use it as is. There are a couple of more things I like about this gem, but those will automatically be covered in the upcoming posts, so stay tuned.

That's it for now, what's next?

I hope this was helpful enough for you to see the differences between the gems. As well as enough links to information so you can start some browser interaction via irb yourself. In case you are missing information or would like to see something being explained a bit more into details, feel free to comment. The next blogpost will be dedicated to writing scenario's using Gherkin which we will need for the blogpost after that where we will go into the details of creating your own test suite and running it.

A collection of blogposts and other useful links

Selenium-webdriver

Most of the selenium-webdriver blog's are related to Java and I have no specific favorite so if anyone has good suggestions, feel free to mention them in the comments. I sometimes did look at Java examples to guess what I needed to do in Ruby. It's not perfect but it works https://simpleprogrammer.com/2017/09/25/9-blogs-learn-selenium-webdriver/
For just some element information, this is a useful page: 
https://gist.github.com/huangzhichong/3284966#file-selenium-webdriver-cheatsheet-md

Watir

For watir there are a bunch of good blog's mentioned at the bottom of this page (I personally like Alister Scott's and Justin Ko's blog's): http://watir.com/community/ 
Titus also has a blog which I already mentioned at the top of this post, but I'm actually surprised it's not in the list on the watir.com website.
For just some element information, this is a useful page (otherwise Google it): 
http://watir.com/guides/elements/

LapisLazuli

Besides mine, from time to time, a new blog post appears on spriteCloud's website: https://www.spritecloud.com/?s=lapis_lazuli
But most of the documentation/information can also be found on the testautomation.info website: http://www.testautomation.info/Lapis_Lazuli:Selecting_an_element

Comments

Popular posts from this blog

PowerShell - How to overcome Azure VM's fixed resolution limitation

TA Basics: Website Test Automation on mobile devices via Appium server

TA: Who doesn't like proxies? Me!