一、认识Selenium

  • Selenium架构

    Selenium自动化测试_chrome

  • Selenium核心组件

    1.selenium webdriver client

    2.selenium drivers

    3.selenium IDE

    4.selenium grid

    需要同一时间在多个浏览器和操作系统上进行测试时;

    要节省测试套件的执行时间时。

二、搭建测试环境

安装Chrome

查看Chrome的版本,需要安装适合版本的Chromedriver。

Selenium自动化测试_chrome_02

安装Chromedriver

ps:设置环境变量后如果没有生效,尝试重启电脑。

安装Selenium的IDE

ps:安装需要梯子。

IDE是入门的好工具。

Selenium自动化测试_元素定位_08

Selenium自动化测试_chrome_09

Selenium自动化测试_chrome_10

安装selenium库

Pychram安装selenium库,创建项目,做为client。

Selenium自动化测试_css_11

Selenium自动化测试_元素定位_12

三、IDE录制脚本

  • 录制脚本
    Selenium自动化测试_元素定位_13
    Selenium自动化测试_元素定位_14
    Selenium自动化测试_元素定位_15
    Selenium自动化测试_chrome_16
    Selenium自动化测试_css_17
    Selenium自动化测试_css_18
    Selenium自动化测试_chrome_19
    Selenium自动化测试_元素定位_20
    Selenium自动化测试_css_21
    Selenium自动化测试_chrome_22
  • 分析定位符
    先执行录制的脚本,在此基础上,可以分析定位符。
    Selenium自动化测试_元素定位_23
    Selenium自动化测试_chrome_24
    在页面上点击“社团”
    Selenium自动化测试_chrome_25

回到ide,发现有css定位表达式

Selenium自动化测试_chrome_26

四、编写用例

  • 导入依赖
    ​​​from selenium import webdriver​
  • 初始化driver
    ​​​driver = webdriver.Chrome()​​​​driver = webdriver.Firefox()​​​​driver = webdriver.Ie()​​​​driver = webdriver.Edge()​​​​driver = webdriver.Opera()​
  • 具体步骤
  • 断言assert
  • 退出

五、 WebDriver对象操作(API)

对WebDriver对象的操作可以抽象成你怎么去控制浏览器,主要方法有:

1.访问URL

​driver.get("https://www.baidu.com/")​

2.窗口大小调整

  • 设置宽800px 高600px
    ​​​driver.set_window_size(800,600) ​
  • 设置最大,最小
    ​​​driver.maximize_window()​​​​driver.minimize_window()​

3.刷新页面

​driver.refresh()​

4.前进后退

​driver.forward()​

​driver.back()​

5.关闭浏览器或窗口

  • 关闭浏览器
    ​​​driver.quit()​
  • 关闭窗口
    ​​​driver.close()​​ 有多个窗口的时候,只会关闭当前窗口。

6.返回当前的一些属性

  • 返回当前url
    ​​​driver.current_url​
  • 返回当前窗口句柄
    ​​​driver.current_window_handle​
  • 返回所有窗口句柄
    ​​​driver.window_handles​
# 在新浪登录页面点击注册,在注册页面邮箱地址输入框中输入邮箱地址,再次跳转到登录页面。
from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.maximize_window()
driver.get('http://mail.sina.com.cn/')
#获取当前窗口句柄
now_handle = driver.current_window_handle
time.sleep(1)
#点击注册链接
driver.find_element_by_link_text('注册').click()
time.sleep(1)
#获取所有窗口句柄
handles = driver.window_handles
#对所有窗口句柄循环处理
for handle in handles:
if handle != now_handle:
#窗口变化之后需要定位当前窗口
driver.switch_to.window(handle)
time.sleep(2)
driver.find_element_by_name('email').send_keys('bing')
time.sleep(2)
#关闭注册页面
driver.close()
driver.switch_to.window(now_handle)
time.sleep(2)
#在账号输入框输入邮箱
driver.find_element_by_id('freename').send_keys('bing')
time.sleep(2)

