赞
踩
最近这几天太肝了,兄弟们,连续写了好几天快有点顶不住了铁汁们,快点赞关注来点动力哦,嘿嘿嘿
( Python+ requests+pytest版本)
原来我们接口自动化是用 python+ request+ pytest执行
接口自动化其实主要就是接口测试的基础上填加了断言,参数化,动态关联
做接口自动化之前,我们也会划分模块,报告,公共的模块,测试数据,测试报告,主要的目的是为了方便后期的维护
测试数据,一般原来我们就是用的接口测试用例,公共的模块,主要是里面的一些公共的作,比如说用例 excel数据的读取
数据库的连接,还有我们封装的每个接口请求
断言的主要是获取访问接口的值判断,用的是 assert,参数化主要用的比较多是excel表格,就是测试用例数据
还有需要调用登录后的 cookies跟 token的时候,我们就会用到关联
比如说原来我们写的一个申请借款的接口吧
首先我们会编写测试用例,把每个用例数据保存到excel中
再建立一个申请借款的模块
这个时候我们去调用申请借款的功能模块,里面的参数我们是保存在 excel表格中
我们建立发送请求,通过参数化,去读写excel表格中的数据,获取到返回的数据,通过assert去对应返回的数据跟用例中异常的数据。
这个时候也会做数据库断言,去连接数据库去查询数据库中时候存在查询,如果是返回结果
是json数据格式,我们还会转化下格式后,再去断言
这个申请借款模块,也会用到登录的 cookie值 token,我们先建立一个登录的请求,提取
返回的 cookie值 token
excel表格多个用例,我们就用到循环去运行,读取excel中用例总的条数,去循环运行,
这里要注意的是:
就是excel表格数据时是str我们要eval转化成字典格式
把每个接口封装好以后
我们就会调用 pytest框架去运行所有test文件的测试用例
如果只是执行部分用例,也可以通过 pytest框架来指定
然后用 yagmail,在 pytest框架运行完test文件之后,发送邮件到指定邮箱。
接口自动化,我个人觉得,性价比是比较高的。
实现起来简单、维护成本低,容易提高覆盖率等特点
接口是稳定的,最多是增加一个字段或者新增接口之类的
低成本,有了相对的稳定性,不需要大量重新编写脚本,只需要基础维护包括用例的扩充就可以了
执行的快,反馈的速度快
(jmeter版本)
原来我们也做了很多接口自动化,接口自动化这块,其实原来我们也是用 jmeter请求去做的,这个时候,我们也用到一些工具,http代理,主要方便编写接口请求,通过录制就行了,我觉得接口自动化只是在接囗测试中多加了一些参数化、关联、断言参数,主要是函数参数化,自定义变量参数化,文件参数化,主要文件类型csv跟txt,不过原来csv文件用的比较多,还有一些数据库的参数化,断言,主要响应代码断言,响应文档断言。
比方说,原来我们一个登录接口主要是正常场,异常场票这块,正常场景,主要是用户跟密码正确,采用数据参数化,把用户名用随机函数进行参数化,随机长度大一些,用户名不存在的情况,原来是通过文件参数化,设置参数值,密码不正确也是通过文件参数化,接口请求中host地址,目录地址,我们都进行数据化,自定义变量去操作,结果检中,我们主要是用断言来检查,每个请求,
设置了2个断言,一个响应代码断言,一般是200,响应文本断言,登录成功,返回码为1
状态提示成功,检意是否成功,对应异常场景也是,都需要设置断言,去检查结果原来做的申请借款接口,需要登录接口http cookie,我需要建立2个接口,一个登录接口,一个申请借款接口,通过正则表达式去提取登录接口返回 cookie,在申请借款请求接口,设置http cookie时,值为登录接口返回cookie,还有也要考虑原来我们项目,还有 token值,提取登录返回 token,提取,当成申请借款的请求参数,当测试场景的脚本编写完成,执行接口测试用例,我们在察看结果树中,检直,主要是看颜色这块,红色检查哪些地方失败,绿色表示通过
编写完成后,我们会把脚本添加到 jenkins里面持续集成运行
原来我们持续集成是半个月运行一次,当然我们也可以手动构建
1,我们一般把写完的 jmeter的脚本
2,通过svn把写好的脚本检入到svn服务器
3,在 jenkins任务下,选择定时构建,或者手动构建,检查svn上传最新的脚本,去运行
一般我们项目在修改新的功能模块,上线,转测之前,都会自动去运行脚本
4,运行完成,我们再 jenkins下,查看脚本运行结果
接口自动化,我个人觉得,性价比是比较高的
实现起来简单,维护成本低,容易提高覆盖率等特点
接口是稳定的,最多是增加一个字段或者新增接口之类的
低成本,有了相对的稳定性,不需要大量重新编写脚本,只需要基础维护包括用例的扩充就
可以了执行的快,反馈的速度快
1.测试范围 2.时间进度 3.人员安排 4.框架确定
5.环境的搭建 6.准备好测试数据 数据驱动 7.工程的管理后期的维护
自动化用例,也没有具体数过,当时我负责的所有模块的接口的自动用例都是我这边独立完成的,
有模块的用例会多一点,有些会少一点,这具体看接口的参数有多少,参数多限制条件多的,
一般用例会比较多一点,我负责的模块大概有100多条用例是有的!
这个是有做过的,就拿当我们那个项目的登录接口来讲吧,那个登录的密码是需要进行加密
加密之后再进行传输。这里需要问开发要加密算法,我们会把它封装成一个函数,调用这个加密函数对密码加密,之后再进行传递。我们公司的加密算法,大部分用的都是MD5的加密算法(base64)
这里首先要搞清楚用的是什么加密算法,问开发要解密算法,对返回的数据进行解密
解密完成之后在与预期结果对比,去进行断言
Web端
1,浏览器设置代理就可以录制,默认ip为 localhost,端口8888
手机端
1,手机设置代理就可以录制
默认ip为pc机器的ip地址,端口8888
用户参数自定义变量文件参数化,csv文件或者txt文件
函数助手随机函数,csvread函数数据库参数化
正则表达式提取或者 JSON Extractor提取
正则表达式或者边界值提取器或者JSON Extractor提取的值
后置处理器- beanshell处理器
定义成全局变量
${_setProperty(newtoken,${access_token},)}
其他线程组,引入变量值
${_P(newtoken,)}或者${_property(newtoken,)}
1,响应断言
添加响应断言:添加-》断言-》响应断言
apply to:是应用范围,设定匹配的范围
Main sample and sub-samples:匹配范围为当前父取样器,及子取样器
Main sample only:仅当前父取样器
Sub samples only:仅子取样器
Meter Variable:变量值进行匹配
要测试的响应文字:针对响应数据不同部分进行匹配
(1)响应文本:响应服务器返回的文本内容,http协议排除 header部分
(2)响应代码:匹配响应代码,比如http请求中200代表成功
(3)响应信息:匹配响应信息,处理成功返回成功”或者“ok”字样
(4) Response Header匹配响应头中的信息
匹配规则:
包括:响应内容包括需要匹配的内容就算成功
匹配:响应内容要完全匹配内容,不区分大小写
equals:完全相等,区分大小写
substring:响应内容包括匹配内容即为成功
可以通过添加断言结果来查看断言的执行情况
执行结果:
如果接口响应数据可以与断言匹配上,则测试用例通过,否则不通过
可以通过断言结果,查看断言执行情况。
2,大小断言
3,持续时间断言
Jmeter -n -t文件路径\fw-zhuce.jmx -l result.jtl -e -o E:\resultreport
讲解:非GUI界面,压测参数讲解
-h帮助
-n非GUl模式
-t指定要运行的 JMeter测试脚本文件
-l记录结果的文件每次运行之前,(要确保之前没有运行过即xxx.jtl不存在,不然报错)
-r Jmter.properties文件中指定的所有远程服务器
-e脚本运行结束后生成html报告
-o用于存放html报告的目录(目录要为空,不然报错)
-R表示选择执行=远程启动
XXX.XXX. XXX. XXX:5174 ,XXX. XXX. XXX. XXX:5172
官方配置文件地址http://jmeter.apache.org/usermanual/get-started.html
(1)监听器中添加-邮件观察仪
文件名-运行完成,保存运行结果的位置
from邮件的发送人
isz181xiongmao@126.com
addressee邮件的接收人(多个人用逗号隔开)
success subject运行成功,发送邮件标题 success limit大于运行请求成功的次数
failure subject运行失败,发送邮件标题 failure limit大于运行请求失败的次数
host邮件服务器地址smtp.126cm
login邮件服务器登录用户名密码(授权码)
1、文件名:只需要给出路径和保存的文件名称即可,给定之后将会把测试结果的数据写入到文件中
注:它不会将此文件已附件的形式在邮件中,只是将测试结果写入到了定的此目录文件中,
如果你运行完脚本,直接在此路径下打开此文件就可以看到运行结果
2、 Success Limit与 Failure Limit:当成功数与失败数为几时进行邮件的发送(注意:此处是大于给定的数值,不是等于),我写的1,则失败2次后将发送邮件通知我,
3、当测试结果100%成功时则不会发送邮件
4、写代码java编写 beanshell后置处理器
用 assert断言
1,断言返回的结果
2,进行逻辑检查,检查数据库产生的数据
把返回的值定义成全局变量
global a_id #定义成一个全局变量
a_id = incharge_id
用例数据这块,当时公司要求使用 excel表格来进行管理,其实这里主要也是为了实现数据与脚本的分离,提高整个工程后期的维护与优化,这里把数据封装到excel表格之后。
我们在脚本中通过调用封装好的读取 excel表格的数据函数,对excel表格中的用例数据,
我们是这么组织的,会有以下几个字段像用例标题,请求地址,请求方式,请求头,请求参数,响应结果,这个几个部分,对于请求头跟请求参数,因为脚本中发请求都是通过组装成字典的形式来发送的所以这里我们也是通过类似于字典的形式文本格式来进行组织,主要就是方便后期脚本的提取与引用其实我觉得,这样去处理的好处就是,后期如果用例数据有变动,或者需要增加或删除部分
用例直接针对 excel表格数据进行操作就可以了,不需要改动脚本这也就方便整个项目工程的管理与维护了。
1,如果返回的是 cookies值,可以直接返回接口的 r.cookies
2,返回的是str类型数据,可以导入re模块进行正则表达式提取返回数据格式是json格式,
导入json,把json数据格式转化 python对象
json.dumps | 将 Python对象编码成JSON字符串 |
json.loads | 将已编码的JSON字符串解码为 Python对象 |
对于 cookie,session的处理一般有三种方式:
第一种就是先获取登录请求的 cookie值,然后发送其他请求的时候,在 requests提供的
两个方法get或post方法中有一个 cookies参数,我们可以通过这个参数来传递 cookies值
第二种就是通过订制请求头,然后把获取到的coookies放在请求头中,通过请求头来进行传递
第三种就是通过创建一个 session会话对象,后期所有的请求发送都通过调用这个 session会话对象来进行发请求,如果是登录请求,它会自动保存 cookies值,然后其他需要用到cookies值的请求,也通过 session对象来发送,它会自动把 cookies发送出去,对于 cookies, session的处理,我们差不多都是通过以上三种方式来实现的
(1)我们做U自动化测试使用 Python+ seleniun+ unittest工具
主要对自动化进行规划,把数据、代码、资源、公共方法进行分离,方便后续维护;
具体是通过元素定位、断言、参数化和封装来实现;
其中元素定位的方法,主要是css定位,也会用一些 xpath定位,还有id、name、 class等
断言,主要是用 Assert来判断实际结果是否与预期结果相符;
参数化,可以用列表、字典、导入excel表格库(xlrd)对数据进行参数化;
对于封装,一般我会对元素还有公共的模块进行封装。
比方说:原来我们有一个申请借款的功能模块
首先我们先进行自动化框架分类,分成测试数据、需要定位的元素、公共方法(比如说,一些数据的操作、excel操作,我们会封装成一个公共方法)。先采用css定位,把申请借款所对应的元素定位出来,里面有很多内嵌页面,还有下拉框元素的定位操作,对应申请借款的数据,我们都会保存在excel表中,从excel表格中去获取数据。申请完成以后,我们会设置一个断言,还有进行数据库的检查。我们会把元素封装到资源库,还有就是模块的封装,申请借款会用到登录模块,我们首先会封装好登录功能。借款申请完成后,会从数据库中删除相关的数据实现数据闭环,再关闭界面。
运行自动化脚本,我们是用 unittest 框架去运行,编写测试集,一般我们是编写 unittest脚本,
去执行所有测试用例。
我觉得自动化中最难的在于元素的定位、内嵌界面、时间控件,这些需要一些js操作去除元素属性,进行操作。
自动化中发现的问题:
在申请借款中,开发人员写了调试代码的弹出框,没有删除,导致我们自动化脚本跑不通
充值过程中,
添加新的支付方式,开发修改了代码,导致原有充值失败,这些都是我们原来自动化发现的问题。原来也用了一些 Robotframework的自动化测试框架,这个比较简单一些,因为部分关键字、框架已经封装好了,只需要调用就行,但是不好的地方,就是扩展性会差一些。
编写完成以后,可以用 Jenkins持续集成去定时跑自动化测试用例,再去查看运行日志。
总的来说RF( Robot Framework)比较简单方便上手比较快,如果公司对自动化要求不高的话可以选择RF框架来做,如果比较高的话就选用 unittest框架来做。
(2)原来我们自动化测试主要是用的 python+ selenium+ pytest框架做的
主要对自动化进行规划,把数据、代码、资源、公共方法进行分离,方便后续维护;
自动化测试其实主要通过几个方面元素定位,参数化,断言,模块的封装,数据闭环等来实现的
其中元素定位主要是cs定位也会用一些 xpath,id,name,classname,ink等等定位,还有js定位和 jQuery定位都会用到;
参数化主要是用列表、字典、以及导入excel表格库(xlrd)对数据进行参数化;
断言:主要是用 assert断言来判断实际结果是否与预期结果相符;
对于封装,我主要会对界面上的元素,一些公共方法(数据库操作,读取excel数据公共方法等),还有测试数据(变量,字典,列表exce表等)和一些元素操作,测试用例等等进行封装;
最后闭环的话,就是都要把新增的数据删除,打开的界面都要关闭,就比如原来我们做的自动化测试,有一个申请借款的功能模块,
首先,我们先进行自动化框架模块的分类划分,分成需要定位的元素 page_element,公共模块 common(比如说数据库操作,读取excel数据的操作,都会封装成一个公共模块的)、测试数据data、测试用例、元素操作 element_action、执行用例以及报告文件等等这些模块。
先导入 selenium包,采用css定位,把申请借款所对应的元素定位出来,里面有一些内嵌界面,需要先进入内嵌界面 --driver.switch_to.frame(),还有下拉框元素的定位操作(定位下拉框的话首先要导入select包,通过 index,value,visible_text进行
选取值: Select(变量). Select_by_value(‘’)把定位到的所有界面元素封装到 page_element模块里面,方便后期维护。
对于申请借款的数据,申请借款的一些标题,利率等等,我们都会保存在excel表中,对于excel表格操作,导入xlrd包把读取数据公共方法,保存到公共模块 common中,方便以后从exell表中获取数据,申请借款成功以后,我们会添加一个断言,获取界面title值,去判断界面的提示,当然也可以获取提示申请成功text内容去判断,也会做数据库断言,检查数据库数据,导入数据库操作包 pymysql,把数据操作,封装到公共方法,
去调用(数据库操作步骤:1打开数据库连接,2建立游标,3执行游标(sql),4返回获取的数据)
申请借款模块需要调用到登录模块,我们先把登录模块封装好,放到元素操作element_action模块中,方便维护,借款申请完成后,我们会从数据库中删除相关数据实现闭环,减低后续维护,再关闭所有打开的界面。
我们运行自动化脚本的时候是用的 pytest框架进行
导入 patent,导入 yamail包
定义一个主函数if _name_="_main_",pytest.main()所有的用例脚本,定义生成对应的HTML报告到 report目录下,最后通过 yagma定义发送邮件
定义发送邮箱的登录信息-定义邮件主题,内容,附件位置--发送邮件到测试人员邮箱中
当后续出现错误用例,也会调用 pytest--if来运行失败的测试用例
我觉得自动化中最难的在于
元素的定位、内嵌界面、时间插件,这些需要一些js操作,去除元素属性,进行操作
自动化中发现的问题:
在申请借款中,开发人员写了调试代码的弹出框,没有删除,导致我们自动化脚本跑不通;
充值过程中,添加新的支付方式,开发修改了代码,导致原有充值失败
把一些简单,重复的工作,用自动化去实现,减少成本原来手工完成事情,通过自动化脚本去替代
功能需求,需求稳定,界面稳定,不会频繁变动,才可以做
版本迭代次数比较多,做出来才有意义
项目周期比较长(大项目)意义
1、前期项目组会评估项目是否合适做自动化测试,例外就是看下哪些模块需要做自动化,适合做
2、人员安排,分工
3、确定测试框架
4、各自领取自己负责模块(根据功能来进行划分,功能测试的模块)
整理功能模块的用例,把能做自动化的用例提炼出,规整成自动化用例文档,
准备数据,整理数据,管理
资源,环境的准备
5、搭建测试环境
6、脚本开发
2年以内,把原来手工做的事情15-30%用自动化脚本去替代
2年以上,实现40-70%
手工编写测试用例
把原来手工的测试用例,当成自动化测试用例
优点:
1、对程序的回归测试更方便
2、可以运行更多更繁琐的测试
3、提高测试效率和准确性,节约时间成本
4、可以执行一些手工测试困难或不可能进行的测试(例如,对于大量用户的测试,可以通过自动化测试模拟同时有许多用户,从而达到测试的目的)
5、自动化测试不存在执行过程中的疏忽和错误,从而增加软件信任度
缺点:
1、不能取代手工测试
2、手工测试比自动测试发现的缺陷更多
3、对测试质量的依赖性极大
4、由于自动测试比手动测试更胞弱,所以维护会受到制,从而会制约软件的开发
5、工具本身无想像力
2年以内,把原来手工做的事情30%用自动化脚本去替代
2年以上,实现40-70%
当时覆盖的确实也不是很多,差不多30-40%的样式吧
1、首先要安装 Python
2、然后安装编写代码工具 pycharm
3、导入 selenium库(pip install seleniun在 pycharm安装 selenium3下载源码包
4、下载浏览器驱动(谷歌.火狐等),把驱动程序发到 Python根目录下
我们用的 selenium3x以上的版本,对于 selenium2x以上的版本原理是这样的:
Selenium2.0则是把 selenium1.0中 selenium RC替换为了 WebDriver
WebDriver利用浏览器原生的API,封装成一套更加面向对象的 SeleniumWeb Driver API
直接操作浏览器页面里的元素,甚至操作浏器本身(截屏,回口大小,启动,关闭,安装插件,配置证书之类的),由于使用的是浏览器原生的API速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学,然而带来的一些副作用就是,不同的浏器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了 SeleniumWebDriver要分浏览器厂商不同,而提供不同的实现,例如 Firefox就有专门的 FirefoxDriver,
Chrome就有专门的 ChromeDriver等等
Selenium1.0使用的是 Javascript注入技术与浏览器打交道,需要 Selenium启动一个 Server,将操作Web元素的AP调用转化为一段段 Javascript,在 Selenium内核启动浏览器之后注入这段 Javascript,开发过Web应用的人都知道, Javascript可以获取并调用页面的任何元素,自如的进行操作,由此才实现了 Selenium的目的:自动化Web操作,这种 Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于 Selenium内核,对API翻译成的 Javascript 质量高低
Selenium2.0则是把 selenium1.0中 selenium RC替换为了 Web Driver
WebDriver利用浏览器原生的API,封装成一套更加面向对象的 SeleniumWebDriverAPI
直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装播件,配置证书之类的),由于使用的是浏览器原生的AP,速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学,然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了 SeleniumWebDriver要分浏览器厂商不同,而提供不同的实现例 Firefox就有专门的 Firefox Driver,
Chrome就有专门的 ChromeDriver等等
driver = Web Driver ChromeO
driver.quit() #退出浏览器
driver.closed() #关闭窗口
driver.implicitly_wait() #设置隐性等待延迟
driver.current_url #获取当前的URL
driver.page_source #获取当前页面的源代码
driver.title #获取当前页面的标题
driver.maximize_window() #窗口最大化
driver.get() #加载一个网页
元素定位的:
driver.find_element_by_id()
driver.find_element(By.xxx,’’)
frame跳转的:
driver.switch_to.frame()
driver.switch_to.parents_frame()
driver.switch_to.default_content()
窗口跳转:
driver.switch_to.window()
对话框的处理:
Driver_switch_to.alert
.accepto
.dismiss
.text
.send_keys()
执行js脚本的:
driver.execute_script(js)
Element类:
element.click()
element.submit()
element.send_keys()
element.clear()
element.text
element.get_attribute()
element.is_displayed()
element.find_element_by_xpath()
1、通过id定位
find_element_by_id()
2、通过name定位
find_element_by_name()
3、通过 class name定位
find_element_by_class_name()
4、通过css定位
find_element_by_css_selector()
5、通过link定位
find_element_by_link_text(‘文本’)没有空格一般a链接
6、通过 partial_link定位
find_element_by_partial_link_text(部分文本)--般有空格a链接
7、通过 xpath定位
find_element_by_xpath()
8、通过 tag_name定位
find_element_by_tag_name()
js用到css定位
1. driver.execute_script("document.getElenmentByld().value='';")
2. driver.execute_script("document.getElenmentByName().value='';")
3. driver.execute_script("document.getElenmentsByClassName()[0].value='';")
4. driver.execute_script("document.getElenmentsByTagName()[0].value='';")
1. driver.execute_script("$(#id定位值)vaC")")-输入值a()处也可以用cick()表示点击
2. driver.execute_script("$(name=name定位值va(")输入值
3. driver.execute_script("$(cas定位值)va()")输入值
4. driver.execute_script("$((class=]").val().)
5. driver. execute script ("SCIvalue= ]").val()")
#通过样式 #id样式, .cass样式为多
1. find_element_by_css_selector("#id")
2. find_element_by_css_selector(".classname定位值")
#通过元素属性
3. find_element_by_css_selector("[name=name定位值]")
Find_element_by_css_selector("[class=定位值]")
#样式,属性结合
find _element_by_css_selector(div#fanwe_msg_box>table>tbody>tr>td:nth-child(2)>div(@class='dialog-content'))
5.父子元素定位
Find_element_by_css_selector(div#fanwe msg box> table>tbody>tr> td:nth-child(2)
>div:nth-child(2))
Xpath写法://*div[@id=’u1’]/a[7] #相对路径
Xpath写法:/html/boy/div[1l/div/div/divl3/a[7 #绝对路径
#先找父元素,结合属性
Find_element_by_xpath(//div(@id=u1"/a[@name=tj_login])
1、首先要导入一个包: from selenium.webdriver.support.select import Select
2、先给下拉框元素定位定义一个变量:a= diver.find_element_by_css_selector()
3、再通过根据下拉框的 value\visible_text\index去选择值
Select(a).select_by_value('')--根据下拉框的vaue值去选取值
Select(a).select_by_visible_text('')--根据下拉框的内容去选值
Select(a).select_by_index('')--根据下拉框的下标去选。从0开始
1、定位元素的时候看到fame的需要进入内嵌
2、如果有内嵌有id或name值时直接进入内嵌 driver.switch_to.frame(id值或name值)
3、如果内嵌没有id或name值,先定义一个内嵌再进入:
a=driver.find_element_by_class_name(‘’)
driver.switch_to.frame(a)
4、如果有多层内嵌,要一层一层进入
5、记得退出内嵌: driver.switch_to_default_content()
6、driver.switch_to.parent_frame()---进入父级内嵌,调至上一级内嵌
1.首先要获取多个界面的句柄
先通过定位元素几个界面: driver.find_element_by_id().click或者其他,获取一个界面打印一个:print (diver.window_handles)
然后获取几个界面的句柄,定义成一个变量:window_list= diver.window_handles()---以列表形式存在
2.通过界面句柄的下标进入不同的界面: driver.switch_to_window(window_list[O])
通过界面句柄的下标进入不同的界面,0表示第一个,下标-1代表最新的界面
注意:如果进入一个界面里面是内嵌,记得退出内嵌再进入另一个界面
一般当我们西面上的元素超过一屏后,想操作屏幕下方的元素,是不能直接操作的,会报元素不可见异常的。这时候需要借助滚动条来拖动屏幕,使被操作的元素显示在当前的屏幕上,selenium提供了一个操作js的方法: execute.script(),可以直接执行js的脚本,
滚动到底部:
Js='var q=document.getElementByld('id')scrollTop=10000'
Driver.execute_script(js)
滚动到顶部:
js='var q=document.documentElementscrollTop=0'
driver.execute_script(js)
#把滚动条拉到指定位置
虽然用上面的方法可以解决拖动滚动条的位置问题,但是有时候无法确定我需要操作的元素在什么位置,有可能每次打开的页面不一样,元素所在的位置也不一样,这个时候我们可以先让页面直接跳到元素出现的位置,然后就可以操作了。
Target_element = driver.find_element_by_xpath(‘//*[@id="4"]/h3/a’)
Driver.execute_script("arguments[O].scrollIntoView();",target_element)
模拟键盘:
1、要导入一个包 rom selenium. wedriver common keys import Keys
2、快捷键输入,通过 send_keys()方法可以来模拟键盘输入操作。
Send_keys(Keys.CONTROL,'a’) 全选(Ctrl+A)
Send_keys(Keys.CONTROL,'C') 复制(Ctrl+C)
Send_keys(Keys.CONTROL,’X’) 剪切(Ct+X)
Sen_ keys(Keys.CONTROL,’V’) 粘贴(Ctr+V)
Send_keys(Keys.ENTER) 回车键
Send_keys(Keys.BACK_SPACE) 删除键
Send_keys(Keys.SPACE) 空格键
Send_keys(Keys.TAB) 制表键
Send_keys(Keys.ESCAPE) 回退键
模拟鼠标:
语法: ActionChains(diver).鼠标操作动作操作的元素. Perform()
鼠标操作动作有:click()单击、 context_click()右击、 double_click()双击、
Move_to_element()鼠标悬停
1.先导入一个鼠标的包:from selenium.webdriver.common.action_chains import Action Chains
2.然后定位元素: driver.find_element_by_xpath()可以定义为一个变量aa
3.然后通过语法执行:Action Chains(driver).move_to_element(aa).perform()
1.可直接赋值 send_keys输入图片的地址
其实上传文件的按钮就是一个 input元素,只是它的type类型是file类型,
我们在处理这种上传文件的按钮的时候,可以直接通过普通定位方式去定位它,
再利用 send_keys方法去输入图片的地址就可以了。
Load_file_element=driver.find_element_by_xpath(‘/html/body/div(8l/div(1)/div(2/div/div[3]/form/div/div/div/inpu’)
2.需要用到一个工具,Autolt工具
帮助我们识 Windows控件信息利用Autolt生成一个操作 Windows对话框的exe执行文件
然后在 python代码中去调用这个可执行文件
这里需要用到os模块,利用 os.system去执行 windows的exe文件,
把exe文件的路径传入,并传入需要上传的图片的路径即可
Drver.fnd_ement_by_xpath(‘html/body/divoiv1/dw2]/div/div3form/dvd/di)cick()#点击浏览
time.sleep(1)
ossystem(C:\Users\\Administrator\\ Desktop\\AA.exe D:\\QQ.png)
1、首先js去定位元素,去除元素中的属性:js="$(‘’).removeAttr(要删除的属性)
2、然后执行js脚本: driver.execute.script(js)
3、然后输入时间日期
driver.find_element_by_xpath(//[@id=start time]").send keys("2018-12-29 10:55:55)#输入日期
弹出框一般有三种:警告消息框,确认对话框,提示消息框
在 selenium中提供了一个方法 switch_to.alert,跳转到对话框上面去对alert对话框进行操作的函数/法
Accept() #点击确定按钮
Dismiss() #点击取消按钮
Text #获取对话框上的文本信息
Send_keys() #输入内容
1、sleep强制等待,要导入from time import sleep,必须等待那么多秒定位才执行
2、driver.implicitly_wait隐式等待多秒内只要找到元素就开始执行,超多设定时间就超时
3、Web DriverWaite(driver,20.1).until(lambdax.x.find_element_by_name()).send_keys()-首先需要导入一个包:fom selenium.webdriver.support.wait import WebDriverWait, driver 1s钟找一次元素,最多找20秒,一直发送请求,直到找到元素位置以后,进行下一步操作。
有的,有时候我们会碰到一些元素不可见,这个时候 selenium就无法对这些元素进行操作了。例如,下面的情况:页面主要通过“display.none”来控制整个下拉框不可见。这个时候如果直接操作这个下拉框,就会提示:我们需要通过 javaScript修改 display的值
具体修改方式如下:
js='document.queryselectorAll(‘select’)[1].style.display="block";’
driver.execute_script(js)
1、像页面加载延迟的问题,这个需要通过等待延迟的方式来处理。
2、不过有时候,页面加载完成,但是元素暂时还不可见,导致定位不成功
这个可以选择使用显示等待来处理,这里需要用到 WebDriverWait类来实现
3、还有就是像内嵌网页的问题,需要使用 driver.switch_to.frame(name/index)这个函数来跳转到处理。
4、还有要注意多窗口问题,动态id问题等的问题,对于多窗口处理,可以使用
driver.switch_to.window()的方式来进行处理,而对于动态id的问题,需要注意的是有些id跟数字有关,可能会动态变化,可以使用xpath也可以使用 css_select属性定位或者样
式定位,或者可以通过父元素来找元素,或者通过兄弟节点来找对应的元素。等等
5、还有要特别注意滚动条的问题,这里通过调用js代码来实现的,driver.execute_script(js)
6、再这就是有时候会碰到某些元素的是不可见的,比如 display属性为none这就需要通过 java Script修改 display的值。
js ='document. querySelectorAll("select")[1]. style. display="block";
driver.execute_script(js)
1、可能是网络问题,导致页面加载延迟,这个可以做延迟等待,一般选择隐式等待,在脚本前面加上 driver.implicitly_wait(20)。
2、也有可能是页面结构发生变化导致的,这个时候最好选择通过 xpath或css结合属性进行或者样式定位可能会好点,或者采用 JQuery定位的方式来进行定位元素
我们可以通过 javaScript 修改 display的值,来实现
#修改元素的属性
#我们需要通过 javaScript修改 display的值。
js='document.querySelectorAll('select')[1].style.display="block";’
driver.execute_script(js)
1,少用绝对路径,多用css或者 jQuery定位
2,单个元素属性进行封装
1,开发去掉验证码
2,开发设定一个万能验证码
3,python导入 pillow和OCR模块 pytesseract
1、其实就是把数据与脚本分离,好处就是方便维护管理,后期数据有变动,只要改 excel
表的数据就可以,脚本不用动
2、封装一个读取 excel表格的函数方法,调用这个函数来读取数据。
3、然后利用ddt模型,使用dt内部装饰器来实现数据引用
我们当时就是这么做的。
把测试数据,通过变量或者文件进行保存,通过修改文件或者变量,达到数据参数化目的
测试过程,减低数据维护成本
1、像测试用例数据这块,我们都是放在 excel表格中的
2、常用的变化比较小的配置数据,比如数据库连接的配置,报告的路径,用例的路径等等
这些放在config配置文件中,利用全局变量来管理的。对于全局变量的数据,直接导入config某块,调用就可以。目的是以便于测试数据改变时,直接修改变量就行了
1.首先都要 import random
随机整数: random randint(10002000),有时需要转化成字符串类型:
str(random randint(1000, 2000))
随机字符串:"join( random.sample(‘abcdefghijk’6)),有时前面固定字母了:
'ldh'+".join(random sample(‘abcdefghijk’,6))
需要用到xlrd库,调用这个库中的API函数来实现的。
1.第一步:导包 import xlrd
2.第二步:book= xrd.open_workbook(文件路径)
3.第三步:table= book.sheet_by_name表名)
4.第四步:读某行数据一般都技行来读取
Table.row_values(x)
如果要读全部的数据,多行数据,利用循环读取就可以
List=[]
for i in range(1,table.nrows):
List.append(table.row_values(i))
return list
1、读取一行数据:YS.row_values(0)0表示第一行
2、读取一列数据:YS.col_values(0)0表示第一行
读取具体某个数据:YS.row_values(O)[0]--表示获取第一行第一列
获取总列数: YS.ncols
获取总行数: YS.nrows
需要自己封装一个函数
1、安装 pymysql: pip install pymysql或者在 pycharm里面安装 pymysql
2、导入 mysql: import pymysql
3、连接数据库: db_connect= pymysql.connect(host='ip地址',
user=’root’,password=’’,database=’’,port=’’,charset='utf8')
4、建立游标: cursor= db_connect.cursor()
5、执行游标: cursor.execute(sql)
6、获取数据
获取游标中所有数据:all= cursor.fetchall()
获取游标中多条数据:many= cursor.Fetchmany()
获取游标中第一条所有数据:one= cursor.fenchone()
7、关闭游标: cursor.close()
8、关闭数据库连接 db_connect.close()
获取游标中多条数据:many= cursor.fetchmany(5)
获取游标中第一条所有数据:one= cursor.fenchone()
首先已经建立好了数据库连接的函数,并且 return了
二维元组的格式
如果要获取具体某个值要用:cursor.fetchall[0][0]---这个表示提取游标中所有值里面的第一个元祖里面的第一个值
断言主要检查几个点:
1.页面跳转是否正确(title,url)
2.页面数据是否正确(核心数据,页面上的关键信息,或者页面上的某个元素是否出现)
3.如果要检查数据库,需要连接数据库,查询数据,与预期结果进行对比
基本都调用 unittest框架中提供的断言函数来实现的,用得比较多的就是
AssertEqual
Assertln
#扩展
1.提取元素text断言
User_text= driver.find_element_by_css_selector("# j_account>a").text#获取实际的值(展示账户名内容)
assert' admin' in user_text #断言 admin在实际值里
2.提取元素属性去断言:
login_button_value=driver.find_element_by_id("lajax-login-submit").get_attribute("vaue") #获取登录按钮的属性vaue值是登录
assert'登录'== login_button_value #断言登录是这个按钮的属性
3.提取界面title值去断言
assert"p2p信贷一最大、最安全的网络借贷平台"in driver.title,"失败"或者in改为 not in
4.提取元素是否可用来进行断言
Assert driver.find_element_by_css_selector("div.user_money > a:nth-child(1)").is enabled0==True,"元素不存在。不可用"
5.数据库断言,去数据库查询结果,是否跟预期一致
selenium提供了三种模式的断言: assert、verify、 waitfor
Assert失败时,该测试将终止。
Verify失败时,该测试将继续执行,并将错误记入日显示屏。也就是说允许此单个验证通过。确保应用程序在正确的页面上。
Waitfor用于等待某些条件变为真。可用于AJAX应用程序的测试
常见的 assert断言:
assertTitle(检查当前页面的title是否正确)
assertText(检查指定元素的文本)
assert Attribute(检查当前指定元素的属性的值)
如果该条件为真,他们将立即成功执行。如果该条件不为真,则将失败并暂停测试。直到超过当前所设定的超过时间。一般跟 setTimeout时间一起使用
1、提取元素text断言:
User_text=driver.find_element_by_css_selector(("#j_account>a").text #获取实际的值
(展示账户名内容)
assert'admin'in user_text #断言 admin在实际值里
2、提取元素属性去断言:
Login_button_value=driver.find_element_by_id("lajax-login-submit").get_attribute(value)#获取登录按钮的属性vaue值是登录
assert'登录'== login_button_value #断言‘登录’是这个按钮的属性
3、提取界面title值去断言:
assert"p2p信贷最大、最安全的网络借贷平台"in driver.title,"失败"或者in改为 not in
4、提取元素是否可用来进行断言
assert driver.find_element_by_css_selector("div.user_money > a:nth-child(1)").is en
abled==True,"元素不存在。不可用"
5、数据库断言,去数据库查询结果,是否跟预期一致
可以判断实际结果是否为预期结果,如果断言失败的话,会终止执行下面的程序,不用再用肉眼去看去判断了是否有没有bug了
模块封装:封裝界面上的所有元素,一些公共模块(数据库操作,读取exell数据公共方法等),
测试数据(返回一些变量,字典列表exell表等),一些元素操作,测试用例等等.
封装的目的:为了后期维护和管理更加方便,如果修改数据时直接在模块中修改就行
def get_data(filename,tablname):
# 1.打开 excel文件
Book = xrd.open_workbook(filename)
# 2.打开一个表
Sheet = book.sheet_by_name(tablname)
Print(sheet.nrows)
#3.对表操作列,行,单元格
list = []
for i in range(1,sheet.nrows):
List.append(sheet.row_values(i))
return list
1、通过调用数据库操作把数据删除
2、打开的所有界面都需要关闭--可以在测试用例处设置装饰器,每个函数调用装饰器就可以每次关闭了才会打开另一个界面
1、将界面元素封装到一个模块 page_element,封装成—个py文件:page_element.py
2、将元素的操作封装到一个模块 element_action,封装成一个py文件:element_action.py
3、将测试数据封装到一个模块data,封装成一个py文件 data_base.py
4、将一些公共的方法例如数据库操作,获取exell表数据的操作方法封装到一个模块common,封装成一个py文件:common_action.py
5、将测试用例(test开头的函数用例)封装到一个模块 test_case,封装成一个py文件test_case.py
6、将运行用例的框架( pytest框架)封装到一个模块 run_case,封装成一个py文件:run_case.py(这里还可以发送邮件)
7、还建一个存放测试报告文件的模块 report,到时生成的报告存放在这个位置中
8、建立一个持续集成需要扩展的模块ci_cd
1、方便维护与管理
2、模块化,比较方便清楚各个模块的东西,提高测试效率和准确性
注意:没有统一的标准
1、包含发件者邮箱地址,授权码
2、接收者邮箱地址,邮件主题,邮件正文内容,附件地址
(对于自动化工程的维护是你做的吗? 你们的工程具体怎么维护的? 如何实现数据与脚本的分离?
具体怎么做的? 优点在哪里? )
工程维护这块,最主要分为几大块模块,主要就是工程管理思想,我们当时采用的POM模型来实现工程的模块化,把数据,配置文件,报告,测试用例,页面操作,公共业务方法等都进行独立起来,
封装到不通过的模块中,
例外就是实现数据驱动,参数化,
还有就是实现一些函数的封装,方便调用,
还有一个重点就是用例的管理,统一加载执行,如何实现全量跑用例,出报告等等
这块我做得不是特别多,大部分都是我们老大维护的,我们主要是协助为主。
1、主看总共执行了多少用例,通过了多少,失败了多少,错误了多少。
2、对于错误的用例,基本都脚本问题,查看报告中的日志详细信息,看具体哪个位置出错了.针对性去进行调试,修改。
3、对于失败的用例,也是首先看报告中的日志,看具体哪个位置出错了,一般首先怀疑自己的脚本,先确定脚本是否有问题,如果脚本没有问题,那可以确定就是Bug了,提Bug即可
#其他问题
文章到这里就结束了,各位铁汁如果有什么觉得不对的可以发在评论区咱们来讨论哈,
听说关注我并三连的铁汁都已经升职加薪暴富了哦!!!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。