保证脚本的有效性
定位:保证定位有效性,封装处理异常
流程:保证流程有效性,封装独立方法
数据:保证数据有效性,数据备份与恢复
降低自动化维护成本
UI自动化,针对不常变的页面
接口自动化,周期短、变动频繁
框架分层,用例与框架分离
获得cookie
browser = webdriver.Chrome()
# 模拟登录操作
。。。。
list_cookies = browser.get_cookies()
s = requests.Session()
cookies = {}
for cookie in list_cookies:
cookies[cookie['name']] = cookie['value']
requests.utils.add_dict_to_cookiejar(s.cookies, cookies)
#之后就可以通过带有cookies的session去发送请求
。。。
ChromeOptions
Chrome Options是一个配置chrome启动时属性的类,可以配置参数:
参数类型 | 参数 |
---|---|
设置chrome 二进制文件位置 | binary_location |
添加启动参数 | add_argument |
添加扩展应用 | add_extension,add_encoded_extension |
添加实验性质的设置参数 | add_experimental_option |
设置调试器地址 | debugger_address |
- 调用chromeOptions
from selenium import webdriver
options = webdriver.ChromeOptions()
......
browser = webdriver.Chrome(chrome_options=option)
- 去掉提示“正在受到自动测试软件的控制”
option.add_argument('disable-infobars')
- 设置窗口大小
option.add_argument('--window-size=1366,768')
或者
browser.set_window_size(480, 800) #移动端大小
- 最大化运行
browser.maximize_window()
or
option.add_argument('--start-maximized')
- 设置编码格式
option.add_argument('lang=zh_CN.UTF-8')
- 设置UA请求头
option.add_argument('User-Agent=Mozilla/5.0')
- 无界面浏览器
option.add_argument('--headless')
- 禁止加载图片
my_prefs = {"profile.managed_default_cotent_settings.images": 2}
option.add_experimental_option("prefs", my_prefs)
- IP代理
# 设置无账号密码的代理
option.add_argument('--proxy-server=http://ip:port')
# 设置有账号密码的代理,需要其他插件
关闭是否保存密码的提示框
prefs = {}
prefs['credentials_enable_service'] = False
prefs['profile.password_manager_enabled'] = False
option.add_experimental_option("prefs", prefs)
- 指定浏览器的分辨率
option.add_argument('window-size=1920 × 3000')
或者
browser.set_window_size(480, 480)
- 手动指定浏览器的位置
option.binary_location = r'绝对路径chrome.exe'
-
浏览器刷新
browser.refresh() -
浏览器后退
browser.back() -
浏览器前进
browser.forward()
异常
- find_element如果找不到元素会报异常;find_elements如果找不到元素会返回[]
判断元素是否存在
通过find_elements方法,根据返回列表的长度判断是否有该元素。
selenium.IsElementPresent(xpath)
#自定义方法
def isElementExist(self,element):
flag=True
browser=self.driver
try:
browser.find_element_by_css_selector(element)
except:
flag=False
finally:
return flag
xpath一般定位
1、选取当前节点的父节点:..,选取当前节点:.
2、选取属性:@
3、选取当前节点下的子节点,不考虑位置://
4、选取当前节点下的直属节点:/
5、匹配任何元素节点:*
6、匹配任何属性节点:@*
7、文本包含字段://*[contains(@name, ‘value’)]
8、不含有属性://*[not(@name)]
9、开始值://*[start-with(@id, ‘as’)]
10、结束值://*[ends-with(@id, ‘as’)]
11、最后一个节点://div[last()]
获取哥哥节点://div[@id=“id1”]/../div[1]
获取哥哥节点://div[@id=“id1”]/preceding-sibling::div[1],获取所有同级哥哥节点,数字越大表示离当前节点越远。
获取弟弟节点://div[@id=“id1”]/…/div[3]
获取弟弟节点://div[@id=“id1”]/following-sibling::div[1]
normalize-space标准化,关于空格的处理
xpath轴定位
-
匹配包含某属性的所有的属性值
//@属性名
返回值是一个list -
选取若干路径,在一个xpath中写多个表达式,互不干扰
“第一个表达式 | 第二个表达式”
返回值是一个list -
选取当前节点的所有子元素(子)
child:: -
选取当前节点的所有属性
attribute:: -
选取父辈元素(父、祖父)
ancestor::
(’//div[@id=“testid”]/ancestor::div/@price’) #定位父辈div元素的price属性值 -
选取父辈元素及当前元素
ancestor-or-self:: -
选取后代元素(子、孙)
descendant:: -
选取后代及当前元素
descendant-or-self:: -
选取当前节点的结束标签之后的所有标签(同级弟、表弟)
following:: -
选取当前节点的结束标签之后的同级标签(同级弟)
following-sibling:: -
选取当前节点的父节点(父)
parent::
数字越大,距离越远 -
选取当前节点的开始标签之前的所有节点
preceding:: -
选取当前节点之前的所有同级节点
preceding-sibling:: -
选取当前节点
self:: -
定位
li[position()=2] -
字符串连接
concat(str1, str2) -
获得第一个节点下的值
string(//li) -
解析节点的名称
local-name(’//*[@id=“as”]’) -
对某两个节点的属性值做除法
属性值1 div 属性值2
拖动滑动条
js = "var q=document.documentElement.scrollTop=1000000"
or
js = "window.scrollTo(0,document.body.scrollHeight)" # window.scrollTo(x,y)
browser.execute_script(js)
or
browser.execute_script("window.scrollTo(document.body.scrollHeight,0)")
or
#获取焦点
target = browser.find_element_by_class_name('top-div')
b.execute_script("arguments[0].focus();", target)
or
#拖动到可见的元素去
target = browser.find_element_by_id('1')
browser.execute_script("arguments[0].scrollIntoView();", target)
frame标签
frame标签有三种:frameset、frame、iframe。其中frameset是普通标签,无需切换;frame需要层层切进去。
- 切换到frame中:switch_to.frame(fererence)
参数可以是:id、name、index以及webElement对象 - 切换回主文档:switch_to.default_content()
- 嵌套frame的操作:switch_to.parent_frame() 从子frame切换到父frame
多窗口切换
WebDriver提供switch_to.window()方法实现不同窗口间的切换
- current_window_handle:获得当前窗口句柄
- window_handles:返回所有窗口的句柄到当前会话
- switch_to.window():切换到相应的窗口
# 获得当前所有打开的窗口句柄
all_handles = browser.window_handles
# 获得当前窗口句柄
curr_window = browser.current_window_handle
告警框处理
JS生成的告警框类型有:alert、confirm、prompt。处理告警框首先使用switch_to.alert()方法定位,然后使用text、accept、dismiss、send_keys等进行操作。
- text:返回告警框中的文字信息
- accept():接受现有告警框
- dismiss():解散现有告警框
- send_keys():在告警框中输入文本
执行js
- 将不可见元素改为可见的
修改前的源码
修改后的源码
from selenium.webdriver.common.action_chains import ActionChains as ac
# 执行js修改属性
js = "document.getElementById('licensemg').style.display='block'"
browser.execute_script(js)
# 将光标悬停在元素上进行下一步的操作
ele = browser.find_element_by_id('licensemenu')
ac(browser).move_to_element(ele).perform()
下拉菜单
select有两种模式:单选和多选,功能有:取消选中option、选中option、判断是否是多选模式、获取option。
其中,取消选中仅对多选模式有效;其他方法单选多选均有效。
- 定位下拉菜单控件
from selenium.webdriver.support.select import Select
# 定位下拉菜单的控件位置
div_select = Select(browser.find_element_by_id('select_id'))
- 选中option
#通过文本值定位
div_select.select_by_visible_text('option_text')
# 通过索引定位(索引从0开始)
div_select.select_by_index(index)
# 通过value值定位
div_select.select_by_value(select_value)
- 取消选中option
仅对多选模式有效,否则报异常
# 取消所有选择项
div_select.deselect_all()
# 取消指定index的选择
div_select.deselect_by_index(index)
# 取消指定value值的选择
div_select.deselect_by_value(value)
# 取消指定文字项的选择(单选模式无效,但不会报异常)
div_select.deselect_by_visible_text(text)
- 判断是否是多选
返回boolean
div_select.is_multiple()
- 获取option
# 返回所有的option(没有option时,会返回空列表,不报异常)
div_select.options()
# 返回所有已选中的option(没有option被选中,会返回空列表,不报异常)
div_select.all_selected_options()
# 返回选中的第一个option(没有option被选中,会报异常)
div_select.first_selected_option()
单选按钮和复选框
一般情况下,这两种标签都是input标签,可以通过点击的方式进行选中。
可按照一般元素进行定位。
Checkbox:
<input type=“checkbox” value=“cv1” name=“c1”>
<input type=“checkbox” value=“cv2”>
Radio:
<input type=“radio” value=“rv1” name=“r1”>
<input type=“radio” value=“rv2” name=“r1”>
判断是否被选中:
div.is_selected(),返回boolean
上传文件
如果是多文件上传,则“路径1” 空格 “路径2”
- 如果选择文件框是input形式的(符合input和type="file"两个条件):
1、选择文件
可直接定位选择文件的元素,调用方法send_keys(文件路径)
2、上传文件
定位上传文件按钮,调用方法click() - 选择文件框不是input形式
selenium + AutoIt。首先在AutoIt中编写操作Windows GUI的脚本,然后将脚本生成exe文件,之后再python程序中执行exe文件(os.system(exe文件路径))。
A、AutoIt介绍
AutoIt是一个使用类似BASIC脚本语言的免费软件,设计用于Windows GUI中进行自动化操作。利用模拟键盘按键,鼠标移动和窗口/控件的组合来实现自动化任务。
AutoIt Windows Info用于帮助我们识别Windows控件信息,例如上传文件时选择文件和打开操作。
SciTE Script Editor用于编写AutoIt脚本。
Run Script用于执行AutoIt脚本(.au3文件)。
Compile Script to .exe用于将AutoIt生成exe执行文件。
B、选择多份文件
对话框
1、获得当前窗口
driver.current_window_handle()
2、获得所有窗口
driver.window_handles()
3、切换窗口
driver.switch_to_window(handle)
模拟鼠标操作ActionChains
ActionChains可以模拟鼠标操作:单击、双击、右击、拖拽等。
from selenium import webdriver
from selenium.webdriver.commom.action_chains import ActionChains
driver = webdriver.Chrome()
action = ActionChains(driver)
- 点击鼠标左键
click(on_element=None) - 长摁鼠标左键
click_and_hold(on_element=None) - 点击鼠标右键
context_click(on_element=None) - 双击鼠标左键
double_click(on_element=None) - 拖拽到某个坐标然后松开
drag_and_drop_by_offset(source,xoffset,yoffset) - 拖拽到某个元素然后松开
drag_and_drop(source, target) - 按下键盘上的键
key_down(value, element=None) - 松开某个键
key_up(value, element=None) - 鼠标从当前位置移动到某个坐标
move_by_offset(xoffset,yoffset) - 鼠标移动到某个元素
move_to_element(to_element) - 移动到距某个元素(左上角坐标)多少距离的位置
move_to_element_with_offset(to_element, xoffset, yoffset) - 执行链中的所有动作
perform() - 在某个元素位置松开鼠标左键
release(on_element=None) - 发送某个键到当前元素
send_keys(*keys_to_send) - 发送某个键到指定元素
send_keys_to_element(*keys_to_send)
功能键Keys
用send_keys()发送键盘的按键
from selenium.webdriver.commom.keys import Keys
Keys.ENTER #回车
Keys.BACK_SPACE #删除
Keys.TAB #制表
Keys.SPACE #空格
Keys.ESPACE #回退
(Keys.CONTROL, 'a') #全选
Keys.F1 #键盘F1
等待的几种方式
- sleep()
- 隐式等待
browser.implicitlyWait(10),如果超出时长仍没加载则抛出NoSuchElementException异常,作用范围是webdriver对象的整个生命周期。 - 显示等待(推荐)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
ele = WebDriverWait(browser, 5, 0.5).until(EC.presence_of_element_located((By.ID, "kw")))
代码解析:
a、WebDriverWait(浏览器驱动,timeout,poll_frequency检测的间隔时间 默认0.5s,ignored_exceptions超时后的异常信息 默认抛NoSuchElementException异常)
b、WebDriverWait()一般与until()或until_not()方法配合使用
c、until(method,message="")调用该方法提供的驱动程序作为一个参数,直到返回True
d、until_not(method,message="")调用该方法提供的驱动程序作为一个参数,直到返回False
e、presence_of_element_located()判断元素是否存在
f、expected_conditions类提供的预期条件判断的方法(全部返回boolean):
方法 | 说明 |
---|---|
title_is | 判断当前页面的title是否完全等于==预期字符串,返回布尔值 |
title_contains | 判断当前页面的title是否包含预期字符串,返回布尔值 |
presence_of_element_located | 判断某个元素会否被加到了dom树里,但不一定可见,需要传入locator |
visibility_of_element_located | 判断某个元素是否可见 |
visilility_of | 判断某个元素是否可见,传入element |
presence_of_all_elements_located | 判断是否只有一个元素存在于dom树中。 |
text_to_be_presnet_in_element_value | 判断某个元素中的value属性是否包含了预期的字符串 |
text_to_be_present_in_element | 判断某个元素中的text是否包含了预期的字符串 |
frame_to_be_avaliable_and_switch_to_it | 判断frame是否可以switch进去,是则返回True并switch进去,否则返回False |
invisibility_of_element_located | 判断某个元素中是否不存在于dom树或不可见 |
element_to_be_clickable | 判断某个元素是否可点击:可见并是enable的 |
staleness_of | 判断某个元素是否被选中,一般用在下拉列表 |
element_selection_state_to_be | 判断某个元素的选中状态是否符合预期,传入element |
element_located_selection_state_to_be | 判断某个元素的选中状态是否符合预期,传入locator |
alert_is_present | 判断页面上是否存在alert |
- 使用javascript
GUI自动化工具——PyAutoGUI
PyAutoGUI的目的是可以用