driver.quit()
  • 返回title
    ​​​driver.title​
  • 获取当前页面代码
    ​​​driver.page_source​​​ 7.查找元素,返回Element对象
    ​driver.find_element_by_css_selector()​​​​driver.find_element_by_name()​​​​driver.find_element_by_id()​​​​driver.find_element_by_tag_name()​​​​driver.find_element_by_class_name()​​​​driver.find_element_by_link_text()​​​​driver.find_element_by_partial_link_text()​​​​driver.find_element_by_xpath()​

8.切换窗口

​driver.switch_to_window(handle)​

9.切换frame

切换框架,直接输入iframe的name或id属性,或者传入定位的元素

​driver.switch_to_frame(frame_reference)​

10.截图保持为文件

​driver.get_screenshot_as_file(img_path_name)​

img_path_name为文件路径,只支持.png格式,文件名注意带上后缀,如“/Screenshots/foo.png”

11.执行js

  • 简单执行
    ​​​driver.execute_script(script, *args)​​​ script:要执行的JavaScript。
    *args:JavaScript的所有适用参数。
  • 异步执行
    ​​​driver.execute_async_script(script, *args)​

12.操作cookie

  • 获取cookie
    ​​​driver.get_cookies()​
  • 添加cookie
    ​​​driver.add_cookie(cookie_dict)​
  • 删除全部cookie
    ​​​driver.delete_all_cookies()​
  • 删除一个指定cookie
    ​​​driver.delete_cookie(name)​

六、元素定位

  • 元素定位本质上分为三大类

    Selenium自动化测试_元素定位_27

  • 使用Chrome验证元素定位表达式

    右键点击“检查”

    Selenium自动化测试_chrome_28

    查看HTML

    Selenium自动化测试_元素定位_29

进入Console验证定位表达式

输入​​$()​​可以验证css定位

输入​​$x()​​可以验证xpath定位

Selenium自动化测试_css_30

  • 元素定位常见错误

    1.element is not attached to the page document

    ​selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document​

    2.NoSuchElementException

  • 元素定位思路

    1.直接定位,有id、name,优先使用这两个定位,不行再尝试class、属性、标签定位。

    2.相对定位,就是根据层级关系定位。层级定位,先找到全局层级,再找下面的层级。

CSS定位

1.CSS常用属性定位

css可以通过元素的id、class、标签这三个常规属性直接定位元素。

# 百度搜索框HTML如下:
<input type="text" class="s_ipt" name="wd" id="kw" maxlength="100" autocomplete="off">
  • css用#号表示id属性
# chrome中验证定位表达式:$('#kw')
driver.find_element(By.CSS_SELECTOR,'#kw')
driver.find_element_by_css_selector('#kw')
  • css用.表示class属性
# chrome中验证定位表达式:$('.s_ipt')
driver.find_element(By.CSS_SELECTOR,'.s_ipt')
driver.find_element_by_css_selector('.s_ipt')
  • css直接用标签名称,无任何标示符
    ​​​$('input')​
  • Selenium自动化测试_css_31

2.CSS其它属性定位

css除了可以通过标签、class、id这三个常规属性定位外,也可以通过其它属性定位。

通过其他属性定位,得把属性放在方括号里。

Selenium自动化测试_chrome_32

# chrome中验证定位表达式:$('[type="text"]')
driver.find_element(By.CSS_SELECTOR,'[type="text"]')
driver.find_element_by_css_selector('[type="text"]')

3.通过标签与属性的组合来定位元素

  • 标签+class属性定位
# chrome中验证定位表达式:$('input.s_ipt')
driver.find_element(By.CSS_SELECTOR,'input.s_ipt')
driver.find_element_by_css_selector('input.s_ipt')
  • 标签+id属性定位
# chrome中验证定位表达式:$('input#kw')
driver.find_element(By.CSS_SELECTOR,'input#kw')
driver.find_element_by_css_selector('input#kw')
  • 标签+其他属性定位
# chrome中验证定位表达式:$('input[type="text"]')
driver.find_element(By.CSS_SELECTOR,'input[type="text"]')
driver.find_element_by_css_selector('input[type="text"]')

Selenium自动化测试_元素定位_33

看这里都是把标签放在前面,如果开始不是标签可以吗?把标签放在属性后面呢?

4.CSS层级关系定位

