使用Selenium包做Web页面自动化测试详解

  • 简介

  • 使用方法

    • Chrome

    • Opera

    • Safari

    • 处理HTTP基本认证及摘要认证

    • 访问页面

    • 定位元素

    • 操作文本框元素

    • 操作表单元素

    • 操作select元素

    • 拖放元素

    • 在窗口和frame间切换

    • 处理弹窗

    • 历史记录前进及后退

    • cookie

    • 等待元素加载

    • 使用其他浏览器

    • 保存屏幕截图

    • 滚动至屏幕底部


载*请注明原始出处:http://blog.csdn.net/a464057216/article/details/52717464

简介

Selenium是ThoughtWorks公司为Web自动化测试开发的工具,除支持多种操作系统如Linux、Mac OS X、Windows外,还支持Chrome、Firefox、Safari、Opera、IE等多种浏览器,适合做Web应用的兼容性测试及自动化测试。在Web开发的持续集成中,如果每次迭代都采用手工方式对已有的功能进行回归测试,需要的人力、时间成本将是非常巨大的,采用Selenium进行自动化地回归测试,可以让团队的精力集中在新功能的测试上,提升工作效率。

本文主要介绍在Python中使用Selenium包进行自动化测试的方法,您需要具备一些HTML的知识及搭建Web服务器的方法,这样才能在学习的过程中亲手做实验,另外完整的示例代码放在我的github项目上,欢迎大家访问。首先使用pip install selenium命令安装Python的Selenium包。针对不同的浏览器及其版本使用Selenium的方法会有所不同,如下是我的版本信息:

  • 操作系统:Mac OS Sierra

  • Python: 2.7.10

  • Selenium: 2.53.6

  • Firefox: 47.0.1

  • Safari: 10.0

  • Opera: 39.0

  • Chrome: 53

使用方法

访问页面

Selenium运行自动化测试的方法是打开浏览器,按照脚本规定的步骤模拟人的操作,如点击按钮、在文本框输入文本等,然后检查期望结果。第一步就是要知道访问什么页面,比如测试使用Firefox访问百度:

# -*- coding: utf-8 -*-from selenium import webdriverfrom selenium.webdriver.common.keys import Keys# 目前支持的driver有Firefox, Chrome, IE和Remote等driver = webdriver.Firefox(executable_path="./geckodriver")# 直到页面被加载完(onload事件被触发)才将控制权返回脚本driver.get('https://www.baidu.com')assert u'百度一下,你就知道' in driver.titleprint u"当前URL:", driver.current_url1234567891011

对于使用了大量AJAX的页面,webdriver并不知道页面何时真正加载完成,这时需要使用waits告诉Selenium等待时间。

Webdriver是Selenium能够实现跨浏览器自动化测试的关键,通常简称wd。不同浏览器有不同的wd,但对外提供了统一的接口调用各个浏览器自身的自动化测试接口。上面Firefox的webdriver请在此下载

定位元素

打开页面后,第二件事情就是定位到我们要操作的页面元素,定位单个页面元素有如下方法(下面的方法,如果没有定位到相应的元素,抛出NoSuchElementException异常):

  • find_element_by_id:通过id属性定位元素(返回第一个匹配的)。

  • find_element_by_name:通过name属性定位元素(返回第一个匹配的)。

  • find_element_by_xpath:通过xpath定位元素(返回第一个匹配的)。

  • find_element_by_link_text:通过超链接文本定位超链接元素,必须是完全匹配(返回第一个匹配的)。

  • find_element_by_partial_link_text:通过超链接文本定位超链接元素,可以是部分匹配(返回第一个匹配的)。

  • find_element_by_tag_name:通过标签名字定位元素(返回第一个匹配的)。

  • find_element_by_class_name:通过class属性定位元素(返回第一个匹配的)。

  • find_element_by_css_selector:使用CSS选择器语法定位元素(返回第一个匹配的)。

上面的方法,对应的批量定位方法如下(返回对应网页元素的列表):

  • find_elements_by_name

  • find_elements_by_xpath

  • find_elements_by_link_text

  • find_elements_by_partial_link_text

  • find_elements_by_tag_name

  • find_elements_by_class_name

  • find_elements_by_css_selector

此外,webdriver还有find_elementfind_elements方法定位元素:

from selenium.webdriver.common.by import Bydriver.find_element(By.XPATH, '//button[text()="Some text"]')driver.find_elements(By.XPATH, '//button')1234

By对象含有如下属性:

  • ID :元素id属性。

  • XPATH:xpath。

  • LINK_TEXT :超链接文本。

  • PARTIAL_LINK_TEXT :部分超链接文本。

  • NAME :元素name属性。

  • TAG_NAME :元素标签名字。

  • CLASS_NAME :元素class属性。

  • CSS_SELECTOR :使用CSS元素选择器语法。

操作文本框元素

比如在百度的输入框查询信息:

