在这个系列的教程中,笔者将根据自己在多年的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_handle
是Selenium::WebDriver::Driver
类的方法,返回当前window的handle。 -
window_handles
是Selenium::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:获取全部cookie
all_cookies
和获取指定cookiecookie(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