元素不能直接定位的时候,才考虑使用层级关系定位。

观察HTML的结构,一层一层找到包含要定位元素的父元素、父父元素,然后一层一层定位。

层级可以跳跃吗?

​div>p:选择父元素为 <div> 元素的所有 <p> 元素。​

​$('form>span>[type="text"]')​

Selenium自动化测试_css_34

5.CSS索引定位

​p:nth-child(2):选择属于其父元素的第二个子元素的每个 <p> 元素。​

input:nth-child(2) :选择属于 input 父元素的第2个子元素的每个 input 元 素

Selenium自动化测试_css_35

定位页面如下:

Selenium自动化测试_chrome_36

Selenium自动化测试_css_37

定位id为menu的父元素下标签为li的元素

Selenium自动化测试_css_38

Selenium自动化测试_css_39

Selenium自动化测试_css_40

Selenium自动化测试_元素定位_41

练习地址:​​https://www.w3school.com.cn//cssref/css_selectors.asp​

Selenium自动化测试_css_42

​$('.govsite-top>a:nth-child(2)')​

Selenium自动化测试_元素定位_43

6.CSS逻辑运算定位

css同样也可以实现逻辑运算,同时匹配两个属性,但跟xpath不一样,无需写and关键字。

​$('input[type="text"][autocomplete="off"]')​

Selenium自动化测试_元素定位_44

​$('[type="text"][autocomplete="off"]')​

Selenium自动化测试_css_45

​$('.s_ipt[type="text"][autocomplete="off"]')​

Selenium自动化测试_元素定位_46

Selenium自动化测试_chrome_47

XPATH定位

1.xpath概念相关

xpath是什么?XML路径语言。用来在HTML/XML文档中查找信息的语言。

xpath使用路径表达式来获取节点/节点集,和常规电脑文件路径类似。

绝对路径 / :/从根节点开始;

相对路径//://相对路径(推荐用),相对于整个源码查找。

Selenium自动化测试_元素定位_48

Selenium自动化测试_css_49

Selenium自动化测试_css_50

Selenium自动化测试_chrome_51

2.xpath定位方式(路径表达式+索引+属性)

  • 利用标签内的属性进行定位

    (1)通过id属性(标签+id)

    ​$x('//input[@id="Popover1-toggle"]')​

    Selenium自动化测试_chrome_52

    Selenium自动化测试_chrome_53

    (2)通过name属性定位

    小结:xpath = "//标签名[@属性='属性值']"

    属性判断条件:最常见为id,name,class等等,属性的类别没有特殊限制,只要能够唯一标识一个元素即可。

    当某个属性不足以唯一区别某一个元素时,也可以采取多个条件组合的方式,如下:

    ​xpath= "//input[@type='XX' and @name='XX']"​

    ​$x('//input[@class="Input" and @type="text"]')​

    Selenium自动化测试_css_54

  • 利用text()方法定位

    ​$x('//div[text()="草稿箱"]')​

    Selenium自动化测试_chrome_55

    Selenium自动化测试_元素定位_56

  • 利用contains()方法定位,也叫模糊定位

    ​xpath = "//标签名[contains(@属性, '属性值')]"​

    Selenium自动化测试_chrome_57

    Selenium自动化测试_css_58

  • 利用相对空间定位

    如果一个元素无法通过自身属性直接定位到,则可以先定位它的父(或父的父,它爷爷)元素,然后再找下一级即可。

    例如要定位如下元素:

    Selenium自动化测试_css_59

    首先定位到“阿里巴巴”

    Selenium自动化测试_chrome_60

    看到“阿里巴巴”要往上4层才与定位的元素在同一父类元素下

    Selenium自动化测试_css_61

    Selenium自动化测试_css_62

    Selenium自动化测试_chrome_63

    ​$x('//table[@class="search__stock__bd"]//span[text()="阿里巴巴"]/../../../..//i[@class="iconfont"]')​

    Selenium自动化测试_chrome_64

  • 逻辑定位

    ​//*[@text="交易" and contains(@resuorce-id,'current_price')]​

其他定位

通过id属性定位

driver.find_element_by_id(‘loginForm’) 
#定位<form id="loginForm">