elem = driver.find_element_by_name('wd')# 清空预填充内容elem.clear()# Keys对象表示键盘按键,如F1、ALT、ARROW_DOWN等elem.send_keys(u'48.HTTP基本认证与摘要认证', Keys.RETURN)assert u'Mars Loo的博客' in driver.page_source# quit方法关闭整个浏览器driver.quit()1234567891011

上传文件也可以采用send_keys方法,此时参数提供为文件的路径即可。

操作表单元素

定位到一个表单元素后,可以调用其submit方法提交表单:

form = ff.find_element_by_name('survey')
form.submit()12

如果调用submit方法的元素不是表单,抛出异常NoSuchElementException。提交表单也可以定位到提交按钮元素后,调用其click方法:

submit = ff.find_element_by_id('submit')
submit.click()12

操作select元素

# 采用xpath获取第一个select元素(即使有多个也返回第一个)element = ff.find_element_by_xpath("//select[@name='car']")# 获取所有选项,打印选项值并点击all_options = element.find_elements_by_tag_name("option")for option in all_options:    print "Value is: %s" % option.get_attribute("value")
    option.click()1234567

Selenium还提供了对<select>元素的抽象——Select对象:

from selenium.webdriver.support.ui import Select

select = Select(ff.find_element_by_xpath("//select[@name='car']"))
select.select_by_visible_text("infinity")
select.select_by_value("bmw")# 按照option的索引选择,第一个option的index为0select.select_by_index("0")1234567

对于允许多选以及有预选值的场景,可以做如下处理:

select = Select(ff.find_element_by_xpath("//select[@name='car']"))# 获取所有已选项print select.all_selected_options# 去选所有选项select.deselect_all()# 获取所有可选项print select.options1234567

拖放元素

selenium包目前还不支持HTML 5的拖放,一种解决方案是通过Javascript脚本及jQuery解决:

jquery_url = "http://upcdn.b0.upaiyun.com/libs/jquery/jquery-2.0.2.min.js"ff = webdriver.Firefox(executable_path="./geckodriver")
ff.get('http://html5demos.com/drag')

ff.set_script_timeout(30)with open("load_jquery.js") as f:
    load_jquery_js = f.read()with open("drag_and_drop.js") as f:
    drag_and_drop_js = f.read()
ff.execute_async_script(load_jquery_js, jquery_url)

ff.execute_script(drag_and_drop_js +                  "$('#one').simulateDragDrop({dropTarget:'#bin'});")1234567891011121314

load_jquery.jsdrag_and_drop.js请在我的github项目获取。

在窗口和frame间切换

在浏览器不同窗口之间切换的方法如下:

a = ff.find_element_by_tag_name("a")# 保存原始窗口,window_handlers是目前wd打开的所有窗口的句柄列表prev = ff.window_handles[-1]# 点击超链接(targe="_blank")后,浏览器新窗口被激活a.click()# 保存新窗口new = ff.window_handles[-1]# 切换到原始窗口ff.switch_to_window(prev)print "Switch to prev success"# 切换到新窗口ff.switch_to_window(new)print "Switch to new success"123456789101112131415161718

因为HTML 5中不再建议使用<frameset>标签,所以以<iframe>为例说明如何在框架间切换:

ff.switch_to_frame('frame1')
element = ff.find_element_by_name('wd')
element.clear()
element.send_keys("This is a test")# 切换到顶级frame,然后才可以切换到其他iframeff.switch_to_default_content()
ff.switch_to_frame('frame2')
element = ff.find_element_by_name('email')
element.clear()
element.send_keys("Input to Sohu")1234567891011

处理弹窗

Javascript的角度,弹窗分为三种:alert、confirm和prompt。使用webdriver的switch_to_alert方法可以将焦点切换到当前的弹窗上,并返回一个Alert对象。 
如果是alert类型的窗口,点击取消或者确定都可以关闭该窗口:

# 切换到当前弹出框并返回Alert对象alert = ff.switch_to_alert()# 获取弹出框的文本内容print "Alert text:", alert.text# 点击弹出框的确定按钮alert.accept()# 点击弹出框的取消按钮# alert.dismiss()12345678

如果是confirm类型的窗口,点击确定会给Javascript返回true,点击取消会给javascript返回false。如果是prompt类型的窗口,可以输入一段文本后再点击取消还是确定,如果点击取消会给Javascript返回null,如果点击确定会给Javascript返回输入的文本,因为弹出的prompt框默认会将其中可编辑的文本内容覆盖选中(见下图),所以Alert对象没有clear方法:

image.png

alert = ff.switch_to_alert()# 如果是prompt类型的弹出框,直接向其中输入内容alert.send_keys("This is my choice")# 然后点击prompt框的确定按钮alert.accept()123456

处理HTTP基本认证及摘要认证

HTTP基本认证和摘要认证的基本原理可以参考我的博文,这种认证弹窗不需要按照上面的方法处理,如果是Firefox浏览器,可以在浏览器中访问about:config进入配置界面将browser.safebrowsing.malware.enabled设置为true,此时Firefox就允许我们以scheme://username:password@domain/path?query#segment的形式访问网页了。设置好了以后,Selenium的脚本可以这样写:

