Selenium实战教程系列(一)--- 浏览器操作

在这个系列的教程中,笔者将根据自己在多年的Selenium自动化测试开发过程中的实战经验,为各位朋友进行梳理和总结,提供一个实战性很强的教程。同时也欢迎各位朋友指出教程的不足之处,一起学习,一起进步。
话不多说,直接进入教程的第一个板块:浏览器操作。

浏览器的操作可以说是使用Selenium进行自动化开发中最基础的内容之一,任何用例的执行都离不开浏览器的操作,因为Selenium的原理就是通过代码实现对浏览器的控制和操作,从而达到模拟人在浏览器上执行测试用例的目的。
本教程以Ruby作为开发语言。

1.打开和关闭浏览器

打开浏览器

任何的一个测试用例,都需要打开一个浏览器的实体,然后才能进行下面的操作。需要注意的是需要提前安装好对应浏览器的Webdriver。

require 'selenium-webdriver'
# chrome
dr = Selenium::WebDriver.for :chrome
# firefox
dr = Selenium::WebDriver.for :ff
# ie
dr = Selenium::WebDriver.for :ie

Headless mode

在一些场景下测试工程师需要在不打开浏览器的情况下进行自动化测试,也就是以headless的方式运行自动化测试。
现在全球最受欢迎的浏览器Chrome在Chrome 59 (Chrome 60 for Windows)版本中已经支持了headless mode,只需要配置一些简单的参数就可以实现。

require 'selenium-webdriver'

options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--remote-debugging-port=9222')
driver = Selenium::WebDriver.for :chrome, options: options

driver.get "https://www.acitve.com"
driver.save_screenshot("#{File.dirname(__FILE__)}/#{Time.now.strftime("%F")}")

关闭浏览器

执行完操作后,必须保证浏览器被关闭。
关闭浏览器有两种方法:

close()

require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
sleep 5
puts '浏览器将被关闭'
dr.close()
puts '浏览器已经关闭'

quit()

require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
sleep 5
puts '浏览器将被关闭'
dr.quit()
puts '浏览器已经关闭'

两种方式的区别:

方法 区别
close 关闭当前的浏览器窗口
quit 不仅关闭窗口,还会彻底的退出webdriver,释放与driver server之间的连接

2.设置浏览器窗口大小

在执行用例的过程中,可能会需要对窗口的大小进行调整,以满足测试的要求,因为页面的布局在不同的浏览器窗口大小下会有不同的展示。
常用的设置主要是:

最大化窗口

require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
dr.maximize_window()

自定义窗口大小

require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
dr.set_window_size(240, 320)

通过设置不同的窗口大小,可以在浏览器上模拟不同场景的页面展示,例如设置一个移动端的分辨率,就可以看到在移动端的页面展示是否符合期望。

3.打开URL

Selenium中有两种打开URL的方法:

require 'selenium-webdriver'
dr = Selenium::WebDriver.for :chrome
url = 'http://www.acitve.com'
puts "now access #{url}"
#方法1:
dr.get url

#方法2:
dr.navigate.to url

这两种方法的区别在于:

方法 区别1 区别2
get 等待page load完成 无法进行前进后退操作
navigate.to 不会等待page load完成 可以保留浏览的历史,进行前进后退刷新操作

4.打印当前页面的title及URL

在验证当前页面的标题和URL时时,会需要用到这个功能

require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
url = 'http://www.acitve.com'
dr.get url
puts "The Title of current page is #{dr.title}"
puts "url of current page is #{dr.current_url}"

dr.quit

5.前进,后退和刷新

dr.navigate返回的Selenium::WebDriver::Navigation类的对象除了可以进行前面提到的to操作外,还可以进行前进,后退和刷新。

require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
url1 = 'http://www.acitve.com'
dr.navigate.to url
url2 = 'http://www.acitve.com/contactus'
dr.navigate.to url
puts "url of current page is #{dr.current_url}" #'http://www.acitve.com/contactus'

#返回
dr.navigate.back()
puts "url of current page is #{dr.current_url}" #'http://www.acitve.com'

#前进
dr.navigate.forward()
puts "url of current page is #{dr.current_url}" #'http://www.acitve.com/contactus'

#刷新
dr.navigate.refresh()
puts "url of current page is #{dr.current_url}" #'http://www.acitve.com/contactus'

