web自动化
2020-04-02 14:00:42 0 举报
AI智能生成
web自动化
作者其他创作
大纲/内容
代码
创建、关闭浏览器驱动
鼠标操作封装
日志初始化函数
PO代码
grid
开启主节点
切换到jar包目录,打开dos
java -jar selenium-server-standalone-3.141.59.jar -role hub -maxSession 10 -port 4444
需要比对自己安装的selenium版本
pip list
开启子节点
切换到jar包目录,另外打开一个新的dos
java -jar selenium-server-standalone-3.141.59.jar -role node -port 5555 -hub http://192.168.254.1:4444/grid/register/ -maxSession 5 -browser browserName=chrome,seleniumProtocol=WebDriver,maxInstances=5,platform=WINDOWS,version=80.0.3987.87
域名是主节点显示的
端口号
版本和当前使用版本要一致
不同数据格式的读写
Json数据
依赖环境:json模块
装饰器:@parameterized.expand()
数据类型:[ () ]
读取/序列化:json.load()
写入/反序列化:json.dump()
Excel文件数据
依赖环境:读-xlrd,写-xlwt模块
装饰器:@parameterized.expand()
数据类型:[ () ]
读取:按提供的函数读取具体数据
写入:按提供的函数写入具体数据
yaml数据:app数据驱动时常使用
依赖环境:yaml模块
@pytest.parametrize()
数据类型:[ {} ]
读取/序列化:yaml.load()
写入/反序列化:yaml.dump()
理论基础
自动化
自动化能解决什么问题
回归测试
压力测试
兼容性测试
提高工作效率,保证产品质量
自动化测试的优点
自动化测试可以客服手工局限性,比如:绕开页面进行测试
自动化测试可以在更短的时间内运行更多的测试用例
自动化的用例可以重复执行
自动化可以避免人为失误
自动化测试的误区
自动化测试可以发现更多的bug
自动化测试是主要是用来提高效率,本意不是为了发现bug
自动化测试可以完全代替手工测试
自动化测试比手工测试更厉害
自动化测试适用于所有模块
自动化测试的分类
web自动化
接口自动化
app自动化
单元测试
桌面自动化测试
安全自动化测试
web自动化
什么样的项目适合做web自动化
需求变更不频繁
需要回归
项目周期长
什么时候开始做web自动化
手工测试之后
因为自动化的预期结果需要从手工测试中得到
环境搭建
python
python解释器
安装
安装地址:https://www.python.org/downloads/release/python-372/
安装
默认安装,一直next
要记得勾选添加环境变量:add path
python代码编写运行ide:pycharm
selenium
版本
selenium1.0
selenium IDE
基于FireFox的一款插件,录制脚本
selenium RC
selenium GRID
selenium2.0
selenium 1.0
废弃了selenium1.0中的RC
webdriver
selenium3.0
彻底删除RC
拥抱Java8
支持更多浏览器
安装与卸载
安装:pip install selenium
卸载:pip uninstall selenium
查看:pip show selenium
浏览器
这里使用谷歌79
webdriver
下载与浏览器匹配的webdriver
selenium
原理
webdriver是按照server–client的经典设计模式设计的
server端就是remote server,可以是任意的浏览器
client就是我们的脚本,client端发出请求
启动浏览器后,selenium-webdriver会将目标浏览器绑定到特定的端口,启动后的浏览器则作为webdriver的remote server。
客户端(也就是测试脚本),发送HTTP请求给sever端,来告诉Selenium我们希望浏览器接下来做什么事情。
客户端(也就是测试脚本),发送HTTP请求给sever端,来告诉Selenium我们希望浏览器接下来做什么事情。
常用API
常用浏览器操作方法
最大化浏览器:driver.maximize_window()
设置浏览器大小:driver.set_window_size(width,height)
设置浏览器位置:driver.set_window_position(x,y)
回退:driver.back()
如果没有回退的空间那么无法执行这个操作
前进:driver.forward()
刷新:driver.refresh()
关闭当前窗口:driver.close()
关闭浏览器驱动对象:driver.quit()
获取页面title:driver.title
获取当前页面的URL:driver.current_url
元素定位
元素定位方式
name:元素name属性值
driver.find_element_by_name("name属性值")
id:元素id属性值
driver.find_element_by_id("id属性值")
class_name:元素class属性值
driver.find_element_by_class_name("class属性值")
class属性值有多个时,只要其中的一个
tag_name:元素标签名
driver.find_element_by_tag_name("标签名")
当有多个相同的标签名时,返回的是第一个
link_text:<a></a>标签元素的全部文本内容
driver.find_element_by_link_text("a标签的所有文本内容")
partial_link_text
<a></a>标签元素的局部文本内容
driver.find_element_by_partial_link_text("a标签的局部文本内容")
xpath:元素路径
路径
绝对路径:以根节点开始,以/html开始,用/来分隔元素
相对路径:可以从任意节点开始,以//tag_name(或则//*)开始,用//分隔元素
xpath路径中可以使用下标代表同标签名的不同元素,下标从1开始
路径+属性
//tag_name[@attribute='值']
//*[@attribute='值']
当使用class属性时,所有class属性值都要写
路径+属性+逻辑
//tag_name[@attribute1='值1' and @attribute='值2']
路径+层级+属性
//tag_name[@attribute='值']/tag_name
扩展
包含xx://*[contains(@attribute,'xx')]
以xx开头://*[starts-with(@attribute,'xx')]
文本内容是xx://*[text()='xx']
css:元素样式
id选择器
根据元素id属性:#id
class选择器
根据元素class属性:.class
多个class属性值时,只用其中一个
元素选择器
根据元素标签名:tag
属性选择器
根据元素身上的属性:[attribute='xx']
当使用class属性是,需要用class所有的属性值
层级选择器
父子层级
element1 >element2
后代层级
element1 element2
扩展
包含xx:[attribute* = 'xx']
以xx开头:[attribute^ = 'xx']
以xx结尾:[attribute$ = 'xx']
定位一组元素
find_elements_by_xxx()
定位的是符合要求的一组元素
返回的是一个列表
列表中的下标是从0开始的
元素定位的两种写法
driver.find_element_by_xxx(”信息“)
driver.find_element(By.xxx,”信息“)
需要导入By类
from selenium.webdriver.common.by import By
元素常用操作
点击:ele.click()
输入:ele.send_keys()
清空:ele.clear()
获取元素信息的方法
返回元素大小
ele.size
获取元素文本
ele.text
获取元素的属性值
ele.get_attribute("属性名")
判断元素是否可见
ele.is_displayed()
判断元素是否可用
ele.is_enabled()
判断元素是否选中,检查单、复选框
ele.is_selected()
鼠标操作
鼠标操作封装在ActionChains类中
from selenium.webdriver.common.action_chains import ActionChains
操作鼠标方法需要用ActionChains实例化的对象
action = ActionChains(driver)
需要传入一个driver参数
常用鼠标操作方法
点击
action.click(element)
右击
action.context_click(element)
双击
action.double_click(element)
悬停
action.move_to_element(element)
拖拽
action.drag_and_drop(element1,element2)
执行
action.perform()
鼠标操作步骤
1、导包
from selenium.webdriver.common.action_chains import ActionChains
2、实例化鼠标对象
action = ActionChains(driver)
3、鼠标操作
action.click(element)
4、鼠标执行操作,必须要执行才会生效
action.perform()
键盘操作
键盘操作封装在Keys类中
from selenium.webdriver.common.keys import Keys
常用的键盘操作
删除键:driver.send_keys(Keys.BACK_SPACE)
空格键:driver.send_keys(Keys.SPACE)
制表键:driver.send_keys(Keys.TAB)
回退键:driver.send_keys(Keys.ESCAPE)
回车键:driver.send_keys(Keys.ENTER)
全选:driver.send_keys(Keys.CONTROL,'a')
复制:driver.send_keys(Keys.CONTROL,'c')
粘贴:driver.send_keys(Keys.CONTROL,'v')
下拉框操作
下拉框是<select></select>时
操作select标签,需要Select类操作
from selenium.webdriver.support.select import Select
实例化Select类对象,才能使用Select类中的方法
select = Select(element)
element是这个下拉框select元素
element = driver.find_element(By.xxx, 'xx')
select对应选项
下拉框option的索引:select.select_by_index(index)
下拉框option的值:select.select_by_value(value)
下拉框option显示的文本:select.select_by_visible_text(text)
下拉框操作步骤
1、导包
from selenium.webdriver.support.select import Select
2、实例化对象
select = Select(driver.find_element(By.xxx, 'xx'))
3、选择对应选项
select.select_by_index(index)
元素等待
元素等待的概念
定位页面元素未找到时,会在设置的一定时间内一直寻找
影响页面加载的因素
网络速度慢
电脑配置低
服务器处理请求速度慢
隐式等待
定位元素,如果能定位到该元素,直返回元素,不进行待待,如果定位不到,则在最长的等待时间每隔一段时间刷新页面再去定位,如果在达到最长等待时没有找到元素,则会抛出异常
异常类型:NoSuchElementException
隐式等待只需要设置一次,针对后面的定位元素的方法都有效
方法:driver.implicitily_wait(timeout)
显示等待
定位元素时,如果能定位到该元素,则直接返回该 回素,不会等待,如果不能定位到元素,会每隔一段时间再去定位这个元素,如果在最长的等待时间内没有定位到该 元素,则抛出异常
异常类型:TimeOutException
显示等待针对单个元素
方法:WebDriverWait(driver, timeout, 间隔时间).until(lambda x:x.find_element(By.xx,'xx'))
需要导入WebDriverWait
from selenium.webdriver.support.wait import WebDriverWait
强制等待
强制让代码休眠
方法:time.sleep()
显示等待和隐式等待的区别
作用域
隐式等待设置一次,后面全部查找元素都有效
显示值针对单个元素
使用方法
隐式:driver.implicitily_wait(timeout)
显示:WebDriverWait(driver, timeout, 间隔时间).until(lambda x:x.find_element(By.xx,'xx'))
抛出异常
隐式:NoSuchElementException
显示:TimeOutException
同时使用时,以显示等待为主
滚动条操作
selenium里面没有直接操作滚动条的方法,需要依赖JS执行。selenium中有调用js的方法
js脚本
js = "window.scrollTo(0, 10000),以像素为单位
selenium执行js脚本
driver.execute_script(js)
弹出框操作
Selenium中对处理弹出框的操作,有专用的处理方法;并且处理的方法都一样
弹出框的类型
alert:警告框
prompt:提示框
confirm:确认框
获取弹出框对象
alert = driver.switch_to.alert
弹出框操作
确认选项
alert.accept()
取消选项
alert.dismiss()
返回alert/confirm/prompt中的文字信息
alert.text
frame切换
在Selenium中封装了如何切换frame框架的方法
切换frame:driver.switch_to.frame(iframe元素对象)
如果要对多层级的iframe进行操作的话,就需要切多少次
切换至首页:driver.switch_to.default_content()
同一个层级的iframe切换,一定需要回到首页之后再来进行切换
不管在哪一个层级,只要调用driver.switch_to.default_content()这个方法就一定会切回首页
多窗口切换
在Selenium中封装了获取当前窗口句柄、获取所有窗口句柄和切换到指定句柄窗口的方法
句柄:英文handle,窗口的唯一识别码
获取当前窗口句柄
handle = driver.current_window_handle
获取所有窗口句柄
handles = driver.window_handles
handles是一个列表,列表中的最后一个是最新打开的窗口,用-1表示
切换到指定句柄窗口
driver.switch_to.window(handle)
窗口截图
自动化脚本是由程序去执行的,因此有时候打印的错误信息并不是十分明确。如果在执行出错的时候 对当前窗口截图保存,那么通过图片就可以非常直观地看到出错的原因。
在Selenium中,提供了截图方法,我们只需要调用即可
方法:driver.get_screenshot_as_file(文件路径名称.png)
路径中所有的目录都是手动创建的
创建的文件是png格式
上传和下载弹窗
依赖pyautoit的第三方模块
import pyautoit
弹窗中的元素对象需要使用其他软件操作
autoit window info
获取弹出框窗口
autoit.win_wait_active("弹窗的名称", 3)
弹窗中上传
autoit.control_send("弹窗名称", "按钮元素对象", "文件")
弹窗中的点击
autoit.control_click("弹窗名称","按钮元素对象")
验证码
在Web应用中,大部分系统在用户登录注册的时候都要求输入验证码,而我们在设计自动化测试脚本的时候, 就需要面临处理验证码的问题。
Selenium中并没有对验证码处理的方法
常用处理验证码的方法
测试环境去掉验证码
测试环境设置万能验证码
验证码识别技术
通过Python-tesseract来识别图片类型验证码
记录cookie,跳过验证码操作
Selenium中对cookie操作提供相应的方法
cookie_dict:一个字典对象,必选的键包括:"name" and "value"
cookie操作
获取指定名字的cookie
driver.get_cookie(name)
获取本网站所有本地cookies
driver.get_cookies()
添加cookie
add_cookie(cookie_dict)
添加cookie步骤
网页或者抓包获取想要的cookie_dict = {"name":"xx", "value":"xx"}
添加cookie:driver.add_cookie(cookie_dict)
调用刷新方法:driver.refresh()
代码自动化重复执行
备份恢复数据库
依赖os模块
import os
备份
执行自动化代码前,备份数据库
mysqldump -uroot -proot -B 数据库名 --tables 表名>./Desktop/备份库.sql
恢复
def restore_db():
cmd = "mysql -uroot -proot 数据库名 < 绝对路径/备份库.sql"
d = os.system(cmd)
# print(d)
cmd = "mysql -uroot -proot 数据库名 < 绝对路径/备份库.sql"
d = os.system(cmd)
# print(d)
执行完代码后删除插入的数据
依赖pymysql模块
import pymysql
操作步骤
def delete_db():
#实例化数据库连接
conn = pymysql.connect("地址", "用户名" ,"密码", "数据库名")
#定义操作数据库的游标
corsur = conn.cursor()
#定义删除数据SQL脚本
sql = "delete from tp_users where 条件(刚刚插入的数据)"
#执行定义好的SQL命令
corsur.execute(sql)
#退出SQL的连接
conn.close()
#实例化数据库连接
conn = pymysql.connect("地址", "用户名" ,"密码", "数据库名")
#定义操作数据库的游标
corsur = conn.cursor()
#定义删除数据SQL脚本
sql = "delete from tp_users where 条件(刚刚插入的数据)"
#执行定义好的SQL命令
corsur.execute(sql)
#退出SQL的连接
conn.close()
定义一个函数保证每次生成的数据都不一致
def get_mobile():
# 列表中用来确定手机号码的格式
mobiles = ["134","135","136","137"]
#从时间戳中获取手机号码的后8位
m_time = str(int(time.time()))[2:]
#随机从mobile列表中取一个手机的开头号码+后8位....
mobile = random.choice(mobiles)+m_time
# print(mobile)
return mobile
# 列表中用来确定手机号码的格式
mobiles = ["134","135","136","137"]
#从时间戳中获取手机号码的后8位
m_time = str(int(time.time()))[2:]
#随机从mobile列表中取一个手机的开头号码+后8位....
mobile = random.choice(mobiles)+m_time
# print(mobile)
return mobile
unittest框架
依赖环境:unittest
import unittest
uniittest优点
组织和管理多个测试用例执行
丰富的断言库
可以自动生成测试报告
五大核心组件
TestCase
定义测试用例
使用方法
文件名必须是test_开头
使用时必须导包:import unittest
定义的测试类必须继承unittest.TestCase
定义的测试用例方法必须是test开头
TestSuite
测试套件,可以把多条测试用例添加至这个套件中
TestSuite只添加测试用例不执行,执行需要使用TestRunner
使用方法
必须先导包
import unittest
创建suite对象
suite = unittest.Test Suite()
添加测试用例
一条一条添加
suite.addTest(ClassName("method_name"))
当前测试类下所有用例一次性添加
suite.addTest(unit test.makeSuite(ClassName))
添加其他测试套件
suite.addTest(suite1)
TestRunner
执行测试套件中的测试用例
使用方法
创建testRunner实例化对象
runner = unittest.TextTestRunner()
执行
runner.run(suite)
TestLoader
TestLoader可以直接将测试用例加载到suite里面,不需做实例化的操作
使用方法
suite = unittest.TestLoader().discover(test_dir, pattern='test*.py')
test_dir 表示的是测试文件存放的目录
pattern代表的是搜索条件
其他写法
unittest.defaultTestLoader.discover(test_dir, pattern='test*.py')
Fixture
Fixture分类
方法级别的fixture
每个测试用例运行都执行一遍 fixture中的内容
初始化/前置处理
def setUp(self):
pass
pass
销毁/后置处理
def tearDown(self):
pass
pass
类级别的fixture
每个测试类运行都执行一遍fixture中的内容
@classmethod 装饰器
初始化/前置处理
@classmethod
def setUpClass(cls):
pass
def setUpClass(cls):
pass
销毁/后置处理
@classmethod
def tearDownClass(cls):
pass
def tearDownClass(cls):
pass
模块级别的fixture
每个模块执行一边fixture中的内容
模块级别的fixture方法必须定义在测试类的外面
初始化/前置处理
def setUpModule():
pass
pass
销毁/后置处理
def tearDownModule():
pass
pass
断言
由程充代替人工进行判断程序执行的结果是否符合预期结果的过程
参数化
跳过
HTML测试报告
依赖环境:HTMLTestRunner.py
POM
思想
封装步骤
数据驱动
日志收集
依赖环境:logging模块
日志简介
logging日志模块的四大组件
日志器
处理器
格式器
过滤器
邮件发送
依赖环境:smtplib模块
0 条评论
下一页
为你推荐
查看更多