1. Selenium 元素定位方法 1.1 元素定位工具:chropath
chropath 官网:https://autonomiq.io/deviq-chropath.html
其它下载地址:https://www.crx4chrome.com/crx/50476
chropath 是一款浏览器插件,用于元素属性识别和自动获取,支持主流浏览器。
我们常规定位元素的方式是通过查看「检查」中的内容,这种方式对于新手来说比较不直观:
而下载了 chropath 之后,则可以快速直观的获取到 “XPath”、”cssSelector”、”tagName” 等相关信息:
1.2 八类基本元素定位方式 在做 WEB UI 自动化时,最根本的就是操作页面上的元素,首先我们要能定位到这些元素,然后才能操作这些元素。
定位方法: driver.find_element(By.XXX, "YYY")
注意: 并不是每个页面的元素都需要用到下面的八种方法,比如一些页面的元素就是没有 id,则就不能用 id 进行定位。
元素名称
By.XXX
id
By.ID
name
By.NAME
class name
By.CLASS_NAME
tag name
By.TAG_NAME
link text
By.LINK_TEXT
partial link text
By.PARTIAL_LINK_TEXT
xpath
By.XPATH
css selector
By.CSS_SELECTOR
1.2.1 通过 ID 定位 例如,百度页面输入框的 ID 属性为 “kw”。
我们通过 ID 定位的结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from selenium import webdriverfrom selenium.webdriver.common.by import Byimport timedriver = webdriver.Chrome() driver.get('http://www.baidu.com' ) element = driver.find_element(By.ID, 'kw' ) element.send_keys('selenium' ) time.sleep(3 ) driver.quit()
1.2.2 通过 Name 定位 还是拿上面百度的例子举例,效果是一样的,都能成功定位到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from selenium import webdriverfrom selenium.webdriver.common.by import Byimport timedriver = webdriver.Chrome() driver.get('http://www.baidu.com' ) element = driver.find_element(By.NAME, 'wd' ) element.send_keys('selenium' ) time.sleep(3 ) driver.quit()
1.2.3 通过 Class Name 定位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from selenium import webdriverfrom selenium.webdriver.common.by import Byimport timedriver = webdriver.Chrome() driver.get('http://www.baidu.com' ) element = driver.find_element(By.CLASS_NAME, 's_ipt' ) element.send_keys('selenium' ) time.sleep(3 ) driver.quit()
1.2.4 通过 Tag Name 定位
注意: 不推荐用 Tag 进行定位,因为一个页面 tag 很可能不是唯一的。
1.2.5 通过 Link Text 定位 Link Text 和 Partail Link Text 都是用于定位超链接元素,例如百度左上角这些元素,点击后会跳转到另一个页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from selenium import webdriverfrom selenium.webdriver.common.by import Byimport timedriver = webdriver.Chrome() driver.get('http://www.baidu.com' ) element = driver.find_element(By.LINK_TEXT, '新闻' ) element.click() time.sleep(3 ) driver.quit()
1.2.6 通过 Partial Link Text 定位 Partial Link Text 和 Link Text 的区别是可以模糊匹配超链接文本,例如有些超链接文本太长,我可以只输入一部分文字进行匹配,就能定位到对应的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from selenium import webdriverfrom selenium.webdriver.common.by import Byimport timedriver = webdriver.Chrome() driver.get('http://www.baidu.com' ) element = driver.find_element(By.PARTIAL_LINK_TEXT, 'hao1' ) element.click() time.sleep(3 ) driver.quit()
1.2.7 通过 Xpath 定位 对于实际场景中,很多元素没办法通过前面的六种简单的方式定位,就需要通过后面两种方式来进行定位,先来看 Xpath 是怎么定位的:
绝对路径:以 / 开头定位,例如 `/html/body/input/xx
相对路径:以 // 开头定位,例如 //input[@id='kw' and @name='wd]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 """ 定位百度搜索框,并输入 selenium """ element = driver.find_element(By.XPATH, "//*[@id='kw']" ) element = driver.find_element(By.XPATH, "//*[@name='wd']" ) element = driver.find_element(By.XPATH, "//*[@id='kw' and @name='wd']" ) element.send_keys('selenium' ) """ 定位文本为「新闻」的超链接,并点击 """ element = driver.find_element(By.XPATH, "//a[text()='新闻']" ) element.click() """ 定位文本为「hao123」的超链接,并点击 """ element = driver.find_element(By.XPATH, "//a[contains(text(), 'hao')]" ) element.click() """ 如果某个元素本身没有唯一的属性可以定位,则可以结合其父节点的属性来唯一定位到这个元素 """ element = driver.find_element(By.XPATH, "//form[@id='form']/span/input" )
1.2.8 通过 CSS Selector 定位 通过 CSS Selector 整体功能和 Xpath 类似,只是 CSS 定位的语法不同,常用语法如下:
以 ID 定位:#id
以 Class Name 定位:.class
以 Tag Name 定位:tag
以 Tag Name 下的某个 ID 定位:tag#id
以 Tag Name 下的某个 Class Name 定位:tag.class
通过其它属性定位:[属性名=属性值]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 """ 定位百度搜索框,并输入 selenium """ element = driver.find_element(By.CSS_SELECTOR, ".s_ipt" ) element = driver.find_element(By.CSS_SELECTOR, "#kw" ) element = driver.find_element(By.CSS_SELECTOR, "input" ) element = driver.find_element(By.CSS_SELECTOR, "input#kw" ) element = driver.find_element(By.CSS_SELECTOR, "input.s_ipt" ) element = driver.find_element(By.CSS_SELECTOR, "input[name='wd']" ) element = driver.find_element(By.CSS_SELECTOR, "input[name='wd'][id='kw']" ) element.send_keys('selenium' )
1.3 复数定位元素方式
定位方法: driver.find_elements(By.XXX, "YYY")
find_elements 属于 selenium 中复数的定位元素内容,find_elements 主要定位页面上多个相同的元素。
例如,我现在想定位百度页面左上角一列的超链接按钮。
而定位的方法其实和上面的 find_element 定位方式一模一样,只是这里的方法名后面多了一个 s,所以我们现在只用找到这些相同元素下相同的属性值用来定位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from selenium import webdriverfrom selenium.webdriver.common.by import Byimport timedriver = webdriver.Chrome() driver.get('http://www.baidu.com' ) elements = driver.find_elements(By.XPATH, "//a[@class='mnav c-font-normal c-color-t' and @target='_blank']" ) print (len (elements))elements[0 ].click() elements[1 ].click() elements.pop().click() time.sleep(3 ) driver.quit()
1.4 元素定位策略 推荐的定位方式的优先级:ID > name > CSS selector > Xpath
定位元素的注意事项:
找到待定位元素的唯一属性
如果该元素没有唯一属性,则先找到能被唯一定位到的父元素/子元素/相邻元素进行辅助定位
不要使用随机唯一属性定位
最重要的是多跟研发沟通,尽量把关键元素加上 ID 或者 name,并减少不合理的页面元素,例如重复 ID 这样的事情最好不要发生
2. Selenium 操作 2.1 元素的操作 在自动化测试中,成功定位到元素后,即可对元素进行相应的操作。
webdriver 中比较常用的操作对象的方法如下:
方法名称
功能
click()
点击对象
send_keys()
在对象上模拟键盘输入
clear()
清楚对象内容
submit()
表单提交,可以触发 action 行为
text
用于获取对象的文本信息
size
用于获取元素尺寸
get_attribute()
获取元素属性
is_displayed()
元素是否可见
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 from selenium import webdriverfrom selenium.webdriver.common.by import Byimport timebrowser = webdriver.Chrome() browser.get("https://www.baidu.com" ) browser.implicitly_wait(30 ) browser.find_element(By.ID, "kw" ).send_keys("python" ) time.sleep(2 ) browser.find_element(By.ID, "kw" ).clear() time.sleep(1 ) browser.find_element(By.ID, "kw" ).send_keys("http" ) time.sleep(2 ) browser.find_element(By.ID, "su" ).click() els = browser.find_element(By.CLASS_NAME, "hint_PIwZX" ) text = els.text print (text) print (browser.find_element(By.ID, "kw" ).size)print (browser.find_element(By.ID, "su" ).size)if browser.find_element(By.ID, "kw" ).is_displayed(): print ("输入框可见" ) print (browser.find_element(By.ID, "su" ).is_displayed())print (browser.find_element(By.ID, "kw" ).get_attribute("type" ))print (browser.find_element(By.ID, "kw" ).get_attribute("value" ))time.sleep(2 ) browser.quit()
2.2 浏览器的操作 在自动化测试中,除了可以对元素进行操作外,同样也支持对浏览器进行控制。
webdriver 中比较常用的操作浏览器的方法:
方法名称
功能
maximize_window
浏览器最大化
set_window_size
设置浏览器的宽和高
back
后退
forward
前进
refresh
刷新
title
打印 title
current_url
打印 url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import timefrom selenium import webdriverbrowser = webdriver.Chrome() browser.maximize_window() first_url = "https://ww.baidu.com" browser.get(first_url) time.sleep(2 ) second_url = "https://news.baidu.com" browser.get(second_url) time.sleep(2 ) print (browser.title)print (browser.current_url)browser.back() time.sleep(2 ) print (browser.title)print (browser.current_url)browser.forward() time.sleep(2 ) print (browser.title)print (browser.current_url)browser.refresh() time.sleep(2 ) browser.quit()
2.3 键盘按键用法 在 Selenium 自动化测试中,要调用键盘按键操作需要引入 keys 包,并通过 send_keys() 调用按键。
Keys() 类提供了键盘上几乎所有按键的方法,这个类可以用来模拟键盘上的按键,包括各种组合键,如 Ctrl+A、Ctrl+X、Ctrl+C、Crtl+V 等等。
属性
含义
Keys.DOWN, Keys.UP, Keys.LEFT, Keys.RIGHT
键盘箭头键
Keys..ENTER, Keys.RETURN
回车和换行键
Keys.HOME, Keys.END, Keys.PAGE_DOWN, Keys.PAGE_UP
Home 键、End 键、Page Up 键、Page Down 键
Keys.ESCAPE, Keys.BACK_SPACE, Keys.DELETE
Esc、Backspace 和删除键
Keys.F1, Keys.F2, …, Keys.F12
键盘顶部的 F1 到 F12
Keys.TAB
Tab 键
模拟键盘的操作首先需要引入 Keys 类:
1 from selenium.webdriver.common.keys import Keys
如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.keys import Keysbrowser = webdriver.Chrome() browser.maximize_window() browser.get("https://www.baidu.com" ) browser.find_element(By.ID, "kw" ).send_keys("selenium1" ) time.sleep(2 ) browser.find_element(By.ID, "kw" ).send_keys(Keys.BACK_SPACE) browser.find_element(By.ID, "kw" ).send_keys(Keys.SPACE) browser.find_element(By.ID, "kw" ).send_keys("教程" ) time.sleep(2 ) browser.find_element(By.ID, "su" ).send_keys(Keys.ENTER) time.sleep(2 ) html = browser.find_element(By.TAG_NAME, "html" ) html.send_keys(Keys.END) time.sleep(1 ) html.send_keys(Keys.HOME) time.sleep(1 ) browser.find_element(By.ID, "kw" ).send_keys(Keys.CONTROL, "a" ) time.sleep(1 ) browser.find_element(By.ID, "kw" ).send_keys(Keys.CONTROL, "x" ) time.sleep(1 ) browser.find_element(By.ID, "kw" ).send_keys(Keys.CONTROL, "v" ) time.sleep(1 ) browser.find_element(By.ID, "su" ).send_keys(Keys.ENTER) time.sleep(2 ) browser.quit()
2.4 鼠标事件用法 WebDriver 中,就爱那个鼠标的操作封装在 ActionChains 类中,常见方法如下:
方法名称
功能
context_click()
右击
double_click()
双击
move_to_element()
悬停
drag_and_drop()
拖动
perform()
执行所有 ActionChains 中存储的行为,可理解为对整个操作的提交动作
在模拟鼠标操作前,需要引入 ActionChains 的类:
1 from selenium.webdriver.common.action_chains import ActionChains
如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsbrowser = webdriver.Chrome() browser.maximize_window() browser.get("https://www.baidu.com" ) right_click_element = browser.find_element(By.LINK_TEXT, "新闻" ) ActionChains(browser).context_click(right_click_element).perform() time.sleep(2 ) ActionChains(browser).double_click(right_click_element).perform() time.sleep(2 ) above = browser.find_element(By.LINK_TEXT, "更多" ) ActionChains(browser).move_to_element(above).perform() browser.find_element(By.LINK_TEXT, "百科" ).click() time.sleep(2 ) browser.quit()
2.5 多框架切换定位用法 在 Web 应用里经常会出现框架或窗口的应用,有时候定位一个元素,定位器没有问题,但是却一直定位不了,这个时候就要检查这个元素是否在一个 frame 中,switch_to.frame() 是将当前定位的主题切换到了 frame 里。因为 frame 中其实相当于嵌入了另一个页面,webdriver 每次只能在一个页面识别。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import osimport timefrom selenium import webdriverfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome() driver.get(os.path.join(os.path.dirname(os.path.abspath(__file__)), "frame.html" )) driver.switch_to.frame("f1" ) driver.find_element(By.ID, "kw" ).send_keys("selenium" ) driver.find_element(By.ID, "su" ).click() driver.switch_to.default_content() driver.find_element(By.ID, "youku" ).click() time.sleep(2 ) driver.quit()
2.6 多窗口切换定位用法 在页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要主机切换到新打开的窗口上进行操作。WebDriver 提供了 switch_to.window() 方法,可以实现在不同的窗口之间切换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome() driver.implicitly_wait(10 ) driver.maximize_window() driver.get("http://www.baidu.com" ) baidu_handle = driver.current_window_handle print ("百度首页的句柄为:" , baidu_handle)time.sleep(2 ) driver.find_element(By.LINK_TEXT, "登录" ).click() time.sleep(2 ) driver.find_element(By.LINK_TEXT, "立即注册" ).click() time.sleep(2 ) all_handles = driver.window_handles print ("所有打开窗口的句柄为:" , all_handles)for handle in all_handles: if handle != baidu_handle: driver.switch_to.window(handle) driver.find_element(By.ID, "TANGRAM__PSP_4__userName" ).send_keys("jack" ) driver.find_element(By.ID, "TANGRAM__PSP_4__phone" ).send_keys("12345678901" ) driver.find_element(By.ID, "TANGRAM__PSP_4__password" ).send_keys("123456jack" ) time.sleep(2 ) for handle in all_handles: if handle == baidu_handle: driver.switch_to.window(handle) driver.find_element(By.ID, "TANGRAM__PSP_4__closeBtn" ).click() driver.find_element(By.ID, "kw" ).send_keys("selenium" ) driver.find_element(By.ID, "su" ).click() time.sleep(2 ) driver.quit()
2.7 其它一些高级用法 Selenium 还有一些其它常见的用法,比如调用 JS、截图保存图片等等。
2.7.1 截图 下面来看一个在百度搜索内容后,保存截图的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome() driver.maximize_window() driver.get("http://www.baidu.com" ) driver.find_element(By.ID, "kw" ).send_keys("selenium" ) driver.find_element(By.ID, "su" ).click() time.sleep(2 ) driver.save_screenshot("screenshot1.png" ) driver.get_screenshot_as_file("screenshot2.png" ) driver.quit()
2.7.2 调用 JS 但是有时候我们拿到一个截图后,想通过对截图中的一些内容进行标亮从而传达一些信息,那么就可以通过调用 JS 脚本来达到这个目的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Bydriver = webdriver.Chrome() driver.maximize_window() driver.get("http://www.baidu.com" ) driver.find_element(By.ID, "kw" ).send_keys("selenium" ) driver.find_element(By.ID, "su" ).click() time.sleep(2 ) js = "var q=document.documentElement.scrollTop=10000" driver.execute_script(js) time.sleep(2 ) js = "var q=document.documentElement.scrollTop=0" driver.execute_script(js) time.sleep(2 ) js = "var ele=document.getElementById(\"kw\");ele.style.border=\"2px solid red\"" driver.execute_script(js) time.sleep(2 ) driver.save_screenshot("screenshot1.png" ) driver.get_screenshot_as_file("screenshot2.png" ) driver.quit()