6.设置等待

Selenium中有两种等待:隐式等待和显式等待。

  • 隐式等待:设置等待定位界面元素的时间。当等待时间超过设定值后,将抛出NoSuchElement异常。
# 如果3s内还定位不到则抛出异常
driver.manage.timeouts.implicit_wait = 3 # seconds
  • 显式等待:通过Selenium::WebDriver::Wait对象,设置一个等待的条件,条件成立时继续执行,超过timeout则抛出异常。
wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds 
wait.until { dr.find_element(class: 'label').displayed? }

7.切换窗口

在测试过程中有可能会有新窗口打开,这样就会有多个窗口同时出现,Selenium提供了方法实现多个窗口间的切换。

  • window_handleSelenium::WebDriver::Driver类的方法,返回当前window的handle。

  • window_handlesSelenium::WebDriver::Driver类的方法,返回全部window的handle数组。

  • switch_to.window(window_handle)实现跳转到指定window_handle的窗口

require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
dr.get 'http://the-internet.herokuapp.com/windows'
dr.find_element(css: '.example a').click

windows_array = dr.window_handles
puts "All windows are #{windows_array}"

dr.switch_to.window(windows_array.first)
puts "Current window is #{dr.window_handle}"

dr.switch_to.window(@driver.window_handles.last)
puts "Current window is #{dr.window_handle}"

8.执行JavaScript

在Selenium自动化测试的开发过程中,很多复杂的控制功能是原生API无法提供或解决的,这就需要用到执行JavaScript来帮助实现。Selenium也提供了接口让开发者在脚本中执行JS脚本。
下面的例子,将演示如何利用JS来实现操作元素的高亮显示。

# coding: utf-8
require 'selenium-webdriver'

def highlight(element, duration = 3)

  # 保留元素原有的style,以待方法执行完成后恢复
  original_style = element.attribute("style")

  # 给元素加一个红色的虚线边界
  $driver.execute_script(
    "arguments[0].setAttribute(arguments[1], arguments[2])",
    element,
    "style",
    "border: 2px solid red; border-style: dashed;")

  # 让元素的边界保留一段时间再恢复
  if duration > 0
    sleep duration
    $driver.execute_script(
      "arguments[0].setAttribute(arguments[1], arguments[2])",
      element,
      "style",
      original_style)
  end
end

begin
    $driver = Selenium::WebDriver.for :firefox
    $driver.get 'https://www.jianshu.com'
    highlight $driver.find_element(xpath: "//a[@class='logo']")
ensure
    $driver.quit
end

利用JS还可以实现很多复杂的功能,笔者将会在后续的教程中专门介绍。

9.处理Cookie

对于Web UI的自动化测试,对于Cookie的处理是比较常见的场景。
Selenium提供了完善的接口让开发者来对cookie进行处理。

  • 获取Cookie:获取全部cookieall_cookies和获取指定cookie cookie(name)
  • 添加Cookie:add_cookie(name: 'token', value: 'xxxxxx')
  • 删除Cookie:删除全部cookie delete_all_cookies 和 删除指定cookiedelete_cookie(name)
#encoding: utf-8
require 'selenium-webdriver'

dr = Selenium::WebDriver.for :chrome
url = 'http://www.acitve.com'
dr.get url

dr.manage.all_cookies
dr.manage.delete_all_cookies

#通过添加鉴权所需的cookie,可以完成登录的效果
dr.manage.add_cookie(name: 'userid', value: 'xxxxxx')
dr.manage.add_cookie(name: 'token', value: 'xxxxxx')

dr.get url

#删除一个鉴权需要的cookie后,登录将失效
dr.manage.delete_cookie('token')
dr.get url

dr.quit()

10.设置代理

在进行UI自动化的过程中,使用代理访问页面的场景也是比较常见的,在Selenium中,给浏览器设置代理主要是通过对profile的设置实现的。

require 'selenium-webdriver'
PROXY = 'localhost:8087'
profile = Selenium::WebDriver::Firefox::Profile.new
profile.proxy = Selenium::WebDriver::Proxy.new( 
    :http     => PROXY,  
    :ftp      => PROXY,  
    :ssl      => PROXY)
driver = Selenium::WebDriver.for :firefox, :profile => profile
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容