ff = webdriver.Firefox(executable_path="./geckodriver")
ff.get('http://mars:loo@localhost:5000/')12

历史记录前进及后退

通过webdriver的backforward方法,可以很方便地在历史记录中前进及后退:

a = ff.find_element_by_tag_name('a')
a.click()print "Go back"ff.back()print "Go forward"ff.forward()123456

处理cookie时,需要webdriver先访问到合法的cookie域,添加cookie然后重新访问即可,比如(namevalue字段分别表示cookie的键和值):

 ff.get('http://localhost:5000/')
 ff.add_cookie({'name': 'username', 'value': 'marsloo'})
 ff.get('http://localhost:5000/') # 获取当前域的cookies
 print ff.get_cookies()12345

上述代码的输出可能为:

[{u'domain': u'localhost', u'name': u'username', u'value': u'marsloo', u'expiry': None, u'path': u'', u'httpOnly': False, u'secure': False}]1

等待元素加载

如果请求的页面使用了大量的AJAX,Selenium不会等待其请求完成后再将控制权交给脚本。为了正确定位到所需的元素,需要使用Selenium的等待功能,最简单的是这样:

# 对于所有元素获取,会等待3秒ff.implicitly_wait(3)try:
    a = ff.find_element_by_partial_link_text('g')
    a.click()except NoSuchElementException:    print "Page load fail or no such element"1234567

在每一个浏览器会话中只需要调用一次implicitly_wait方法。如果相对每个元素获取设置不同的超时时间,可以这样做(其他更详细的代码可以在我的github项目获取):

from selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.common.exceptions import TimeoutException@auto_closedef func():
    try:
        a = WebDriverWait(ff, 3).until(
            EC.presence_of_element_located((By.TAG_NAME, "p")))
        a.click()    except TimeoutException:        print "No such element"1234567891011121314

上述代码中的(By.TAG_NAME, "p")元组,在下面的解释中以locator参数代替。expected_conditions对象还有很多方法可以使用:

  • title_is(title):标题是title(完全匹配)。

  • title_contains(title):标题包含title(部分匹配)。

  • presence_of_element_located(locator):元素在DOM树上存在(但是不一定可见)。

  • visibility_of_element_located(locator):元素在DOM树上存在并且肉眼可见。

  • visibility_of(element):检查元素的肉眼可见性。

  • presence_of_all_elements_located(locator):元素们在DOM树上存在(但是不一定可见),locator返回的是元素的列表。

  • text_to_be_present_in_element(locator, text):某个元素的文本中是否包含text

  • text_to_be_present_in_element_value(locator, text):某个元素的value属性中是否包含text

  • frame_to_be_available_and_switch_to_it(locator):判断某个frame是否可操作,如果可以的话切换到该frame并返回True,否则返回False

  • invisibility_of_element_located(locator):元素不存在于DOM树或者不可见。

  • element_to_be_clickable(locator) :元素可见且是可点击状态。

  • staleness_of(element):元素从DOM树上移除。

  • element_to_be_selected(element):元素被选中。

  • element_located_to_be_selected(locator):元素被选中。

  • element_selection_state_to_be(element, bool):判断元素被选中的状体,bool参数中True表示选中,False表示未选中。

  • element_located_selection_state_to_be(locator, bool):判断元素被选中的状体,bool参数中True表示选中,False表示未选中。

  • alert_is_present:弹出了一个窗口。

使用其他浏览器

Chrome

使用Chrome进行测试,需要先下载Chrome Driver (可能需要翻墙),解压缩后代码如下:

driver = webdriver.Chrome(executable_path="./chromedriver")1

Opera

首先下载Opera Driver,解压缩后代码如下:

webdriver_service = service.Service('./operadriver')
webdriver_service.start()
driver = webdriver.Remote(webdriver_service.service_url,
                          webdriver.DesiredCapabilities.OPERA)

driver.get('https://www.baidu.com')1234567

Safari

Safari 10已经开始内置自动化测试的支持,Safari偏好设置->高级->在菜单栏中显示“开发”菜单,然后开发->允许远程自动化,最后下载Selenium Server的jar包,测试脚本如下:

# -*- coding: utf-8 -*-from selenium import webdriverimport timeimport os

os.environ["SELENIUM_SERVER_JAR"] = "selenium-server-standalone-2.53.1.jar"# 设置quiet模式,否则会打印很多logdriver = webdriver.Safari(quiet=True)
driver.get('https://www.baidu.com')assert u'百度一下,你就知道' in driver.titleprint u"当前URL:", driver.current_url
time.sleep(4)
driver.quit()123456789101112131415

保存屏幕截图

使用driver.save_screenshot(filename)可以保存浏览器的运行截图(默认是覆盖写入)。

滚动至屏幕底部

使用ff.execute_script("window.scrollTo(0, document.body.scrollHeight);")可以滚动至屏幕底部。


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864