1、selenium介绍css
selenium主要用于web应用程序的自动化测试,还支持全部基于web的管理任务自动化。html
selenium经历了2个版本,selenium1.0和selenium2.0;selenium不是一个单独的工具,而是由一些插件、类库构成,每一个组成部分都有其特色和应用场景。前端
selenium2.0由如下组件构成:python
selenium2.0 = selenium1.0 + Webdriverweb
Webdirver:经过原生浏览器支持或扩展来直接控制浏览器,针对各个浏览器开发,与浏览器紧密集成,支持建立更高级的测试,其还能够利用操做系统级的调用,模拟用户输入;chrome
selenium IDE:嵌入到Firefox浏览器中的一个插件,实现简单的浏览器操做录制与回放功能,主要用于快速建立BUG及重现脚本,可转化为多种语言;编程
selenium Gird:测试辅助工具,利用现有的计算机基础设施,实现多台计算上和异构环境中运行测试用例;设计模式
selenium RC:selenium的核心组件,支持多种不一样语言编写自动化测试脚本,经过其服务器做为代理服务器去访问应用,达到测试的目的;浏览器
Client Libraries:Client Libraries库主要用于编写测试脚本,用来控制Selenium Server的库;安全
Selenium Server:负责控制浏览器行为;
Selenium Core(一个JavaScript函数集合):被嵌入到浏览器中,经过它实现用程序对浏览器进行操做;
Launcher:用于启动浏览器,把Core加载到浏览器页面当中,并把浏览器代理设置为Selenium Server的HTTP Proxy;
2、环境搭建
一、安装python
登陆Python官网,找到download,选择与自身平台(Windows/Linux)相符的版本下载(建议3.5+),而后安装便可;
注意:安装时选择安装界面的“Add Python 3.x to PATH”进行勾选,避免再次配置环境变量;
安装完成后经过Windows命令提示符CMD输入“python”,查看是否安装成功,以下图所示:
如上图所示,则证实安装成功;
二、安装setuptools与pip
setuptools是PEAK(Python enterprise Application Kit)的一个副项目,是python的distutilsde的加强工具,能够更方便建立和发布python包,特别是对其余包有依赖的状况;
pip是一个安装和管理python包的工具,经过pip来安装python包将变得很简单,省去了繁琐的过程,pip的安装依赖于setuptools,安装pip以前须要先安装setuptools;
注意:python目前不支持setuptools,所以须要使用distribute;
setuptools与pip的下载地址以下:
setuptools:https://pypi.python.org/pypi/setuptools
pip:https://pypi.org/project/pip/
注意: 最新版的python安装包中已经集成了pip,能够在安装目录下的script路径下查看是否有pip.exe或pip3.exe文件,若是有,则cmd命令行中输入pip进行验证;
如上图所示,则证实已经安装pip;
三、安装selenium
完成上面2个步骤以后,能够经过cmd命令直接安装selenium包,以下图所示:
注意:安装时若是只输入包名,则默认安装当前库中的最新版本,若是想安装本身须要的版本,则须要在包名后面加上版本号,好比:
pip install selenium==2.48.0
四、下载浏览器驱动
前面说过,selenium支持多种浏览器,因此只须要下载对应的浏览器驱动,将解压获得的exe文件放到python的安装目录下便可;
各个浏览器驱动下载地址:https://www.seleniumhq.org/download/
五、调试
打开一款python编译器,输入下面的代码,运行,查看是否成功调用浏览器运行,若是运行成功,则说明已成功搭建好自动化开发环境;
1、WebDriver原理
一、关于WebDriver
设计模式:按照Server-Client的经典设计模式设计;
Server端:即Remote Server(远程服务器),能够是任意的浏览器,当脚本启动浏览器时,该浏览器就是Remote Server,它的职责是等待Client发送请求并作出响应;
Client端:简单来讲就是咱们的测试代码,测试代码中的一些行为是以HTTP请求的方式发送给被测试浏览器——Remote Server,Remote Server接受请求,执行相应操做,
并在Response中返回执行状态、返回值等信息;
二、WebDriver工做流程
①WebDriver启动目标浏览器,并绑定至指定端口,启动的浏览器实例将做为WebDriver的Remote Server;
②Client端经过CommandExcuter发送HTTPRequest给Remote Server的侦听端口(通讯协议:the webdriver wire protocol);
③Remote Server须要依赖原生的浏览器组件(好比:chromedriver.exe)来转化浏览器的native调用;
三、WebDriver.log
python提供了logging模块给运行中的应用,提供了一个标准的信息输出接口。它提供了basicConfig方法用于基本信息的定义,开启debug模块,
就能够捕捉到Client端向Server端发送的请求,例子以下:
1 # coding=utf-8 2 # 导入logging模块,捕捉Client发送的请求 3 from selenium import webdriver 4 import logging 5 from selenium import webdriver 6 from selenium.webdriver.support.select import Select # select类 7 from selenium.webdriver.common.by import By #By类:定位元素 8 9 logging.basicConfig(level=logging.DEBUG) 10 driver = webdriver.Chrome("F:\安装工具\python\chromedriver.exe") 11 driver.get("www.baidu.com") 12 13 driver.find_element_by_id("kw").send_keys("selenium") 14 driver.find_element_by_id("su").click() 15 driver.quit()
2、WebDriver定位方法
WebDriver是基于selenium设计的操做浏览器的一套API,针对多种编程语言都实现了这套API,站在python角度来讲,WebDriver是python的一个用于实现Web自动化的第三方库。
一、WebDriver定位方法
WebDriver定位方法提供了八种元素定位方法,所对应的方法、特性分别是:
二、XPath和CSS的相似功能对比
三、用By定位元素
针对前面介绍的8种定位方法,WebDriver还提供另外一种方法,即:统一调用find_element()方法,经过By来声明定位方法,而且传入对应定位方法的定位参数,例子以下:
find.element()方法只用于定位元素,它须要两个参数,第一个参数是定位的类型,由By提供,第二个参数是定位的具体方式,在使用By以前须要将By类导入;
# 导入By类的包 from selenium.webdriver.common.by import By find.element(by.id,"kw") find.element(by.name,"wd") find.element(by.class_name,"s_ipt") find.element(by.tag_name,"input") find.element(by.link_text,"新闻") find.element(by.partial_link_text,"新") find.element(by.xpath,"//*[@class='bg s_btn'") find.element(by.css_selector,"span.bg s_btn_wr>input#su")
四、定位一组元素
上面提到的8种定位方法,都是针对单个元素定位的,webdriver还提供了与之对应的8种用于定位一组元素的方法。其通常应用于如下场景:
①批量操做元素,例如勾选页面上全部的复选框;
②先获取一组元素,再从这组元素中过滤出须要操做的元素;
定位一组元素的方法与定位单个元素的用法类似,惟一的区别是在element后面多一个s表示复数,具体以下:
# webdriver提供的定位一组元素方法 id find_elements_by_id() Name find_elements_by_name() class_name find_elements_by_class_name() tag Name find_elements_by_tag_name() link text find_elements_by_link_text() partial link text find_elements_by_partial_link_text() xpath find_elements_by_xpath() css selector find_elements_by_css_selector()
获取一组元素中某个元素的几个方法:
len():用来计算元素的个数,经过print()打印出计算的结果;
pos()或pop(-1):默认获取一组元素的最后一个元素,并返回该元素的值;
pop(0):默认获取一组元素的第一个元素,并返回该元素的值;
pop(1):默认获取一组元素的第二个元素,并返回该元素的值;
......
3、WebElement接口经常使用方法
一般须要与页面交互的方法都由WebElement接口提供,包括上面提到的8种定位方法,下面介绍经常使用的几种方法:
submit():用于提交表单,例如搜索框输入关键字以后的“回车”操做,例如:
# 提交表单 from select import webdriver driver = webdriver.Chrome("安装工具\python\chromedriver.exe") driver.get("http://www.baidu.com") driver.find_element_by_id("kw").send_keys("imyalost") # 提交输入框中的内容 driver.find_element_by_id("imyalost").submit() driver.quit()
注意:有时候submit()方法和click()方法能够互用,但submit()的应用范围不及click()普遍;
clear():清除文本;
send_keys(*value):模拟按键输入;
click():单击元素;
size:返回元素的尺寸;
text:获取元素的文本;
get.attribute(name):得到属性值;
is_displayed():设置该元素是否用户可见;
# webelement接口经常使用方法 from selenium import webdriver driver = webdriver.Chrome("安装工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 得到输入尺寸 size = driver.find_element_by_id("kw").size print("size") # 返回百度页面底部备案信息 text = driver.find_element_by_id("cp").text print("text") # 返回元素的属性值,能够是id、name、type或其余属性 attribute = driver.find_element_by_id("kw").get_attribute("type") print("attribute") # 返回元素结果是否可见,返回结果为True或Flase result = driver.find_element_by_id("kw").is_displayed() print("result")
1、控制浏览器
webdriver主要提供操做页面上各类元素的方法,但它也提供操做浏览器的一些方法,例如控制浏览器大小、前进和后退等。
一、控制浏览器窗口大小
# 控制浏览器大小 from selenium import webdriver driver = webdriver.Chrome("安装工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 参数数字为像素点 print("设置浏览器宽480、高800显示") driver.set_window_size(480,800)
二、全屏显示
webdriver提供了maximize_window()方法使打开的浏览器全屏显示,其用法与set_window_size()相同。
三、控制浏览器前进、后退
如今的浏览器在浏览网页时都提供了前进和后退功能,webdriver也提供了对应的forward()和back()方法,来模拟前进和后退按钮:
# 控制浏览器前进、后退 from selenium import webdriver driver = webdriver.Chrome("安装工具\python\chromedriver.exe") # 访问百度首页 first_url='http://www.baidu.com'' print("now access %s "%(first_url)) driver.get(first_url) # 访问新闻页面 second_url='http://www.news.baidu.com' print("now access % s "%(second_url)") driver.get("second_url") # 后退到百度首页 print("back to %s "%(first_url)") driver.back() # 前进到新闻页 print("forward to %s "%(second_url)") driver.forward()
为了看清脚本执行过程,每一步的操做都经过print()打印当前的URL地址,执行结果以下:
now access http://www.baidu.com
now access http://news.baidu.com
back to http://www.baidu.com
froward to http://news.baidu.com
四、模拟浏览器前刷新
通常咱们刷新页面都是经过F5或者页面上的刷新按钮,webdriver也提供了刷新方法refresh(),用来模拟页面刷新:
......
# 刷新当前页面
driver.refresh()
......
2、鼠标事件
在webelement接口提供的方法中,能够经过click()来模拟鼠标单击操做,但实际上鼠标交互方式不少,例如:右击、悬停、鼠标拖动等功能;
webdriver提供了ActionChains类,封装了鼠标操做的经常使用方法:
perform():执行全部的ActionChains中存储的行为
context_click():鼠标右击
double_click():鼠标双击
drag_and_drop():鼠标拖动
move_to_element():鼠标悬停
一、鼠标右击操做
# 鼠标右击操做 from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains driver = webdriver.Chrome("安装工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 定位到要右击的元素 right_click = driver.find_element_by_id("KW") # 对定位到的元素执行鼠标右击操做 ActionChains(driver).context_click(right_click).perform() ...
二、鼠标悬停
鼠标悬停弹出下拉菜单也是一个十分常见的功能设计,move_to_element()方法能够模拟鼠标悬停动做,其用法与context_click()相同;
1 # 鼠标悬停 2 ... 3 above = driver.find_element_by_id("id") 4 ActionChains(driver).move_to_element(above).perform() 5 ...
三、鼠标双击操做
double_click()方法用于模拟鼠标双击操做;
1 # 鼠标双击操做 2 ... 3 double_click = driver.find_element_by_id("id") 4 ActionChains(driver).double_click(double_click).perform() 5 ...
四、鼠标拖放操做
drag_and_drop(source,target)在源元素上按住鼠标左键,而后移动到目标元素上释放;
source:鼠标拖动的源元素
target:鼠标释放的目标元素
# 定位元素的位置 ... element = driver.find_element_by_id("id") # 定位元素要移动到的目标位置 target = driver.find_element_by_id("xx") # 执行元素的拖放操做 ActionChains(driver).drag_and_drop(element,target).perform() ...
3、键盘事件
Keys()类提供了键盘上几乎全部的按键方法,send_keys()不见能够模拟键盘输入,还能够用来输入键盘上的按键,甚至是组合键,例子以下:
# 模拟键盘事件 from selenium import webdriver # 引入keys模块 from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome("安装工具\python\chromedriver.exe") driver.get("http://www.baidu.com") # 输入框输入内容 driver.find_element_by_id("kw").send_keys("selenium") # 输入“教程” driver.find_element_by_id("kw").send_keys("教程") # 删除“教程” driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE) ...
如下为经常使用的键盘操做:
# 经常使用的键盘操做 send_keys(Keys.BACK_SPACE) send_keys(Keys.SPACE) send_keys(Keys.TAB) send_keys(Keys.ESCAPE) send_keys(Keys.ENTER) send_keys(Keys.CONTROL,'a') send_keys(Keys.CONTROL,'c') send_keys(Keys.CONTROL,'v') send_keys(Keys.CONTROL,'x') send_keys(Keys.F1) ... send_keys(Keys.F12)
以上为webdriver的控制浏览器操做以及模拟键盘、鼠标操做的经常使用方法,固然具体在实际使用过程当中,还须要结合实际的业务场景,灵活运用
在编写自动化测试脚本时,为了使“机器”去自动辨识test case的执行结果是True仍是False,通常都须要在用例执行过程当中获取一些信息,来判断用例的执行时成功仍是失败。
判断成功失败与否,就涉及到断言。webdriver的断言使用有三种模式:操做(action)、辅助(accessors)、断言(assertion)。
一、操做(action)
模拟用户与Web应用程序的交互,通常用于操做应用程序的状态;
如点击连接,选择选项的方式进行工做;若是一个动做执行失败,或是有错误,当前的测试将会中止执行。
常见命令以下:
open(打开页面)
click(点击)
clickAndWait(点击并等待)
type(文本类型)
select(选择下拉菜单)
selectWindow(选择弹出窗口)
pause(等待指定时间,以毫秒为单位,即要睡眠的时间)
setSpeed(设定执行速度。以毫秒延迟间隔长度。默认没有延迟,即为0)
setTimeout(指定等待动做完成的等待时间。默认为30秒,须要等待的动做包括了OPEN 和WAITFOR)
goBack(模拟用户点击其浏览器上的“back”按钮)
close(模拟用户点击弹出窗体或表单标题栏上的”关闭”按钮)
二、辅助(accessors)
辅助工具,用于检查应用程序的状态并将结果存储到变量中;
如:storeElementPresent(locator,variableName)
其中参数locator表示元素定位器,variableName用于存储结果的变量名;
即将locator定位到的状态存储到variableName变量中,若是该元素出现返回true,不然返回false,可同断言一同使用。
三、断言(assertion)
验证应用程序的状态是否同所指望的一致。
常见的断言包括:验证页面内容,如标题是否为X或当前位置是否正确,或是验证该复选框是否被勾选。
经常使用断言以下:
assertLocation(判断当前是在正确的页面)
assertTitle(检查当前页面的title是否正确)
assertValue(检查input的值, checkbox或radio,有值为”on”无为”off”)
assertSelected(检查select的下拉菜单中选中是否正确)
assertSelectedOptions(检查下拉菜单中的选项的是否正确)
assertText(检查指定元素的文本)
assertTextPresent(检查在当前给用户显示的页面上是否有出现指定的文本)
assertTextNotPresent(检查在当前给用户显示的页面上是否没有出现指定的文本)
assertAttribute(检查当前指定元素的属性的值)
assertTable(检查table里的某个cell中的值)
assertEditable(检查指定的input是否能够编辑)
assertNotEditable(检查指定的input是否不能够编辑)
assertAlert(检查是否有产生带指定message的alert对话框)
waitForElementPresent (等待检验某元素的存在,为真时,则执行)
使用断言的注意点:
①不要使用断言做为公共方法的参数检查,公共方法的参数永远都要执行;
②断言语句不能够有任何边界效应,不要使用断言语句去修改变量和改变方法的返回值;
在UI自动化测试中,有时候会遇到页面元素没法定位的问题,包括xpath等方法都没法定位,是由于前端元素被设置为不可见致使。
一、具体问题
常见的页面元素不可见致使的不可定位,都是因为下面的问题:
经过查看相关文档,能够看出display:none方法是设置元素不可见,这就是致使为何经过定位页面元素没法定位的缘由。
二、解决方案
对于这种问题,能够经过JavaScript修改页面元素属性来将元素置位可见,而后经过id、classname等方法去定位,示例代码以下(针对上图所示):
js = "document.getElementById(\"txtPassword\").style.display='block';" # 调用js脚本 driver.execute_script(js) sleep(3) driver.find_element_by_id("txtPassword").send_keys("123456")
代码解析:
首先经过selenium封装好的方法document去找到display元素,document提供如下方法来定位display元素:
getElementById():返回对指定ID第一个对象的引用
getElementsByName() :返回带有指定名称的对象集合
getElementsByTagName():返回带有指定标签名的对象集合
上面我定义了一个js变量,而后经过getElementById()方法去引用display元素,修改none属性为block属性(做为块级元素显示),而后经过selenium自带的execute_script方法执行脚本。
最后,当元素属性置为可见时,能够经过ID去定位元素。
其实还有一个解决方案:让前端修改display:none为block就行了,但这样的话,带来的变化和安全风险又是须要考虑的问题。一个问题的解决老是伴随着新的问题,核裂变了解一下?
想起今天和同行聊天时提及的分裂BUG的话题,对话以下:
大佬N:核裂变的原理是经过中子撞击原子核产生多个新的原子核,原子核是已有的BUG,中子是修改BUG加上的代码,分裂以后这个bug消失了,取而代之的是更多的原子核(BUG)。。。
我:引发一个BUG的缘由多是多个,修改一段代码可能形成多个BUG,就像用新技术解决旧问题而带来的新问题一个意思。。。
自动化自己最大的挑战仍是变化,所以从分层测试角度结合公司项目具体状况,考虑解决问题的方法,才是最好的选择。
在利用selenium进行UI自动化测试过程当中,常常会遇到下拉框选项,这篇博客,就介绍下如何利用selenium的Select模块来对标准select下拉框进行操做。。。
首先导入Select模块:
1 # coding=utf-8 2 from selenium import webdriver 3 from selenium.webdriver.support.select import Select
感兴趣的能够将鼠标指向Select,而后按住Ctrl鼠标单击,查看Select模块的源码,是如何定义封装Select的各个方法的。
一、Select提供了三种选择某一项的方法
1 select_by_index # 经过索引定位 2 select_by_value # 经过value值定位 3 select_by_visible_text # 经过文本值定位
注意事项:
index索引是从“0”开始;
value是option标签的一个属性值,并非显示在下拉框中的值;
visible_text是在option标签中间的值,是显示在下拉框的值;
二、Select提供了三种返回options信息的方法
1 options # 返回select元素全部的options 2 all_selected_options # 返回select元素中全部已选中的选项 3 first_selected_options # 返回select元素中选中的第一个选项
注意事项:
这三种方法的做用是查看已选中的元素是不是本身但愿选择的:
options:提供全部选项的元素列表;
all_selected_options:提供全部被选中选项的元素列表;
first_selected_option:提供第一个被选中的选项元素;
三、Select提供了四种取消选中项的方法
1 deselect_all # 取消所有的已选择项 2 deselect_by_index # 取消已选中的索引项 3 deselect_by_value # 取消已选中的value值 4 deselect_by_visible_text # 取消已选中的文本值
注意事项:
在平常的web测试中,会常常遇到某些下拉框选项已经被默认选中,这种时候就须要用到这里所说的四种方法;
下面以实际的代码来作个示例,被测试网页与源码截图以下:
好比要选择3线,那么三种选择方法示例代码以下:
# coding=utf-8 from selenium import webdriver from selenium.webdriver.support.select import Select from time import sleep # 登陆 driver = webdriver.Chrome() ...... # 根据索引选择 Select(driver.find_element_by_name("storeDeclare.cityLine")).select_by_index("3") # 根据value值选择 Select(driver.find_element_by_name("storeDeclare.cityLine")).select_by_value("3线") # 根据文本值选择 Select(driver.find_element_by_name("storeDeclare.cityLine")).select_by_visible_text("3线") sleep(5) driver.quit()
以上就是关于selenium的Select模块提供的几种方法的用法,示例代码只是示例,具体实践还须要结合实际的工做须要来进行
UI自动化测试,大多都是经过定位页面元素来模拟实际的生产场景操做。但在编写自动化测试脚本中,常常出现元素定位不到的状况,究其缘由,无非两种状况:一、有frame;二、没有设置等待。
由于代码运行速度和浏览器加载渲染速度,不是一个量级,因此致使了这种状况发生。webdriver提供了3种类型的等待:显式等待、隐式等待、强制等待。
一、显示等待
定义:等待某个条件成立时继续执行,不然在达到最大时长时抛出异常(TimeoutException);
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None) driver:浏览器驱动 timeout:最长超时时间 poll_frequency:检测间隔时间,默认0.5s ignored_exceptions:超时后的异常信息,默认状况抛出NoSuchElementException异常 WebDriverWait()通常由until()或until_not方法配合使用,下面是这两种方法的说明: until(method,message=''):调用该方法提供的驱动程序做为一个参数,直到返回值为True; until_not(method,message=''):调用该方法提供的驱动程序做为一个参数,直到返回值为Flase;
示例代码以下:
# coding = utf-8 from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome("F:\安装工具\python\chromedriver.exe") driver.implicitly_wait(10) driver.get('http://www.cnblogs.com/imyalost/') locator = (By.LINK_TEXT, '老_张') try: WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator)) print(driver.find_element_by_link_text('老_张').get_attribute('href')) finally: driver.close()
代码解析:
本例中,经过as关键字将expected_conditions重命名为EC,并调用presence_of_element_located()方法判断元素是否存在;
上面的例子中,同时使用了隐性等待和显性等待,可是须要注意的是:等待的最长时间取二者之中的最大值;
title_is: 判断当前页面的title是否彻底等于(==)预期字符串,返回布尔值 title_contains : 判断当前页面的title是否包含预期字符串,返回布尔值 presence_of_element_located : 判断某个元素是否被加到了dom树里,并不表明该元素必定可见 visibility_of_element_located : 判断某个元素是否可见. 可见表明元素非隐藏,而且元素的宽和高都不等于0 visibility_of : 跟上面的方法作同样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就行了 presence_of_all_elements_located : 判断是否至少有1个元素存在于dom树中。举个例子,若是页面上有n个元素的class都是‘column-md-3‘,那么只要有1个元素存在,这个方法就返回True text_to_be_present_in_element : 判断某个元素中的text是否 包含 了预期的字符串 text_to_be_present_in_element_value : 判断某个元素中的value属性是否 包含 了预期的字符串 frame_to_be_available_and_switch_to_it : 判断该frame是否能够switch进去,若是能够的话,返回True而且switch进去,不然返回False invisibility_of_element_located : 判断某个元素中是否不存在于dom树或不可见 element_to_be_clickable : 判断某个元素中是否可见而且是enable的,这样的话才叫clickable staleness_of : 等某个元素从dom树中移除,注意,这个方法也是返回True或False element_to_be_selected : 判断某个元素是否被选中了,通常用在下拉列表 element_selection_state_to_be : 判断某个元素的选中状态是否符合预期 element_located_selection_state_to_be : 跟上面的方法做用同样,只是上面的方法传入定位到的element,而这个方法传入locator alert_is_present : 判断页面上是否存在alert
二、隐式等待
定义:经过设定的时长等待页面元素加载完成,再执行下面的代码,若是超过设定时间还未加载完成,则继续执行下面的代码(注意:在设定时间内加载完成则当即执行下面的代码);
隐式等待的方法为:implicitly_wait,示例代码以下:
# coding = utf-8 from selenium import webdriver driver = webdriver.Chrome("F:\安装工具\python\chromedriver.exe") driver.implicitly_wait(10) # 隐性等待,最长等10秒 driver.get('http://www.cnblogs.com/imyalost/') print(driver.current_url) driver.quit()
代码解析:
本例中,设置的等待时长为10秒,但这10秒并不是一个固定时间,并不影响脚本执行速度;其次,隐式等待对整个driver的周期都起做用,所以只须要设置一次便可。
三、强制等待
即sleep()方法,由python中的time模块提供,强制让代码等待xxx时间,不管前面的代码是否执行完成或者还未完成,都必须等待设定的时间。
示例代码以下:
# coding = utf-8 from selenium import webdriver from time import sleep driver = webdriver.Chrome("F:\安装工具\python\chromedriver.exe") driver.get('http://www.cnblogs.com/imyalost/') sleep(5) print(driver.current_url) driver.quit()
代码解析:
本例中,设置强制等待时间为5秒,5秒以后,打印获取到的当前页面的url,而后关闭窗口。
这种强制等待的方法,在debug时候颇有用,不过建议慎用这种方法,由于太死板,严重影响程序执行速度!
以上三种等待方法,在具体的场景中须要根据状况选择合适的方法,灵活运用。。。
自动化测试过程当中,得到用例的执行结果后,须要有具象化、简洁明了的测试结果,好比:用例执行时间、失败用例数、失败的缘由等,这时候,就须要用到测试报告。
HTML测试报告是python语言自带的单元测试框架,其扩展的HTMLTestRunner模块可用于生成易于使用的HTML测试报告。
一、HTMLTestRunner下载
下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
下载完成后,将下载的文件保存到C盘的\Python35\Lib目录下(能够经过以下命令获取python安装目录):
①进入cmd命令行
②输入python
③输入import sys
④输入print(sys.path)
C:\Users\dell>python Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> print(sys.path) ['', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35\\python35.zip', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35\\DLLs', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35\\lib', 'C:\\Users\\dell\\AppData\\Local\\Programs\\Python\\Python35', 'C:\\Users\\dell\\ AppData\\Local\\Programs\\Python\\Python35\\lib\\site-packages']
二、修改HTMLTestRunner文件
由于HTMLTestRunner是基于python2开发的,为了使其支持python3的环境,须要对其中的部份内容进行修改,修改后的内容以下:
# HTMLTestRunner修改内容 # 第94行 import io # 第539行 self.outputBuffer = io.StringIO() # 第631行 print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)) # 第642行 if not cls in rmap: # 第766行 uo = o # 第772行 ue = e
三、python文件执行与调用
①python文件的后缀为.py
②py文件既能够用来执行,就像一小段程序,也能够用来做为模块被导入
③在python中导入模块通常用import
代码以下:
from selenium import webdriver import unittest import time class MyTest(unittest.TestCase): def setUp(self): self.driver = webdriver,Chrome("F:\安装工具\python\chromedriver.exe") self.driver.maximize_window() self.driver.implicitly.wait(10) self.base_url = "http://www.baidu.com" def test_baidu(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_key("unittest") driver.find_element_by_id("su").click() time.sleep(2) title = assertEqual(title,"unittest_百度搜索") def tearDown(self): self.driver.quit() if __name__ == "__main__": unittest.main()
四、HTMLTestRunner测试报告
以上面的test_baidu.py文件为例子,生成HTMLTestRunner测试报告,代码以下:
from selenium import webdriver import unittest from HTMLTestRunner import HTMLTestRunner class Baidu(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome("F:\安装工具\python\chromedriver.exe") self.driver.implicitly_wait(10) self.base_url = "http://www.baidu.com/" def test_baidu_search(self): driver = self.driver driver.get(self.base_url) driver.find_element_by_id("kw").send_key("HTMLTestRunner") driver.find_element_by_id("su").click() def tearDown(self): self.driver.quit() if __name__ == "__main__": baidu = Baidu("test_baidu_search") testunit = unittest.TestSuite() testunit.addTest(baidu) # 定义报告存放路径 fp = open('./result.html', 'wb') # 定义测试报告 runner = HTMLTestRunner(stream=fp, title='百度搜索测试报告', description= '用例执行状况:') runner.run(testunit) #运行测试用例 fp.close() #关闭报告文件
代码简析:
①将HTMLTestRunner模块用import导入
②经过open()方法以二进制写模式打开当前目录下的result.html,若是没有则自动建立该文件
③调用HTMLTestRunner模块下的HTMLTestRunner类,stream指定测试报告文件,title用于定义测试报告的标题,description用于定义测试报告的副标题
④经过HTMLTestRunner的run方法运行测试套件中所组装的测试用例,最后经过close()关闭测试报告文件
随着软件不断迭代功能愈来愈多,对应的测试用例也会呈指数增加。一个实现几十个功能的项目,对应的用例可能有上百个甚至更多,若是所有集成在一个文件中,那么这个文件就很臃肿且维护麻烦。
一个很好的方法就是将这些用例按照功能类型进行拆分,分散到不一样测试文件中,即一个项目,对应多个分支。
1、分拆后的实现代码
一、testbaidu.py
from selenium import webdriver import unittest import time class MyTest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome("F:\安装工具\python\chromedriver.exe") self.driver.maximize_window() self.driver.implicitly.wait(10) self.base_url = "http://www.baidu.com" def test_baidu(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("kw").clear() driver.find_element_by_id("kw").send_key("unittest") driver.find_element_by_id("su").click() time.sleep(2) title = assertEqual(title,"unittest_百度搜索") def tearDown(self): self.driver.quit()
二、testyoudao.py
from selenium import webdriver import unittest import time class Mytest(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome("F:\安装工具\python\chromedriver.exe") self.driver.maximize_window() self.driver.implicitly_wait(10) self.base_url = "http://www.youdao.com" def test_youdao(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element_by_id("query").clear() driver.find_element_by_id("query").send.keys("webdriver") driver.find_element_by_id("qb").click() time.sleep(2) title = driver.title self.assertEqual(title, "webdriver - 有道搜索") def tearDown(self): self.driver.close()
2、建立用于执行全部用例的ALL_HTMLtest.py文件
一、ALL_HTMLtest.py
# coding=utf-8 import unittest import time from HTMLTestRunner import HTMLTestRunner # 加载用例testbaidu,testyoudao import testbaidu import testyoudao # 将测试用例添加到测试集中 suite = unittest.TestSuite() suite.addTest(testbaidu.MyTest("test_baidu")) suite.addTest(testyoudao.Mytest("test_youdao")) if __name__ == '__main__': # 执行测试 runner = unittest.TextTestRunner() runner.run(suite)
拆分带来的好处显而易见,能够根据不一样功能建立不一样的测试文件,甚至不一样的目录,还能够将不一样的小功能划分为不一样的测试类,在类下编写测试用例,总体结构更加清晰。
但依然存在缺陷(当用例达到成百上千条时,在ALL_HTMLtest.py中addTest()添加测试用例就变得很麻烦)。。。
二、TestLoader类
unittest单元测试框架提供了TestLoader类,该类负责根据各类标准加载测试用例,并将它们返回给测试套件。
unittest提供了能够共享的defaultTestLoader类,可使用其子类和方法建立实例,discover()方法就是其中之一。
discover(start_dir, pattern='test*.py', top_level_dir=None)
找到指定目录下的全部测试模块,并递归查找子目录下的测试模块,只有匹配到文件名才能被加载,若是启动的不是顶层目录,则顶层目录必须单独指定。
start_dir:要测试的模块名或测试用例目录;
pattern='test*.py':表示用例文件名的匹配原则,下面的例子中匹配文件名为以“test”开头的“.py”文件,星号“*”表示任意多个字符;
top_level_dir=None:测试模块的顶层目录,若是没有顶层目录,默认为None;
# coding=utf_8 import unittest from unittest import defaultTestLoader # 定义测试用例的目录为当前目录 test_dir = './' discover = unittest.defaultTestLoader.discover(test_dir,pattern='test*.py') if __name__ == '__main__': runner = unittest.TextTestRunner() runner.run(discover)
3、集成测试报告
# coding=utf_8 import unittest import time from unittest import defaultTestLoader from HTMLTestRunner import HTMLTestRunner # 定义测试用例的目录为当前目录 test_dir = './report' discover = unittest.defaultTestLoader.discover(test_dir,pattern='test*.py') if __name__ == '__main__': now = time.strftime("%Y-%m-%d %H_%M_%S") filename = test_dir + '/' + now + 'result.html' fp = open(filename, 'wb') runner = HTMLTestRunner(stream=fp,title='集成测试报告demo',description= '用例执行状况:') runner.run(discover) fp.close()
执行后,结果以下:
转载: https://www.cnblogs.com/imyalost