学习Selenium webdriver - ruby篇

写在前面

被selenium webdriver中的定位虐过,决定过一遍这方面的知识点,记录下踩过的坑。

好,来认识下selenium webdriver及其使用。

几个概念

  • Selenium

    Selenium is a set of different software tools each with a different approach to supporting test automation.

    一套用于进行浏览器自动化测试的开源工具集。selenium的一个重要特性是支持所有主流浏览器(chrome,Firefox,IE,Safari)。

    selenium产生于2004年,由Jason Huggins开发,起因是他为了解决每次更新应用时,需要手动测试带来的低效,他通过开发一个JavaScript的library,实现与页面进行交互,从而可以在多个浏览器之间实现测试自动化。而这个library最终成为了后来selenium的内核(Selenium Core)。

    selenium test支持的语言: Java, C#, Javascript,python,ruby

  • Webdriver

    06年,Google的一位工程师Simon Stewart开始着手一个项目,由于Selenium的起源是一个 JavaScript的library,Simon希望开发出一个可以直接与浏览器进行交互的测试工具,通过使用浏览器和操作系统的原生methods,以避免来自JavaScript环境的限制, 这个项目就是WebDriver,这也是webdriver的由来。

    你可以理解成它是一个开源项目,可以让用户编写各种操作代码,这些代码可以在主流浏览器上运行,与页面进行交互。

  • Selenium Webdriver

    08年,Selenium 与 Webdriver联姻,二者merge了。merge的原因?Simon Stewart的原话:

    ‘’Why are the projects merging? Partly because WebDriver addresses some shortcomings in selenium (by being able to bypass the JS sandbox, for example. And we’ve got a gorgeous API), partly because selenium addresses some shortcomings in WebDriver (such as supporting a broader range of browsers) and partly because the main selenium contributors and I felt that it was the best way to offer users the best possible framework’‘

    我简单地理解成各有千秋,互补增强。

使用

基本用法其实就是定位到页面指定的元素,然后对元素进行操作,比如单击、滚动、输入等等。

看一段简单的ruby代码:

# require selenium-webdriver module
require "selenium-webdriver"
# 打开一个Firefox的浏览器,也可以打开chrome,IE,将:firefox换成:chrome, :ie
driver = Selenium::WebDriver.for :firefox
# 打开网页
driver.navigate.to "http://www.google.com"
# 定位元素
element = driver.find_element(:name, 'q')
# 对元素进行操作
element.send_keys "Hello Selenium WebDriver!"
element.submit

定位及操作

find_element: 查找匹配到的第一个元素

find_elements: 查找匹配到的所有元素

在Selenium webdriver中,主要有以下几类:

  • ID

    通过ID来定位元素,ID是唯一的,通常较少变动,所以可以很准确地定位到指定元素。

    比如:

    element = driver.find_element(:id, "username")
    element.send_keys("admin")
    driver.find_element(:id, "submit").click
    
  • Name

    Name也是比较常用的定位方式

    element = driver.find_element(:name, "username")
    driver.find_element(:name, "comment").send_keys("my comments")
    
  • Link Text

    只用于超链接元素的定位

    driver.find_element(:link_text, "Cancel").click
    driver.find_element(:link, "Login")
    
  • Partial Link Text

    selenium 允许通过一部分的超链接文本来定位某个超链接,比如:

    # 点击到“cancel” 或者“Cancel”链接
    driver.find_element(:partial_link_text, "ancel").click
    
  • XPath

    Xpath 几乎可以定位到页面上的任何一个元素。XPath是XML path的简称,它有两种用法:

    • 绝对路径, 用”/“, 例如:/html/body/table[1]
    • 相对路径,用”//“

    例如:

    driver.find_element(:xpath, "//*[@id='div2']/input[@type='checkbox']").click
    driver.find_element(:xpath,"//input[@value='Sign in']")
    driver.find_element(:xpath, "//a[@href='/logout']").click
    

    一般不推荐用绝对路径,因为一旦页面结构发生变化,该路径随之失效。

  • Tag Name

    通过元素的标签名称来查找元素,不过这种方法找到的元素通常不止一个。

    driver.find_element(:tag_name, "body")
    driver.find_element(:tag_name, "body").text
    # 查看button的个数
    button_elems = driver.find_elements(:tag_name, "button")
    button_elems.count
    
  • Class Name

    这是利用元素的css样式表所引用的类名称来进行查找,不过当某个元素含有多个类时,不可以使用多个类来查找。

    例如如下的HTML:

    <a href="back.html" class="btn btn-default">Cancel</a>
    <input type="submit" class="btn btn-deault btn-primary">Submit</input>
    

    对应的元素定位:

    driver.find_element(:class, "btn-primary").click # Submit button
    driver.find_element(:class, "btn").click # Cancel link
    

    这里Cancel和Submit都有”btn”这个class,find_element会返回匹配到的第一个元素,所以driver.find_element(:class, "btn").click 点击的是cancel这个button。

    但是不允许指定多个class,下面这样的用法是错误的:

    driver.find_element(:class, "btn btn-deault btn-primary").click
    

    如果想要定位带有多个class的元素,怎么办?可以使用CSS Selector。

  • CSS Selector

    定位ID为login的元素下面的text,可以这么写:

    driver.find_element(:css, "#login > input[type='text']").click
    

    当需要指定多个属性值时,可以逐一加在后面,比如:

    driver.find_element(:css, "#login > input[type='text'][name = 'username']")
    

    而上面多个class的情况,可以这么写:

    driver.find_element(:css, "input.btn.btn-deault.btn-primary").click
    

小结:

看过一些前辈写的相关文章,里面提到定位的一些原则,比如:Xpath很强大,但是非常费时,需要扫描整个网页来定位,尽量少用。Css selector与xpath比较类似,但是执行速度要更快,有ID的尽量用ID,别浪费。

参考:

Selenium Tutorial: Locators

Selenium Documentation

另,推荐一个小册子:Selenium WebDriver Recipes in Ruby