背景
公司的会议室资源一直很紧缺,需要提前通过内网系统预定,为了保证团队每天有会议室可用,组内的测试妹子甚至每天8点准时守在电脑前抢会议室......简直就是春运抢票的缩影。
最近这个妹子由于种种原因离职了,抢会议室这个吃力不讨好的活儿,自然谁也不愿意接。于是,身为一名优秀普通自动化测试的我(滑稽脸😛),为了体现自己的价(装)值(逼),毅然跟领导承诺......那就写一个抢会议室神器吧!
本打算写一个简单的python爬虫就完事交差了,可是当我打开会议室系统熟练地按下F12后,不禁陷入了沉思....😔
会议室系统全是由各种js、iframe、ajax组成,还有十几个长达数十位字母的参数以及各种没见过的token。想用普通的爬虫搞定它,仅仅研究这些参数的含义估计都得吐好几升血。
不过好在机智的码农总有方法,既然爬虫搞不定,那我就直接模拟手动抢会议室嘛!借助Web自动化神器---Selenium。虽然效率低了点,但抢会议室还是够用了。
说干就干,第一步:先学习Selenium!
学习Selenium
公司内的自动化主要应用于Win桌面端产品,是公司自主研发的一套测试框架,基于ruby语言,与主流的Web自动化相距甚远。所以本次学Selenium也算是从零开始入门。
学习资料:找同事借的一本书---Selenium 2自动化测试实战基于Python语言
一、Selenium3.0简介
Selenium是一款开源、应用最广的web自动化测试框架,支持主流的Firefox、Chrome、IE甚至android移动端浏览器。支持主流的java、python、ruby、C、C++、C#等语言。目前已经发展到Selnium3.0。
Selenium3.0主要由Webdriver、Selenium Grid、Selnium IDE组成。
Webdriver:selenium的核心部分,通过原生浏览器支持或者浏览器扩展来直接控制浏览器,支持多语言编写脚本。(Webdriver曾经也是一款独立的自动化框架,还是selenium1.0的竞争对手,不过后来两者居然合并了!)
Selnium IDE:一款FireFox浏览器的插件,支持录制、回放脚本,调试神器!
Selenium Grid:一种自动化的测试辅助工具,能实现分布式运行。(这个没有研究过)
本次主要介绍webdeiver、selenium IDE的用法。
二、Selenium安装方法
步骤:
1、配置python2.7环境
2、安装selenium for python库:pip install selenium
3、下载对应的webdriver驱动,并加入path环境变量
详细安装方法:略。(度娘一大堆)
需要注意的是,对于不同浏览器需要下载对应的webdriver驱动,比如本人用chrome测试,需要下载chromedriver.exe,并且最好使用最新的chrome浏览器,以保证兼容性。
*#测试selenium是否安装成功:*
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("www.baidu.com")
#执行该脚本,会启动chrome浏览器,并访问百度主页
三、webdriver定位方法
selenium主要提供了以下8种定位html元素方法,前6种就是比较常见的html元素定位方法,比如id、name、class、link等。除此以外,还支持css 语法定位,以及xpath定位。(xpath定位简直是定位神器,几乎没有它定位不到的元素,这个一定要掌握!xpath学习资料)
- find_element_by_id()
- find_element_by_name()
- find_element_by_class_name()
- find_element_by_tag_name()
- find_element_by_link_text()
- find_element_by_partial_link_text()
- find_element_by_xpath()
- find_element_by_css_selector()
#举例:
from selenium import webdriver
driver = webdriver.Chrome()#
driver.get("www.xxxx.com")
driver.find_element_by_id("btn").click() #找到id为btn的控件并点击。
四、控件常用方法
selenium也对控件提供了丰富的方法(比如上面的例子click()方法)。用于对控件操作,比如 点击、输入文本、获取控件大小、获取控件的文本信息等。详细如下:
clear() # 清除文本,一般用于文本框。
send_keys (value) #模拟按键输入,比如输入账号密码。
#除了常用的输入字符串以外,还能输入快捷键,相亲可以研究selenium.webdriver.common.keys
click() # 单击元素。
submit() #提交表单,比如相当于填完账号密码后点击回车
size() #获取控件的大小
text() #获取控件的文本信息
get_attribute(name) #获取控件的属性信息。比如某个控件里可能有id、tagname、class、src等属性,可以通过该方法获得具体的属性值。
五、设置控件元素等待
一般而言,基于UI的自动化测试,在操作控件时都需要设置等待时间,原因是有些控件默认是不显示的,只有在软件执行某些操作后才会显示出来。比如web网页,需要等待网页完全刷新后才能进行下一步操作。否则脚本会报错找不到控件。
selenium提供了两种等待元素方法,分别为显示等待与隐式等待。(不建议在脚本中使用sleep函数,sleep等待的时间是固定的,可能过长也可能过短,都不合适。我们需要的是动态等待)
显示等待:等待某个控件出现为止,若超时都未找到控件否则抛异常。等待的超时时间以及间隔由参数控制。
#例:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
element = WebDriverWait(driver, 5, 0.5).until(
EC.presence_of_element_located((By.ID, "kw"))
)
#1、presence_of_element_located 用于判断元素是否存在,返回结果为Boolean类型
#2、WebDriverWait为等待函数,它会等待unitil()中的返回值为True为止。参数表示每隔0.5s查找一次,最长找5s。
#3、也可配合not_until()函数食用,表示等待返回结果为False为止。
隐式等待:这个比较灵活,在操作所有元素时,若未找到元素,就会自动等待该元素,直到等到元素出现才继续操作。若超时仍未找到元素,则抛异常。
#例:
driver.implicitly_wait(10) #若能找到元素,不会等待;若未找到元素则等待元素出现为止,最长等待10s。
六、多表单(iframe)切换
如今的web技术发展越来越成熟,早已不是最原始的静态页面了。一般主流web都包含各种js、以及frame嵌套,你表面上看是一个页面,其实内部可能包含了多个页面。而对于iframe嵌套,selenium无法直接操作iframe里面的内容(毕竟是属于另一个页面了)。selenium提供的方法是先切换到对应的iframe,然后再操作内部的元素。
#例:
#先定位到具体的frame元素
frame = driver.find_element_by_xpath('//*[@id="x-URS-iframe"]')
#利用switch_to函数切换到具体的frame。然后就能愉快地操作frme里面的东东啦😊
driver.switch_to.frame(frame)
#其它方法
driver.switch_to.parent_frame()#切换到父frame
driver.switch_to.default_content()#切换到最外层frame,其实也就是最原始的页面
[注1]:
在定位网页的frame元素时,可能会遇到这样的场景:页面内的frame标识是在不断动态生成的!
比如:网页有两个弹窗都是iframe,操作第一个弹窗时显示为id1,操作第二个为id2;再次操作第一个弹窗,显示为id3。。。
也就是说iframe的标识是动态的,而不是唯一的,这样就给定位iframe带来了困扰。(公司的会议室系统就是酱子的套路,困扰了好久😭)
不过解决方法也很简单:那就是遍历查找页面内的所有iframe元素,然后取最后一个iframe。一般而言最新创建的iframe都是最后一个。
#举栗:
driver.switch_to.default_content()
frames = driver.find_elements_by_tag_name("iframe")
driver.switch_to.frame(frames[-1])
[注2]:
还有一个问题,在页面有多个ifram的情况下,若要在多个iframe上来回切换,需要先切换到default页面,再切换到另一个frame。
#举栗:
f = driver.find_elements_by_tag_name("id1")
driver.switch_to.frame(f)
driver.switch_to.default_content()#切换到另一个frame前,前切回默认页面。否则可能会切换失败
f2 = driver.find_elements_by_tag_name("id2")
driver.switch_to.frame(f2)
七、其它常用方法
1、屏幕截图
一般在脚本运行时,为了便于分析,截图保存是个不错的选择
driver.get_screenshot_as_file("D:\\baidu_img.jpg")
2、页面刷新
driver.refresh()
3、浏览器前进、后退
driver.forward()
driver.back()
4、退出、关闭浏览器
driver.quit()
八、待续
以上主要是在编写工具时用到的内容,还有一些操作未用到,暂未整理。(比如:鼠标操作、多窗口切换、cookie、js、视频处理等)