#简单写法,导入By模块
from selenium.webdriver.common.by import By
driver.find_element(By.ID,"loginForm")

通过name属性定位

driver.find_element_by_name(‘username’) 
#定位<input name="username" type="text" />
driver.find_element(By.NAME,"username")

通过class名定位

driver.find_element_by_class_name(‘content’) 
#定位<p class="content">Site content goes here.</p>
driver.find_element(By.CLASS_NAME,"content")

通过TagName标签名定位

driver.find_element_by_tag_name(‘input’) 
#定位<input name="username" type="text" />,如果匹配了多个,默认只选第一个
driver.find_element(By.TAG_NAME,"input")

通过link text定位,就是通过a标签的text内容定位

driver.find_element_by_link_text(‘Continue’)  #全匹配
driver.find_element_by_partial_link_text(‘Con’) #部分匹配
#定位<a href="continue.html">Continue</a>
driver.find_element(By.LINK_TEXT,‘Continue’)
driver.find_element(By.PARTIAL_LINK_TEXT,‘Con’)

元素Element事件

元素定位是返回元素,需要对元素进行操作才可以实现自动化测试。

Element对象有一系列的方法,可以操作定位的元素。

1.Element.click() 点击元素

​driver.find_elements_by_link_text(‘Continue’).click()​

2.输入文本

# 有些输入框中原有的文本不会被自动清除掉,需要使用clear()方法清除 driver.find_element_by_name(‘username’).clear() 
# 输入内容 driver.find_element_by_name(‘username’).send_keys("username")

3.获取参数

# 获取对应特性值 
Element.get_attribute(name)
# 获取对应属性值
Element.get_property(name)
# property是DOM中的属性,是JavaScript里的对象;attribute是HTML标签上的特性,它的值只能够是字符串。一般用 attr就行
# 获取当前元素的内容
Element.text
# 获取当前元素标签名
Element.tag_name
# 获取当前元素尺寸
Element.size
# 获取当前元素坐标
Element.location

4.判断方法

#判断当前元素是否可见 
Element.is_displayed()
#判断当前元素是否被启用
Element.is_enabled()
#判断当前元素是否被选中
Element.is_selected()

等待

现在的网页,基本都是使用ajax异步的加载各种资源的,所以可能我们需要定位的元素不会第一时间就加载出 来,这时候是无法定位的,也就会抛出异常。而解决这个问题的方法,就是等待。

定时等待

不推荐使用定时等待,在正式脚本中很少使用,可在调试脚本的时候使用。

import time 
time.sleep(10)

隐式等待

一种全局的设置,设置一个最大时长,如果定位的元素没有出现就会循环查找元素直到超时或者元素出现,相比于定时等待,这个更加弹性,元素出现了就不会等待了。

from time import sleep
from selenium import webdriver # driver需要的依赖
from selenium.webdriver.common.by import By # 元素定位

class TestBiying:
# 做初始化的操作
def setup_method(self):
# 实例化webdriver对象
self.driver = webdriver.Chrome()
# 打开url
self.driver.get('https://baidu.com/')
# 隐式等待
self.driver.implicitly_wait(5)

显式等待

显式等待就是设定一个条件,同时设置一个时间,在这个时间范围内,如果网页出现符合的条件的元素,就不等待继续执行,如果没有则循环查找元素直到超时报错。

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.Firefox()
driver.get("http://somedomain/url_that_delay_loading")
try:
element=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"myDynamicElement")))
finally:
driver.quit()

这段代码主要讲的是:

  1. 实例化WebDriverWait类,传入driver与最大等待时长10秒 ,默认poll_frequency(扫描频率)为0.5秒。
  2. until()是WebDriverWait类的一个方法,参数是一个等待条件(expected_conditions),如果满足等待条件,则WebDriverWait类停止等待,并且返回expected_conditions的值,否则当等待时间到将抛出 TimeoutException异常。
  3. WebDriverWait类还有个方法until_not(),如果不满足等待条件,就停止等待。
  4. 等待条件(expected_conditions)如果成功则返回element对象,或有些是返回布尔值,或者其它不为 null的值。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

