一、windows下安装及环境配置
- Python安装,本文中安装的是2.x版本。去下载
- 配置环境变量:我的电脑-属性-高级系统设置-环境变量,将以下变量加入Path中
C:\Python27;C:\Python27\Scripts
- 检查python是否正确安装和配置:
Win+R输入cmd或powershell,命令行输入“python”检查,出现Python 2.7.x...等字样表示安装配置完成 - 安装selenium:使用pip命令(最新版python 2.7或3.6都默认带有pip),命令行输入以下命令即可
pip install selenium
- 下载webdriver,解压后放在path环境变量的路径下,或者与python脚本放在同一文件夹下
Chrome驱动,各版本的文件夹中notes.txt标注了支持的Chrome版本,根据自己安装的Chrome版本选择即可
Firefox驱动,直接下载最新版本使用
Edge驱动
Safari驱动
二、知识储备
- html+css基础
- javascript基础,需要在脚本中执行js
- python基础,以及unittest框架
三、简介
最基础的用法如下:
from selenium import webdriver #导入webdriver
driver = webdriver.Firefox() #创建实例并打开浏览器,此处为Firefox
driver.get("www.google.com") #get(url)方法打开指定URL
assert “Google” in driver.title #断言检测页面title是否为期望值
driver.close() #关闭当前浏览器窗口
driver.quit() #关闭浏览器并退出webdriver
利用unittest的test suite方式:
1、针对待测事物写test case,继承TestCase类,定义test_xxx方法
2、在各test代码后面构造测试集,并调用runner执行测试,如:
if __name__ == "__main__":
suite = unittest.TestSuite()
suite.addTest(test_xxx())
...
runner = unittest.TextTestRunner()
runner.run(suite)
3、创建一个执行所有用例的文件,例如:
import unittest
import testCaseA, testCaseB...
suite = unittest.TestSuite()
suite.addTest(testCaseA.testXxx())
suite.addTest(testCaseB.testXxx())
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite)
四、元素的定位
1.基础定位方式有如下几种:
- find_element_by_id —— 通过id定位
- find_element_by_name —— 通过name定位
- find_element_by_class_name —— 通过class name定位
- find_element_by_link_text —— 通过link text定位
- find_element_by_partial_link_text —— 通过匹配部分link text定位
- find_element_by_tag name —— 通过tag name定位
- find_element_by_xpath —— 通过xpath定位
- find_element_by_css selector —— 通过CSS选择器定位,推荐
2.定位元素组
使用find_elements_by_xxx方法,常用于批量操作对象,如勾选所有checkbox,例:
# 选择所有的checkbox并全部勾上
checkboxes = dr.find_elements_by_css_selector('input[type=checkbox]')
for checkbox in checkboxes:
checkbox.click()
# 选择页面上所有的input,然后从中过滤出所有的checkbox并勾选之
inputs = dr.find_elements_by_tag_name('input')
for input in inputs:
if input.get_attribute('type') == 'checkbox':
input.click()
# 把页面上最后1个checkbox的勾给去掉
dr.find_elements_by_css_selector('input[type=checkbox]').pop().click()
3.层级定位
层级定位:实际项目中有很多个属性基本相同的元素,需要具体定位到其中的一个,这时需要先定位父元素,然后再定位到子孙元素,如:find_element_by_id('parent').find_element_by_id('child')
4.button group按钮组
定位思路是先找到button group的div,然后通过层级定位,用index或者属性去定位具体的按钮,例:
# 定位text是second的按钮
buttons = dr.find_element_by_class_name('btn-group').find_elements_by_class_name('btn')
for btn in buttons:
if btn.text == 'second': print 'find second button'
5.button dropdown
button dropdown按钮把按钮和下拉菜单放在一起,处理思路是先点击这个按钮,等待下拉菜单显示后,通过层级定位获取下拉菜单中的选项,例:
#点击下拉菜单
dr.find_element_by_link_text('Info').click()
#找到dropdown-menu父元素
WebDriverWait(dr,10).until(lambda the_driver: the_driver.find_element_by_class_name('dropdown-menu').is_displayed())
#找到better than
menu = dr.find_element_by_class_name('dropdown-menu').find_element_by_link_text('better than')
6.navs
navs用于简单的tab导航栏,通常先定位ul再层级定位到li即可,或者直接根据link_text定位
7.面包屑
面包屑一般来说当前层级都没有链接,而副层级基本是链接,所以思路基本上是:先找到面包屑所在div或ul,再找到其下所有链接,这些链接就是父层级,最后不是链接的就是当前层级了
8.分页
一般分页需要知道的是:总共的页数,当前页数,是否可以上下翻页,或者直接跳转
分页通常使用ul来实现,当前页一般是没有链接的,通过class name = active定位,其它2个信息按页面情况获取
四、元素的操作:
1.获取对象的属性及内容
通过webdriver的element.attribute()方法获取dom元素属性
获取css属性:element.value_of_css_property()
2.获取对象的状态
通常需要获取对象的四种状态:
- 是否显示——使用element.is_displayed()
- 是否存在——使用find_element_by_xxx方法,捕获抛出的一场,如果存在异常则不存在
- 是否被选中——一般是判断表单元素是否被选中,如radio或checkbox,通过element.is_selected()方法
- 是否enable——使用element.is_enabled()
3.一些基本的操作
- click() 点击对象
- send_keys() 在对象上模拟按键输入或往文本框赋值(需要
form selenium.webdrive.common.keys import Keys
) - clear() 清除对象内容
- submit() 用于提交表单,特别用于没有提交按钮的情况,比如搜索框输入关键字后按回车搜索的(也可以通过模拟回车键来实现)
4.执行js
通常需要在页面上或者定位的元素上执行js,而webdriver就提供了execute_script()接口来执行js
js = "some javascripts"
driver.execute_script(js)
5.等待
在页面进行操作致使一些元素隐藏或出现时,或者等待ajax执行完成时,需要用到WebDriverWait的until方法等待(显式等待),需要用到的是selenium.webdriver.support.ui.WebDriverWait类,until方法会一直等下去,直到
- 代码块中的内容为true(不为false或没有抛出异常)
- 超时,即超过timeout设定的时间
例如等待直到某元素显示
wait = selenium.webdriver.support.ui.WebDriverWait(driver, 10)
wait.until(lambda driver: driver.element.isdisplayed()) #lambda为Python创建匿名函数的关键字
隐式等待,是指通过一定的时长等待页面所有元素加载完成,如果超出了设置的时长而元素还没有被加载则抛出NoSuchElementException异常。WebDriver提供了implicitly_wait()方法来实现隐式等待,默认设置为0.
6.复杂的操作
1. ActionChains模拟鼠标操作
- perform() 执行所有ActionChains中存储的行为
- context_click() 右击
- double_click() 双击
- drag_and_drop() 拖动
- move_to_element() 鼠标悬停
2.frame切换
页面嵌套frame时,若要定位frame中的元素,需要通过switch_to_frame(id/name)方法先将定位主体切换到frame里。
如果iframe没有id或name可以定位,则先通过其它方式先定位到frame,再将定位对象传给switch_to_frame()方法。
如果完成了在当前frame上的操作,可以通过switch_to_default_content()方法返回上一层表单。
3.多窗口切换
通过switch_to_window()方法切换到任意窗口。
current_window_handle——获得当前窗口句柄
window_handles——返回所有窗口的句柄到当前会话
switch_to_window(handle)——根据给的句柄切换到相应窗口
4.警告框处理
处理JS生成的alert、confirm以及prompt做法是通过switch_to_alert()方法定位到alert/confirm/prompt,然后使用text/accept/dismiss/send_keys执行对应操作
- text 返回提示框中的文字信息
- accept 点击确认按钮
- dismiss 点击取消按钮(当存在取消按钮时可用)
- send_keys 输入值(仅prompt可用)
5.文件上传
- 对于用过input标签实现的上传,可以将其看作一个输入框,通过send_keys()传入本地文件路径从而模拟上传功能。
- 借助Autolt实现上传。首先通过AutoIt写好脚本并转换成exe可执行文件,然后在python中,打开上传文件对话框,再调用os.system('xxx.exe')运行exe来实现上传。
6.文件下载
- 通过编辑配置文件将文件下载到默认路径
- 通过AutoIt脚本实现
7.操作cookie
- get_cookies() 获得所有cookie信息
- get_cookie(name) 返回有特定name值得cookie信息
- add_cookie(cookie_dict) 添加cookie,必须有name和value值
- delete_cookie(name) 删除特定部分的cookie信息
- delete_all_cookies() 删除所有的cookie信息
8.窗口截图
webdriver提供了截图函数get_screenshot_as_file()来截取当前窗口
五、遇到的一些坑
- 使用Chrome,登陆后总是弹出记住密码提示框——解决办法:打开Chrome时设置option选项:
options = webdriver.ChromeOptions()
prefs = {"":""}
prefs["credentials_enable_service"] = False
prefs["profile.password_manager_enable"] = False
options.add_experimental_option("prefs",prefs)
driver = webdriver.Chrome(chrome_options = options)
根据关键词搜索结果的断言,思路是
获取搜索结果集,遍历判断对应列的text是否包含关键词,包含则count++,最后判断count与搜索结果总数是否相等(这个想法太蠢了,用循环遍历每个搜索结果,并assert判断是否等于或包含,一个用例可以包含多个断言的,每个断言是并行的,所有assert都通过,结果才是通过的)
问题一:搜索结果较多,分页怎么获取正确数量遇到一个案例,浏览器点击当前页面A元素,打开了新的标签页B之后,实际的window句柄还是在当前A页面,而我想当然以为是新标签页B,然后定位B中的元素发现死都找不到。。。所以如果有打开新的页面,还是需要通过switch_to.window(handler)切换到新的页面