class TestMail():
def setup(self):
self.driver = webdriver.Chrome()

def test_window(self):
self.driver.get('https://testerhome.com/topics/21805')
self.driver.implicitly_wait(5)
self.driver.find_element_by_link_text('第六届中国互联网测试开发大会').click()
# 打印窗口,可以观察到出现了多个窗口
print(self.driver.window_handles)
# 切换窗口
self.driver.switch_to.window(self.driver.window_handles[1])
ele = (By.LINK_TEXT,'演讲申请')
WebDriverWait(self.driver,10).until(EC.element_to_be_clickable(ele))
self.driver.find_element(*ele ).click()

等待条件(expected_conditions)内置的方法主要有:

  • title_is : #验证 driver 的 title 是否与传入的 title 一致,返回布尔值。
  • title_contains : #验证 driver 的 title 中是否包含传入的 title,返回布尔值。
  • presence_of_element_located :# 验证页面中是否存在传入的元素,传入元素的格式是 locator 元组,如 (By.ID, "id1"),返回element对象。
  • visibility_of_element_located : #验证页面中传入的元素( locator 元组格式 )是否可见,这里的可见不仅仅是 display 属性非 None ,还意味着宽高均大于0,返回element对象或false。
  • visibility_of : #验证页面中传入的元素( WebElement 格式 )是否可见。返回element对象或false。
  • presence_of_all_elements_located : #验证页面中是否存在传入的所有元素,传入元素的格式是 locator 元组构成 的 list,如 [(By.ID, "id1"), (By.NAME, "name1"),返回element或false。
  • text_to_be_present_in_element : #验证在指定页面元素的text中是否包含传入的文本,返回布尔值。
  • text_to_be_present_in_element_value : #验证在指定页面元素的value中是否包含传入的文本,返回布尔值。
  • frame_to_be_available_and_switch_to_it : #验证frame是否可切入,传入 locator 元组 或 WebElement,返回布尔值。
  • invisibility_of_element_located : #验证页面中传入的元素( locator 元组格式 )是否可见,返回布尔值。
  • element_to_be_clickable : #验证页面中传入的元素( WebElement 格式 )是否点击,返回element。
  • staleness_of : #判断传入元素(WebElement 格式)是否仍在DOM中,返回布尔值。
  • element_to_be_selected : #判断传入元素(WebElement 格式)是否被选中,返回布尔值。
  • element_located_to_be_selected :# 判断传入元素(locator 元组格式)是否被选中,返回布尔值。
  • element_selection_state_to_be :# 验证传入的可选择元素(WebElement 格式)是否处于某传入状态,返回布尔值。
  • element_located_selection_state_to_be : #验证传入的可选择元素(WebElement 格式)是否处于某传入状态,返回布尔值。
  • alert_is_present : #验证是否有 alert 出现,返回alert对象。

一般使用:检查元素是否存在、检查元素是否可见、检查元素是否可点击。

1.presence_of_element_located :# 验证页面中是否存在传入的元素,传入元素的格式是 locator 元组,如 (By.ID, "id1"),返回element对象 。2.visibility_of_element_located : #验证页面中传入的元素( locator 元组格式 )是否可见,这里的可见不仅仅是 display 属性非 None ,还意味着宽高均大于0,返回element对象或false。

3.visibility_of : #验证页面中传入的元素( WebElement 格式 )是否可见。返回element对象或false。

4.invisibility_of_element_located : #验证页面中传入的元素( locator 元组格式 )是否可见,返回布尔值。

5.element_to_be_clickable : #验证页面中传入的元素( WebElement 格式 )是否点击,返回element。

ps:具体的区别不是很明白。

ps:传入格式?

元素状态大概这样区分

title出现

dom出现 presence

css出现 visibility

js执行 clickable

应用场景

隐式等待尽量默认都加上,时间限定在3-6s,不要太长,这是为了所有的findElemen方法都有一个很好的缓冲。

显式等待用来处理隐式等待无法解决的一些问题,比如文件上传。

定时等待一般不推荐,除非特殊情况。

Action Chains类模拟鼠标行为

ActionChains简介

Actionchains是selenium里面专门处理鼠标相关的操作如:鼠标移动,鼠标按钮操作,按键和上下文菜单(鼠标右键)交互。

这对于做更复杂的动作非常有用,比如悬停和拖放。

Actionchains也可以和快捷键结合起来使用,如ctrl,shif,alt结合鼠标一起使用。

当你使用actionchains对象方法,行为事件是存储在actionchains对象队列。当你使用perform(),事件按顺序执行。

方法一:可以写一长串

menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")
ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

方法二:可以分几步写

menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")
actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(hidden_submenu)
actions.perform()

使用Actionchains首先需要实例化,然后调用其中的方法,完成相应的操作。

import time
from selenium import webdriver
from selenium.webdriver import ActionChains

browser =webdriver.Firefox()
browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
# 切换frame,id = 'iframeResult'
browser.switch_to.frame('iframeResult')
# 被拖拽的对象
source = browser.find_element_by_css_selector('#draggable')
# 目标对象
target = browser.find_element_by_css_selector('#droppable')
actions = ActionChains(browser)
actions.drag_and_drop(source, target)
actions.perform()
time.sleep(3)
browser.close()

常见的鼠标操作

click(on_element=None)

鼠标单击

click_and_hold(on_element=None)

鼠标单击并且按住不放

context_click(on_element=None)

右击

double_click(on_element=None)

双击

drag_and_drop(source, target)

拖拽

drag_and_drop_by_offset(source, xoffset, yoffset)

将目标拖动到指定的位置

key_down(value, element=None)

按住某个键,使用这个方法可以方便的实现某些快捷键,比如下面按下Ctrl+c键

​ActionsChains(browser).key_down(Keys.CONTROL).send_keys('c').perform()​

key_up(value, element=None)

松开某个键,可以配合上面的方法实现按下Ctrl+c并且释放。

​ActionsChains(browser).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()​

move_by_offset(xoffset, yoffset)

指定鼠标移动到某一个位置,需要给出两个坐标位置

move_to_element(to_element)

将鼠标移动到指定的某个元素的位置

move_to_element_with_offset(to_element, xoffset, yoffset)

移动鼠标到某个元素位置的偏移位置

perform()

将之前的一系列的ActionChains执行

release(on_element=None)

释放按下的鼠标

send_keys(*keys_to_send)

向某个元素位置输入值

send_keys_to_element(element, *keys_to_send)

向指定的元素输入数据

Frames与多窗⼝处理

官方把selenium.webdriver包中的switch方法全部封装成了witch_to包。

switch_to包的方法详解

Selenium自动化测试_chrome_65

  • driver.switch_to.parent_frame()
    是switch_to中独有的方法,可以切换到上一层的frame,对于层层嵌套的frame很有用。
    switch_to.frame
    Selenium自动化测试_元素定位_66
    switch_to.window
    例如,访问https://testerhome.com/topics/21805,点击“第六届中国互联网测试开发大会”,会弹出一个新的窗口,然后在新的窗口再点击“演讲申请”。
    Selenium自动化测试_元素定位_67
    Selenium自动化测试_元素定位_68
    Selenium自动化测试_chrome_69
def test_window(self):
self.driver.get('https://testerhome.com/topics/21805')
self.driver.implicitly_wait(5)
self.driver.find_element_by_link_text('第六届中国互联网测试开发大会').click()
print(self.driver.window_handles)
self.driver.switch_to.window(self.driver.window_handles[1])
ele = (By.LINK_TEXT,'演讲申请')
WebDriverWait(self.driver,10).until(EC.element_to_be_clickable(ele))
self.driver.find_element(*ele ).click()

Selenium自动化测试_css_70

复用浏览器

通过设置Chrome options参数来复用浏览器。

Chrome Options是一个配置chrome启动时属性的类,通过这个参数我们可以为Chrome添加参数,以实现一些功能,如设置默认编码、设置代理、设置无头模式等。

首先打开一个调试的浏览器,需要在环境变量中PATH里将chrome的路径添加进去。

​chrome --remote-debugging-port=9222​

Selenium自动化测试_chrome_71

from time import sleep
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

class TestHome():
def setup(self):
chromeOptions = Options()
#9222是端口号,只要是不被占用的端口号都可以
chromeOptions.add_experimental_option('debuggerAddress', '127.0.0.1:9222')
# 使用webdriver,需要from selenium import webdriver
self.driver = webdriver.Chrome(options=chromeOptions)
# 隐式等待,是全局生效的
self.driver.implicitly_wait(3)

Selenium自动化测试_chrome_72

实例化webdriver下的ChromeOptions

设置浏览器的调试地址

复用浏览器

这两种形式的区别?

cookie处理

如何获取cookie?

执行JavaScript

在打开一个网页的时候,可以执行JS获取一些数据,特别是性能数据。

一般只会用到execute_script,源代码如下:

def execute_script(self, script, *args):
"""
Synchronously Executes JavaScript in the current window/frame.

:Args:
- script: The JavaScript to execute.
- \*args: Any applicable arguments for your JavaScript.

:Usage:
driver.execute_script('return document.title;')
"""
converted_args = list(args)
command = None
if self.w3c:
command = Command.W3C_EXECUTE_SCRIPT
else:
command = Command.EXECUTE_SCRIPT

return self.execute(command, {
'script': script,
'args': converted_args})['value']

在Chrome中也可以执行JS,可以先在Chrome中验证,再copy到脚本中。

Selenium自动化测试_css_73

如打开网站,获取性能数据。

Selenium自动化测试_css_74

def test_JS(self):
for code in [
# 获取网页标题
'return document.title',
# 获取性能数据
'return JSON.stringify(performance.timing)',
]:
result = self.driver.execute_script(code)
print(result)

结果如下:

Selenium自动化测试_chrome_75

多浏览器测试

通过参数传入浏览器,使用命令行执行脚本。

无UI执行测试用例

1.phantomJS

这个项目已经没有维护了。

2.chrome的headless模式

通过设置Chrome options参数

options.add_argument('--headless')

文件上传和下载

PO

PO是什么

PageObject,顾名思义,页面对象。

PO适用于UI自动化测试。

Selenium自动化测试_css_76

2013年马丁·福勒提出PageObject思想

​https://martinfowler.com/bliki/PageObject.html​

selenium引入PO

​https://github.com/SeleniumHQ/selenium/wiki/PageObjects​

为什么需要使用PO

在做UI自动化测试的时候,让人很头疼的一个问题是页面元素经常变化,这时候测试用例也得跟着改变。为了让测试用例保持稳定,可以把元素定位、元素操作与测试用例进行分离。把元素定位、元素操作具体操作细节封装成一个方法,测试用例直接调用这个方法,编写测试用例的时候就无需关注操作细节。在业务流程没有变化的情况下,页面元素发生了变化,那只需要对封装方法进行修改,测试用例可以保持不变。

方便分工与合作

方便从业务角度理解测试用例

Selenium自动化测试_chrome_77

PO的原则

  • ⽅法意义
    ❖ ⽤公共⽅法代表UI所提供的功能
    ❖ ⽅法应该返回其他的PageObject或者返回⽤于断⾔的数据
    ❖ 同样的⾏为不同的结果可以建模为不同的⽅法
    ❖ 不要在⽅法内加断⾔
  • 字段意义
    ❖ 不要暴露页⾯内部的元素给外部
    ❖ 不需要建模UI内的所有元素

如何使用PO

首页

Selenium自动化测试_chrome_78

注册页

Selenium自动化测试_元素定位_79

登录页

Selenium自动化测试_元素定位_80

BasePage声明driver的类型为WebDriver,不然继承BasePage后不能自动带出driver的方法。

Selenium自动化测试_css_81

Selenium自动化测试_元素定位_82

Selenium自动化测试_css_83

Selenium自动化测试_元素定位_84

Selenium自动化测试_chrome_85

参数化

Selenium自动化测试遇到的问题

  • [Pycharm] AttributeError: module 'selenium.webdriver' has no attribute 'Firefox'

    ​https://www.jianshu.com/p/2409c638665a​

    重新创建一个虚拟环境,创建一个项目

  • element is not attached to the page document
  • NoSuchElementException

    Selenium自动化测试_css_86

常见控件

单选框、复选框、下拉框、表格