Web自动化测试

1.selenium使用方法

1.1操作浏览器

1、启动浏览器(实例化浏览器)

启动Chrome浏览器(驱动已放入path环境变量下)

driver = webdriver.Chrome()

指定驱动路径驱动Chrome 浏览器

# .driverchromedriver.exe 为驱动存放位置,可以是相对路径或者绝对路径
driver = webdriver.Chrome(executable_path=r'.driverchromedriver.exe')

启动Firefox浏览器

driver=webdriver.Firefox() 
 # 指定驱动路径 启动 
driver=webdriver.Firefox(executable_path="..drivergeckodriver.exe")

启动IE浏览器

driver=webdriver.Ie()  
# 指定驱动路径 启动
driver=webdriver.Ie(executable_path=r".driverIEDriverServer.exe") 

2、最大化浏览器

driver.maximize_window()

driver为实例化浏览器对象(下同)

3、设置浏览器大小

driver.set_window_size(480, 800)  # width 400, height 800

4、打开网页

driver.get('https://www.zhihu.com/') 

5、使用另外窗口打开网页

# 新开一个窗口,通过执行js来新开一个窗口
js='window.open("https://mail.163.com");'
driver.execute_script(js)

6、控制浏览器前进、后退

driver.get('https://www.zhihu.com/') 
driver.get('https://mail.163.com')  # 在同一窗口重新打开一个网页
driver.back()  # 后退 到知乎
driver.forward()  # 前进 换回到163

7、获取网页标题

title =driver.title  # 获取网页的title

获取到的title为页面源码head 标签中title中的文本信息

8、获取网页的URL

url=driver.current_url  # 获取网页的URL

获取的url为当前浏览器地址栏中的url

9、刷新页面

driver.refresh()

10、获取浏览器窗口大小

size=driver.get_window_size()

返回为字典型 如:{'width': 1050, 'height': 840}

11、关闭浏览器

driver.close()

关闭的是当前浏览器窗口的页签,存在多个窗口时关闭当前的活动窗口

12、退出浏览器

driver.quit()

关闭整个浏览器,包括webdriver的进程也会退出

1.2获取元素对象

八种属性定位页面元素:

序号

类型

示例

1

id 定位

find_element(By.ID,"id值")

2

name 定位

find_element(By.NAME,"name值")

3

tag 定位

find_element(By.TAG_NAME,"id值")

4

class 定位

find_element(By.CLASS_NAME,"class值")

5

link_text 定位

find_element(By.LINK_TEXT,"文本值")

6

partial_link 定位

find_element(By.PARTIAL_LINK_TEXT,"文本模糊值")

7

XPath 定位

find_element(By.XPATH,"唯一路径标识")

8

CSS_selector 定位

find_element(By.CSS_SELECTOR,"各种组合") ,实际使用最多

webdriver中元素定位元素的简便方法:

driver.find_element_by_id('元素id属性')  # ------ 最常用,简单
driver.find_element_by_name('元素name属性')  # ------ 最常用,简单
driver.find_element_by_class_name('元素class属性')  # ------ 易重复,看情况使用
driver.find_element_by_tag_name('元素标签名')  # ------ 最不靠谱
driver.find_element_by_link_text('链接文本')  # ------ 精确匹配链接 ( 标签中的文字)
driver.find_element_by_partial_link_text(‘部分链接文本’)  # ------ 模糊匹配链接
driver.find_element_by_xpath()  # ------ 最灵活,万能的灵药
driver.find_element_by_css_selector()  # ------ 没xpath灵活

1、id元素定位

id="query" class="sec-input" name="query" maxlength="100" autocomplete="off" type="text">

driver.find_element_by_id('query')
driver.find_element(By.ID,'query')

2、name元素定位

name="query" maxlength="100" autocomplete="off" type="text">

driver.find_element_by_name('query')
driver.find_elemnet(By.NAME,'query')

3、class name元素定位

class="sec-input" name="query" maxlength="100" autocomplete="off" type="text">

driver.find_element_by_class_name('sec-input')
driver.find_element(By.CLASS_NAME,'sec-input')

4、 tag name元素定位(最不靠谱)

<input id="query" class="sec-input" name="query" maxlength="100" autocomplete="off" type="text">

driver.find_element_by_tag_name('input')
driver,find_element(By.TAG_NAME,'input')

5、 link_text元素定位

页面底部搜狗输入法连接

搜狗输入法

driver.find_element_by_link_text('搜狗输入法')
driver.find_element(By.LINK_TEXT,'搜狗输入法')

注意:连接文本是标签对之间的文本

6、 partial link text元素定位

<搜狗输入法

driver.find_element_by_partial_link_text('输入法')
driver.find_element(By.PARTIAL_LINK_Text,'输入法')

7、 XPath元素定位(强大)

xpath 可以根据元素的父节点或者哥哥弟弟节点定位到元素。

driver.find_element_by_xpath(‘//form[@id="sf"]//input[@type="text"]’) # 上级节点定位下级子节点
driver.find_element_by_xpath(‘//span[@class="enter-input"]/preceding-sibling::span/input’)  # 通过节点的弟弟节点定位

注意:使用xpath最好不要使用工具获取,手写的可靠性更高

8、css元素定位

css定位元素比xpath块,id,name,class,tag name都是转换为css后定位元素。具体请看find_element方法的代码。

driver.find_elements_by_css_selector(".sec-input")  #  .表示class
driver.find_elements_by_css_selector("#query")   #  #表示id

1.3操作元素对象

一、元素的常用操作

element.click() # 单击元素;除隐藏元素外,所有元素都可单击

element.submit() # 提交表单;可通过form表单元素提交表单

element.clear() # 清除元素的内容;如果可以的话

element.send_keys(‘需要输入的内容’) # 模拟按键输入;只针对支持输入的元素

注意:send_keys() 输入的内容必须为字符串

搜狗查询实例:

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.maximize_window()  # 最大化
driver.get(r'https://www.sogou.com/')  # 打开网页
driver.find_element_by_id('query').send_keys('selenium')  # 搜索框输入selenium
time.sleep(2)  # 等待3秒
driver.find_element_by_id('query').clear()  # 清除搜索框内容
time.sleep(2)
driver.find_element_by_id('query').send_keys('selenium')  # 重新输入内容
driver.find_element_by_id('sf').submit()  # 提交搜索框的表单
# driver.find_element_by_id('stb').submit()  #  提交按钮也可提交表单,单击按钮也可以
time.sleep(2)
driver.quit()  # 关闭浏览器

注意:submit() 提交表单,可以是提交按钮,也可以是表单元素,也可以是输入框元素

二、元素的常用方法

element.location 返回元素的坐标字典(相对于网页左上角0,0开始)

element.text 获取元素的文本,页面上看得到的文本

element.get_attribute('属性名称') 获得元素的属性 强调“有”

element.get_property('属性名称') 获得元素的固有属性值 强调“专”

element.is_displayed() 返回元素的结果是否可见,有些元素肉眼可见,但是他是隐藏的

示例:

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.maximize_window()  # 最大化
driver.get(r'https://www.sogou.com/')  # 打开网页
driver.find_element_by_id('query').send_keys('selenium')  # 搜索框输入selenium
element=driver.find_element_by_id('query')
print('搜索框的内容为:',element.get_attribute('value'))
print('搜索框的class属性:',element.get_attribute('class'))
print('搜索框的type属性:',element.get_attribute('type'))
print('搜索框的坐标位置:',element.location)
print('搜索框是否可操作:',element.is_displayed())
time.sleep(2)
text = driver.find_element_by_class_name('erwm-box').text  # 获取二位码的文本
print('底部二维码的文本为:',text)
time.sleep(2)
driver.quit()  # 关闭浏览器

1、element.location 获取元素的坐标位置

对于已加载到浏览器的底部元素,操作元素时现在chrome无法自动拖动滚动条,需要获取元素位置后,采用js拖动滚动条到相应位置采用操作元素。

2、element.text 获取元素的文本


       
       
           

搜狗搜索APP

搜你所想

如上,我们定位class="erwm-box"元素,获取到的文本是 [搜狗搜索APP 搜你所想] ,也就是界面上能看到的文字内容。输入框除外(输入框的值是存储在value属性中),只要是界面上的文本内容都可以获取。

多用于校验点。

3、element.get_attribute('属性名称') 获取对应的属性值,强调“有”

type="text" class="sec-input" name="query" id="query" maxlength="100" autocomplete="off">

如上搜索输入框的属性有type、class、name、id、maxlength、autocomplete;我都可以通过get_attribute()获取到他的值,因为他’有’。

value是特殊的属性,输入框,单项按钮,多选按钮多具有改属性。

4、element.get_property('属性名称') 获得元素的固有属性值,强调“专”

它与get_attribute() 差别,get_property()是获取元素的固有属性。

我们所有的元素都有特定固有属性,如id、type、value等。

当使用get_attribute()无法获取到属性的值时,可使用get_property()。

5、element.is_displayed() 判定改元素是否可见

当我们定位到了元素,但是无法操作时,可以看看他是否可见,不可见不一定就是在界面上消失了。

6、其他方法

element.size 元素的大小

element.is_enabled() 元素是否可用

element.is_selected() 元素是否被选中,用于检测复选框或单项按钮是否被勾选

1.4设置等待时间

一、time.sleep(seconds) 固定等待

import time
time.sleep(3) #等待3秒

time.sleep(seconds) seconds参数为整数,单位(秒)。

它是Python的time提供的休眠方法。

常用于短时间的等待,为了自动测试用例的执行效率固定等待的时间需要控制在3秒内。在用例中尽量少用固定等待。

二、智能隐性的等待implicitly_wait(回应超时等待)

driver.implicitly_wait(time_to_wait)

回应超时等待,隐性的,设置后对应的是全局,如查找元素。

driver.implicitly_wait(10)  # 设置全局隐性等待时间,单位秒

每次driver执行 找不到元素都会等待设置的时间,它的值设置的过长对用例执行效率有很大的影响,必须在执行完成之后还原回来。driver.implicitly_wait() 要慎之又慎的使用。

driver对它的默认值为0,driver.implicitly_wait(0)能还原隐性等待的设置时间。

三、智能显性等待WebDriverWait

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

参数说明:

driver 为webdriver驱动 timeout 最长超时时间,单位(秒) poll_frequency 循环查找元素每次间隔的时间,默认0.5秒 ignored_exceptions 超时后需要输出的异常信息

WebDriverWait()下面有两个方法可用until()和until_not()

*WebDriverWait(driver, timeout).until(method, message='')*

method 函数或者实例call()方法返回True时停止,否则超时后抛出异常。

参数说明:

method 在等待时间内调用的方法或者函数,该方法或函数需要有返回值,并且只接收一个参数driver。 message 超时时抛出TimeoutException,将message传入异常显示出来

*WebDriverWait(driver, timeout).until_not(method, message='')*

于上面的until() 相反,until_not 中的method函数或者实例call()方法返回False结束,否则抛出异常。

until方法使用的method 的函数或者类call()方法详解:

函数我们一般采用匿名函数lambda 。

lambda driver:driver.find_element(<定位元素>) # 当定位的元素时为True,无元素时为False。如示例1、2:

WebDriverWait示例1:

WebDriverWait(driver,5).until(lambda driver:driver.find_element_by_id('query'))

5秒内等待元素(id='query')出现,lambda driver:driver.find_element_by_id('query') 为一个匿名函数,只有一个driver参数,返回的是查找的元素对象。

WebDriverWait示例2:

WebDriverWait(driver, 5).until_not(lambda driver:driver.find_element_by_name('query'))

5秒内等待元素消失,同示例1 until_not 要求无元素返回即元素不存在于该页面。

定义类中的call()方法。

class wait_element(object):
   def __init__(self, locator):
       self.locator = locator

   def __call__(self, driver):
       return driver.find_element(self.locator)

WebDriverWait(driver, 5).until(wait_element((By.ID, 'query')))  # 等待元素出现
WebDriverWait(driver, 5).until_not(wait_element((By.ID, 'query')))  # 等待元素消失

wait_element类中init()方法接收需要定位的元素,call()方法中只能有唯一变量driver,并且返回元素对象。

这样做是是不是很麻烦,其实selenium提供的一个库进行操作,expected_conditions库。引入位置

from selenium.webdriver.support import expected_conditions as ec,它囊括了我们需要使用等待的所有情况。

四、expected_conditions 类库

from selenium.webdriver.support import expected_conditions as ec  # 引入包

下面示例都是以搜狗搜索首页为例。

方法中参数说明 locator=(By.ID, 'id') 表示使用By方法定位元素的元组,element表示获取的webElement元素对象。

ec.title_is(‘title’) 判断页面标题等于title

*ec.title_contains(‘title’)* 判断页面标题包含title

WebDriverWait(driver, 10).until(ec.title_is('搜狗搜索引擎 - 上网从搜狗开始'))  # 等待title 于参数相等
WebDriverWait(driver, 10).until(ec.title_contains('搜狗搜索引擎'))  # 等待title 包含 参数的内容

*ec.presence_of_element_located(locator)* 等待locator元素是否出现

ec.presence_of_all_elements_located(locator) 等待所有locator元素是否出现

WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.ID, 'query')))
WebDriverWait(driver, 10).until(ec.presence_of_all_elements_located((By.ID, 'query')))

*ec.visibility_of_element_located(locator)* 等待locator元素可见

ec.invisibility_of_element_located(locator) 等待locator元素隐藏

*ec.visibility_of(element)* 等待element元素可见

WebDriverWait(driver, 10).until(ec.visibility_of_element_located((By.ID, ''stb'')))  # 等待元素可见
WebDriverWait(driver, 10).until(ec.invisibility_of_element_located((By.ID, ''stb'')))  # 等待元素隐藏
WebDriverWait(driver, 10).until(ec.visibility_of(driver.find_element_by_link_text('高级搜索')))  # 等待元素可见

*ec.text_to_be_present_in_element(locator,text)* 等待locator的元素中包含text文本

ec.text_to_be_present_in_element_value(locator,value) 等待locator元素的value属性为value

WebDriverWait(driver, 10).until(ec.text_to_be_present_in_element((By.ID, 'erwx'), '搜索APP'))  # 等待元素中包含搜索APP文本
WebDriverWait(driver, 10).until(ec.text_to_be_present_in_element_value((By.ID, 'query'),'selenium'))  # 等待元素的值为 selenium,一般用于输入框

ec.frame_to_be_available_and_switch_to_it(locator) 等待frame可切入

WebDriverWait(driver, 10).until(ec.frame_to_be_available_and_switch_to_it((By.ID, 'frame')))
WebDriverWait(driver, 10).until(ec.frame_to_be_available_and_switch_to_it('frameid'))
ec.alert_is_present() 等待alert弹出窗口出现
WebDriverWait(driver, 10).until(ec.alert_is_present())

ec.element_to_be_clickable(locator) 等待locator元素可点击

WebDriverWait(driver, 10).until(ec.element_to_be_clickable((By.ID, 'kw')))

等待元素被选中,一般用于复选框,单选框

ec.element_to_be_selected(element) 等待element元素是被选中

ec.element_located_to_be_selected(locator) 等待locator元素是被选中ec.element_selection_state_to_be(element, is_selected) 等待element元素的值被选中为is_selected(布尔值)

ec.element_located_selection_state_to_be(locator,is_selected) 等待locator元素的值是否被选中is_selected(布尔值)

from selenium import webdriver
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec  # 引入包
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.maximize_window() 
driver.get(r'https://www.baidu.com/') 
driver.find_element_by_link_text('设置').click()
WebDriverWait(driver, 3).until(ec.element_to_be_clickable((By.LINK_TEXT, '搜索设置')))  # 等待搜索可点击,不可缺少
driver.find_element_by_link_text('搜索设置').click()
element = driver.find_element_by_id('s1_1')
WebDriverWait(driver, 2).until(ec.element_to_be_selected(element))  # element被选中
WebDriverWait(driver, 10).until(ec.element_located_to_be_selected((By.ID, 'SL_0'))) # id=’SL_0’ 被选中
WebDriverWait(driver, 10).until(ec.element_selection_state_to_be(element,True )) # element 被选中
WebDriverWait(driver, 10).until(ec.element_located_selection_state_to_be((By.ID, 'SL_1'), False)) #  id=’SL_1’不被选中
time.sleep(3)
driver.quit()

五、什么时候使用等待

固定等待sleep与隐性等待implicitly_wait尽量少用,它会对测试用例的执行效率有影响。

显性的等待WebDriverWait可以灵活运用,什么时候需要用到?

1、页面加载的时候,确认页面元素是否加载成功可以使用WebDriverWait

2、页面跳转的时候,等待跳转页面的元素出现,需要选一个在跳转前的页面不存在的元素

3、下拉菜单的时候,如上百度搜索设置的下拉菜单,需要加上个时间断的等待元素可点击

4、页面刷新的时候

总之,页面存在改变的时候;页面上本来没的元素,然后再出现的元素

1.5键盘鼠标事件ActionChains

一、鼠标点击操作

click(element=None) 左击 context_click(element=None) 右击 double_click(element=None) 双击 move_to_element(element) 移动鼠标到元素中间(悬停) drag_and_drop(source,target) source上按下左键拖动到target元素上 click_and_hold(element=None) 在元素上按下鼠标左键 release() 释放鼠标 perform() 执行ActionChains中存储的动作

element有None默认值的表示不传入参数该动作在原地执行。

鼠标事件具体使用示例如下:

示例1:鼠标左键点击

action=ActionChains(driver)
action.click() # 在鼠标当前位置单击
action.perform() # 执行action存储的动作

# 鼠标在 '新闻' 元素位置单击
action.click(driver.find_element_by_link_text('新闻')).perform()  

注意:action.click() 动作并未执行,它只是存储在action实例中,需要通过action.perform()方法执行存储动作;鼠标键盘事件动作动作可以存储多个,然后一次性执行。如下执行Cytl+C:

ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()

示例2:鼠标右击

action=ActionChains(driver)
action.context_click().perform() # 在鼠标当前位置右击

# 鼠标在 '新闻' 元素位置右击
action.context_click(driver.find_element_by_link_text('新闻')).perform()

示例3:鼠标双击操作

action=ActionChains(driver)
action.double_click().perform() # 在鼠标当前位置双击

# 鼠标在 '新闻' 元素位置双击击
action.double_click(driver.find_element_by_link_text('新闻')).perform()

示例4:鼠标移动

action = ActionChains(driver)
element=driver.find_element_by_link_text('设置')
# 鼠标移动到 '新闻' 元素上的中心点
action.move_to_element(element).perform()

# 鼠标在原位置向x轴移动xoffset、y轴移动yoffset;xoffset、yoffset可为正负数
action.move_by_offset(-200,100).perform()

# 鼠标移动到element元素中心点偏移xoffset、yoffset
action.move_to_element_with_offset(element,-500,600).perform()

action.move_by_offset(xoffset,yoffset) 这里需要注意,如果 xoffset 为负数,表示横坐标向左移动,yoffset 为负数表示纵坐标向上移动。而且如果这两个值大于当前屏幕的大小,鼠标只能移到屏幕最边界的位置。

鼠标移动操作在测试环境中比较常用到的场景是需要获取某元素的 flyover/tips,实际应用中很多 flyover 只有当鼠标移动到这个元素之后才出现,所以这个时候通过执行 move_to_element(to_element) 操作,就能达到预期的效果。

根据我个人的经验,这个方法对于某些特定产品的图标的 flyover/tips 也不起作用,虽然在手动操作的时移动鼠标到这些图标上面可出现 flyover,但当使用 WebDriver 来模拟这一操作时,虽然方法成功执行,但 flyover 却不出来。所以在实际应用中,还需要对具体的产品页面做相应的处理。

示例5:鼠标悬停

action.click_and_hold().perform()  # 鼠标在当前位置按下并不释放
# 鼠标 在'设置' 上悬停
action.click_and_hold(driver.find_element_by_link_text('设置')).perform()
action.click_and_hold(element) 这个方法实际上是执行了两个动作,首先是鼠标移动到元素 element,然后再 click_and_hold, 所以这个方法也可以写成 action.move_to_element(element).click_and_hold()。

示例6:鼠标拖拽

source = driver.find_element_by_id("kw")  # 获取起始位置元素
target = driver.find_element_by_id("sk")  # 获取目标元素
# 将元素source拖动到target的位置
ActionChains(driver).drag_and_drop(source, target).perform()

# 鼠标拖拽动作,将 source 元素向x、y轴方向移动 (xoffset, yoffset) ,其中 xoffset 为横坐标,yoffset 为纵坐标。
ActionChains(driver).drag_and_drop_by_offset(source, -100, 100).perform()

在这个拖拽的过程中,已经使用到了鼠标的组合动作,首先是鼠标点击并按住 click_and_hold( source) 元素,然后执行鼠标移动动作 (move_to),移动到 target 元素位置或者是 (xoffset, yoffset) 位置,再执行鼠标的释放动作 (release)。所以上面的方法也可以拆分成以下的几个执行动作来完成:

ActionChains(driver).click_and_hold(source).move_to_element(target).release().perform()

示例7:鼠标释放操

action = ActionChains(driver)
action.release().perform()  # 释放按下的鼠标

二、键盘操作

对于键盘的模拟操作,ActionChains类中有提供了按下key_down(keys)、释放key_up(keys)、按下并释放send_keys(keys_to_send) 等方法。

键盘的操作有普通键盘和修饰键盘两种 。

普通键盘为常用字母数字等;修饰键盘为Ctrl、Shift、Alt等,修饰键盘一般和其他键组合使用的键。

使用键盘操作时需要引入from selenium.webdriver.common.keys import Keys包,Keys 包中含所有特殊用键。

1、普通键盘操作

键盘操作使用send_keys(*keys_to_send)方法,该方法支持多个按键连续操作,如果需要对某个元素执行按键操作使用send_keys_to_element( element, *keys_to_send)方法。具体使用如下示例:

from selenium.webdriver.common.keys import Keys
action = ActionChains(driver)
action.send_keys(Keys.SPACE).perform()  # 按下并释放空格键
action.send_keys(Keys.TAB).perform()  # 按下并释放Tab键
action.send_keys(Keys.BACKSPACE).perform()  # 按下并释放Backspace键
action.send_keys(Keys.BACKSPACE,Keys.SPACE).perform()  # 连续执行按键动作
action.send_keys(Keys.TAB).send_keys(Keys.TAB).perform() # 也可以这样组合

'''
针对某个元素发出某个键盘的按键操作,或者是输入操作
'''
element = driver.find_element_by_id('query')
# 对一元素使用键盘操作
action.send_keys_to_element(element, 'selenium').perform()
# 上面动作拆解为下面动作
action.click(element).send_keys('selenium').perform()

注意除了 ActionChains类有 send_keys(keys_to_send)方法外,WebElement 类也有一个 send_keys_to_element(keys_to_send)方法,这两个方法对于一般的输入操作基本上相同,不同点在于以下几点:

第一:Actions 中的 send_keys(*keys_to_send)对修饰键操作后并不会释放,也就是说当调用 actions.send_keys(Keys.ALT)、 actions.send_keys(Keys.CONTROL)、 action.send_keys(Keys.SHIFT) 的时候,相当于调用 actions.key_down(keys_to_send),而如果在现实的应用中想要模拟按下并且释放这些修饰键,应该先action.reset_actions()重设action,然后再调用 action.send_keys(keys.NULL).perform()取消按下的修饰键。

第三点,在 WebDriver 中,我们可以使用 WebElement 类的 send_keys() 来上传附件,比如 element.send_keys(“D: estuploadfile est.jpg”)上文件,但不能使用ActionChains来上传附件,因为type=’file’的输入框并不支持键盘输入。

2、修饰键的使用

修饰键是键盘上的一个或者一组特别的键,当它与一般按键同时使用时,用来临时改变一般键盘的普通行为。

修饰键一般跟普通键组合使用,比如 Ctrl+A、Alt+F4等。

我们电脑中的修饰键一般有以下几种修:Ctrl、Alt(Option)、Shift、AltGr、Windows logo、Command、FN(Function)。一般使用的都是前三种。

对于修饰键的使用在Python selenium中一般使用按下key_down(keys)、释放key_up(keys)、按下并释放send_keys(keys_to_send)组合实现。

action = ActionChains(driver)
action.key_down(Keys.CONTROL).perform() # 按下ctrl键
action.key_up(Keys.CONTROL).perform() # 释放ctrl键

action.key_down(Keys.SHIFT).perform() # 按下shift键
action.key_up(Keys.SHIFT).perform() # 释放shift键

action.key_down(Keys.ALT).perform() # 按下alt键
action.key_up(Keys.ALT).perform() # 释放alt键

示例:通过ctrl+c 来复制文本

ActionChains(driver).key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform()

三、WebElement.send_keys()键盘操作

WebElement元素对象下的send_keys也支持组合键盘操作。

代码示例如下:

element = driver.find_element_by_id('query')
element.send_keys('selenium')
element.send_keys(Keys.BACK_SPACE)  # 按BACKSPACE删除一个字符
element.send_keys(Keys.SPACE)  # 空格键(Space)
element.send_keys(Keys.CONTROL, 'a')  # 全选(Ctrl+A)
element.send_keys(Keys.CONTROL, 'c')  # 复制(Ctrl+C)
element.send_keys(Keys.CONTROL, 'v')  # 粘贴(Ctrl+v)
element.send_keys(Keys.TAB)  # 制表键(Tab)
element.send_keys(Keys.ESCAPE)  # 回退键(Esc)
element.send_keys(Keys.ENTER)  # 回车键(Enter)

1.6层级定位与定位一组元素

一、层级定位(二次定位)

在实际测试过程中,一个页面可能有多个属性基本相同的元素,如果要定位到其中的一个,这时候需要用到层级定位。先定位其父元素,然后再通过父元素定位该元素。

示例:通过层级定位搜狗输入框

driver = webdriver.Chrome()
driver.maximize_window()
driver.get(r'https://www.sogou.com/')
form_element = driver.find_element_by_id('sf')  # 获取form表单元素
form_element.find_element_by_id('query').send_keys('selenium')  # 通过表单定位输入框
form_element.find_element_by_id('stb').click()  # 通过表单定位搜索按钮
time.sleep(3)
driver.quit()

如上代码,我们先定位到了form表单,然后通过表单定位下面的输入框与按钮。

注意:上面示例只通过两层定位到了元素,层级定位不一定定位两次,我们可以定位多次。

二、定位一组元素

而当我们需要获取多个属性相同的对象,并且需要批量操作该对象时,就会使用find_elements定位一组元素。

创建以下html文件,文件名checkbox.html

 

示例:全选上面的多选框

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.maximize_window()
driver.get(r'E:xxxcheckbox.html') # 打开checkbox.html文件,使用绝对地址
checkboxs = driver.find_elements_by_xpath('//input[@type="checkbox"]')  # 获取批量的对象
for checkbox in checkboxs:  # 循环控制
   if not checkbox.is_selected():  # 判断多选框是否被选中
       checkbox.click()  # 单击
time.sleep(3)
driver.quit()

三、综合运用

当我们需要定位一组元素时,页面上相似的元素会很多,这时我们需要和层级一定一起使用。先定位到该组元素的父元素,然后通过父元素定位其子孙元素。

示例1:获取搜狗微信页面搜索热词的内容

driver = webdriver.Chrome()
driver.maximize_window()
driver.get(r'http://weixin.sogou.com/')
topele = driver.find_element_by_id('topwords')  # 搜索热词的父元素
tops = topele.find_elements_by_tag_name('a')  # 二次批量定位热词元素
for top in tops:  # 循环获取元素
   print(top.text)  # 打印文本内容
driver.quit()

UI自动化测试中对于表格的定位是个难点,怎么样快速获取表格数据,请看下面几个示例。

示例2:定位表格获取表头

driver = webdriver.Chrome()
driver.maximize_window()
driver.get(r'http://www.w3school.com.cn/cssref/css_selectors.asp')
# //table[@class="dataintable"]//tr[1]//th 获取表头元素
table_header = driver.find_elements_by_xpath('//table[@class="dataintable"]//tr[1]//th')
for header in table_header:  # 循环获取元素
   print(header.text)  # 打印文本内容
driver.quit()

示例3:定位表格第二列数据内容

driver = webdriver.Chrome()
driver.maximize_window()
driver.get(r'http://www.w3school.com.cn/cssref/css_selectors.asp')
# //table[@class="dataintable"]//tr[y]//td[x]   y第几条记录,x第几列数据
# //table[@class="dataintable"]//tr//td[2] 获取第二列数据
table_header = driver.find_elements_by_xpath('//table[@class="dataintable"]//tr//td[2]')
for header in table_header:  # 循环获取元素
   print(header.text)  # 打印文本内容
driver.quit()

示例4:获取表格中所有的数据

driver = webdriver.Chrome()
driver.maximize_window()
driver.get(r'http://www.w3school.com.cn/cssref/css_selectors.asp')
# //table[@class="dataintable"]//tr 定位所有行
tables = driver.find_elements_by_xpath('//table[@class="dataintable"]//tr')
for tr in tables:  # 循环每行元素
   for td in tr.find_elements_by_tag_name('td'):  # 循环获取列
       print(td.text, end='		')
   print('
')
driver.quit()

定位表格,采用find_elements 组定位,使用xpath=//table//tr[y]//td[x](y第几条记录,x第几列数据),当y或者x其中一个没有值时定位一行或一列。

1.7下拉框元素定位

选择获取反选下拉框元素首先要实例化select元素

from selenium.webdriver.support.ui import Select # 引入包

select_element=Select(element) # 实例化select

三种常用选择方法

select_element.select_by_index(index) 根据index定位,从0开始 select_element.select_by_value(value) 根据value属性定位 select_element.select_by_visible_text(text) 根据文本定位

反选的方法

select_element.deselect_by_index(index) 根据index定位,从0开始 select_element.deselect_by_value(value) 根据value属性定位 select_element.deselect_by_visible_text(text) 根据文本定位 select_element.deselect_all() 取消全部选择

获取选项的值

select_element.options 返回这个select元素所有的options select_element.all_selected_options 所有被选中的options select_element.first_selected_option 第一个被选中的option

创建select.html 文件,代码如下:

示例1:采用三种方法依次选择's1Id'的值

s1 = Select(driver.find_element_by_id('s1Id'))  # 实例化Select,页面第一个下拉框
s1.select_by_index(1)  # 选择第二项选项:o1
s1.select_by_value("o2")  # 选择value="o2"的项
s1.select_by_visible_text("o3")  # 选择text="o3"的值,即在下拉时我们可以看到的文本

示例2:想查看一个's1Id'所有的选项

s1 = Select(driver.find_element_by_id('s1Id'))
for select in s1.options:
   print(select.text)

示例3:查看我已选中的所有选项,'s2Id'可以多选的选择框

s4 = Select(driver.find_element_by_id('s2Id'))
s4.select_by_index(1)  # 根据顺序选择第2个
s4.select_by_value("o2val")  # 根据value属性选择o2val
s4.select_by_visible_text("With spaces")  # 根据展示文本选择With spaces
s4.select_by_visible_text(u"    With nbsp") # 注意空格,只有为 是才用空格
for select in s4.all_selected_options:  # 循环获取所有的值
   print(select.text)

注意:只有只有为 的空格才是空格,在html中代码只有 才代表空格,代码中的空格不是空格。

示例4:查看选择框的默认值或选中的值

s1 = Select(driver.find_element_by_id('s1Id'))
print(s1.first_selected_option.text)  # 查看选择默认值
s1.select_by_value("o2")
print (s2.first_selected_option.text)  # 查看选中的值

示例5:取消选择

s4 = Select(driver.find_element_by_id('s2Id'))
s4.select_by_index(1)
s4.select_by_value("o2val")
s4.select_by_visible_text("With spaces")
s4.select_by_visible_text(u"    With nbsp")
s4.deselect_by_index(1)  # 根据值顺序取消选择
s4.deselect_by_value("o2val")  # 根据value属性取消选择
s4.deselect_by_visible_text("With spaces")  # 根据文本取消选择
s4.select_by_value("o2val")
s4.select_by_index(1)
s4.deselect_all()  # 取消全部选择

1.8定位frame和iframe中的元素对象

< frame>

inner_frame.html



   inner frame





   

inner frame


示例:操作主文档的元素 --> 切换到外层frame 操作外层frame的元素 --> 切换到内层frame 操作内层的元素 --> 切换回外层frame 操作外层frame 的元素 --> 再次切入内层frame操作元素 --> 切换回主文档操作文档元素 -->再去切换到外层frame操作元素

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.get(r'E:frame.html')  # 打开frame.html页面,注意修改为你的位置
driver.find_element_by_id('frameinput').send_keys('操作frame外的元素')
driver.switch_to.frame(0)  # 根据index切换,从0开始
text = driver.find_element_by_id('innerlable').text
print(text)
driver.find_element_by_id('innercheck').click()
driver.switch_to.frame('f2')  # 根据id切入 内层frame
driver.find_element_by_id('index-kw').send_keys('selenium frame')
driver.switch_to.parent_frame()  # 切换到上一层表单
driver.find_element_by_id('innercheck').click()
driver.switch_to.frame('frame2')  # 根据name再次切入内层frame
driver.find_element_by_id('index-bn').click()
driver.switch_to.default_content() # 切换回主文档
driver.find_element_by_ta('frameinput').clear()
driver.switch_to.frame(driver.find_elements_by_tag_name('iframe'))  # 通过webelement切换driver.find_element_by_id('innercheck').click()
time.sleep(3)
driver.quit()

1、 driver.switch_to.frame(frame_reference)切换进入frame

switch_to_frame() 将淘汰使用,建议使用switch_to.frame()。

switch_to.frame() 切换frame支持4种不同参数方法进行切换,元素的frame的index,frame的id或name属性,frame元素的WebElement元素对象。

通常采用id和name就能够解决绝大多数问题。但有时候frame并无这两项属性,则可以用index和WebElement来定位:

2、 driver.switch_to.default_content() 切换回主文档

切到frame中之后,我们便不能继续操作主文档的元素,这时如果想操作主文档内容,则需切回主文档。

driver.switch_to.default_content() # 切换到主文档中。

注意:很多人都会忘记这步操作

3、driver.switch_to.parent_frame() 切换到上一层表单


   

嵌套frame很少会遇到,如下frame1为外层,frame2嵌套在frame1中。我们进行切换操作如下:

a. 从主文档切到frame2,一层层切进去

driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")

b. 从frame2再切回frame1,selenium提供了一个方法能够从子frame切回到父frame,而不用我们切回主文档再切进来。

driver.switch_to.parent_frame()  # 如果当前已是主文档,则无效果

parent_frame()这个相当于后退的方法,我们可以随意切换不同的frame。

1.9Alert/Confirm/Prompt 弹出窗口处理

一、Alert/Confirm/Prompt弹出窗口特征说明

Alert弹出窗口:

提示用户信息只有确认按钮,无法通过页面元素定位,不关闭窗口无法在页面上做其他操作。

Confirm 弹出窗口:

有确认和取消按钮,该弹出窗口无法用页面元素定位,不关闭窗口无法在页面上做其他操作。

Prompt弹出窗口:

有输入框、确认和取消按钮,该弹出窗口无法用页面元素定位,不关闭窗口无法在页面上做其他操作。

注意:3种窗口为浏览器自带的窗口,该窗口无法定位到元素,能定位到元素需要使用WebElement操作。

二、Alert/Confirm/Prompt弹出窗口操作

第一步:需要获取弹出窗口,两种方法 与Alert(driver)

alert=driver.switch_to.alert

from selenium.webdriver.common.alert import Alert
alert=Alert(driver)

第二步:对获取到的窗口进行操作,常用方法如下:

alert.text()  # 获取窗口信息
alert.accept()  # 确认
alert.dismiss()  # 取消
alert.send_keys(keysToSend)  # 输入信息

alert.authenticate(username, password) # 用户认证信息登录,已有确认操作

三、实例说明

创建下面3个html文件

alertTest.html



   Alert Test
   



Alert Test

confirmTest.html



   
   Confirm Test



Confirm Test

promptTest.html



   
   Prompt Test



Prompt Test

示例1:Alert弹窗获取文本与确认操作

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.expected_conditions import alert_is_present
from selenium.webdriver.common.alert import Alert

driver = webdriver.Chrome()
driver.get(r'E:XXXalertTest.html')
driver.find_element_by_name('button1').click()  # 点击第一个按钮
WebDriverWait(driver, 5).until(alert_is_present())  # 等待弹出窗口出现
alert = driver.switch_to.alert  # 获取弹出窗口
text1 = alert.text  # 获取窗口文本信息
print(text1)  # 打印窗口文本信息
alert.accept()  # 确认
print('----------')
driver.find_element_by_name('button2').click()  # 点击第二个按钮
WebDriverWait(driver, 5).until(alert_is_present())  # 等待弹出窗口出现
alert = Alert(driver)  # 获取弹出窗口
text1 = alert.text  # 获取窗口文本信息
print(text1)  # 打印窗口文本信息
alert.accept()  # 确认
driver.quit()

注意:WebDriverWait(driver, 5).until(alert_is_present()) 加上这个可提高代码的可靠性

示例2:Comfirm弹窗获取文本、确认、取消操作

driver = webdriver.Chrome()
driver.get(r'E:XXXconfirmTest.html')
driver.find_element_by_name('button1').click()  # 点击按钮
WebDriverWait(driver, 5).until(alert_is_present())  # 等待弹出窗口出现
alert = driver.switch_to.alert  # 获取弹出窗口
print(alert.text)  # 打印窗口信息
alert.accept()  # 确认
time.sleep(2)

driver.find_element_by_name('button1').click()  # 点击按钮
WebDriverWait(driver, 5).until(alert_is_present())  # 等待弹出窗口出现
alert = driver.switch_to.alert  # 获取弹出窗口
alert.dismiss()  # 取消
time.sleep(2)
driver.quit()

示例3:Prompt 弹窗获取文本、输入内容、确认操作

driver = webdriver.Chrome()
driver.get(r'E:XXXpromptTest.html')
driver.find_element_by_name('button1').click()  # 点击按钮
WebDriverWait(driver, 5).until(alert_is_present())  # 等待弹出窗口出现
alert = Alert(driver)  # Alert 获取弹出窗口
alert.send_keys('selenium Alert弹出窗口输入信息')  # 输入信息
alert.accept()  # 确认
time.sleep(2)
driver.quit()

1.10上传文件

一、input控件上传文件

查看长传文件的页面元素标签,如果为input表明是通过input控件上传文件。我们可以直接采用WebElement.send_keys(‘文件地址’) 长传文件。

创建html文件,如下:

upload.html



   
   upload file


upload file

示例:长传C:install.log文件。

from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get(r'E:XXXXHtmlupload.html')  # 文件的地址
driver.find_element_by_name('file').send_keys(r'C:install.log')  # 上传文件
time.sleep(2)
driver.quit()

1.11浏览器多窗口切换

有时web应用会打开多个浏览器窗口,当我们要定位新窗口中的元素时,我们需要将webDriver的handle(句柄)指定到新窗口。

什么意思?

假设我们打开web应用,在系统运行过程中重新打开一个新窗口(可以是页签,当前浏览器存在两个窗口),这时我们webDriver对浏览器的操作指针(句柄)还再原窗口,如果需要操作新窗口元素就要将handle句柄切换到新窗口。

一、常用方法

driver.current_window_handle 获取当前窗口handle

driver.window_handles 获取所有窗口的handle,返回list列表

driver.switch_to.window(handle) 切换到对应的窗口

driver.close() 关闭当前窗口

二、示例

示例:进入搜狗搜索 --> 打开搜狗输入法页面 --> 输入法页面查看皮肤 --> 关闭搜狗搜索页面 --> 输入法页面查看词库

from selenium import webdriver
import time

driver = webdriver.Chrome()
driver.get('https://www.sogou.com/')
driver.find_element_by_link_text('搜狗输入法').click()
nowhandle = driver.current_window_handle  # 获得当前窗口
print(driver.current_window_handle)
print('当前窗口为:', driver.title)
allhandles = driver.window_handles  # 获得所有窗口
for handle in allhandles:  # 循环判断窗口是否为当前窗口
   if handle != nowhandle:
       driver.switch_to.window(handle)  # 切换窗口
       time.sleep(2)
print('切换到窗口:', driver.title)
driver.find_element_by_link_text('皮肤').click()  # 操作新窗口元素
driver.switch_to.window(nowhandle)  # 回到原先的窗口
print('回到原来窗口:', driver.title)
driver.close()  # 关闭当前窗口,关闭的是当前的窗口
driver.switch_to.window(driver.window_handles[0])  # 再次切换窗口
driver.find_element_by_link_text('词库').click()
time.sleep(5)
driver.quit()

三、封装层函数

在自动化测试中切换窗口页面一般会封装为函数,如下示例:

def switch_to_window(driver, winB):
   """
   :param winB:
       1.切换窗口的标题
       2.切换窗口的序号
       3.切换页面的元素
   :return: True 切换成功
   :Usage:
   driver.switch_to_window('win_name')
   driver.switch_to_window(2) # 切换到第二个窗口
   located=(By.ID,'id') # 确定切换页面的元素
   driver.switch_to_window(located) # 切换到页面中存在located的元素窗口
   """
   result = False
   handles = driver.window_handles
   current_handle = driver.current_window_handle
   if isinstance(winB, tuple):
       for handle in handles:
           driver.switch_to.window(handle)
           time.sleep(2)
           try:
               driver.find_element(*winB)
           except NoSuchElementException:
               pass
           else:
               result = True
               break
       if not result:
           driver.switch_to.window(current_handle)
           time.sleep(2)
   elif isinstance(winB, str):
       for handle in handles:
           driver.switch_to.window(handle)
           time.sleep(2)
           if winB in driver.title:
               result = True
               break
       if not result:
           driver.switch_to.window(current_handle)
           time.sleep(2)
   elif isinstance(winB, int):
       if winB <= len(handles):
           driver.switch_to.window(winB - 1)
           time.sleep(2)
           result = True
   else:
       print('参数错误')
   return result

1.12xpath定位元素

XPath 最初是用来在 XML 文档中定位 DOM 节点的语言,由于 HTML 也可以算作 XML 的一种实现,所以 Selenium 也可以利用 XPath 这一强大的语言来定位 Web 元素。xpath的强大在于它可以通过父节点或者兄弟节点,根据html元素的前后关联性定位到元素需要的元素。

XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。

1、选取节点

XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

示例:

2、谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中。

3、选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

示例:

4、XPath 轴

轴可定义相对于当前节点的节点集。

示例:

5、综合运用

示例:搜狗搜索页面元素为示例

1.13CSS定位元素

1、CSS 元素选择器

input 选择input元素

p 选择p元素

2、CSS ID与类选择器

ID 选择器以 "#" 来定义。

class类选择器以一个‘.’点号显示

示例:搜狗搜索页面元素示例

#query 表示id为query的元素

.query 表示class为query的元素

3、CSS 属性选择器

属性选择器可以根据元素的属性及属性值来选择元素。

示例:

[title] 将title属性放到中括号中,表示选择具有该属性的元素

[title=value] title属性等于value的元素

[title~=value] title属性包含value单词的元素,注意是单词

[title|=value] title属性以value单词开头的元素

[title^=value] title属性以value开头的元素

[title$=value] title属性以value结尾的元素

[title*=value] title属性包含value的元素

input[title*=value] input元素下有title属性包含value的元素

inputtype="ext#query input元素下有type="text"、 name='query'、id="query"的元素

4、CSS 后代选择器

后代选择器(descendant selector)又称为包含选择器。后代选择器可以选择作为某元素后代的元素。

注意:后代不一定是儿子,也有可能是孙子。

示例:搜狗搜索页面元素示例

span input 选择span下的input元素

p.content span.enter-input input#stb 选择p.content下span.enter-input的下的input ID=stb的元素。(搜狗搜索示例)

5、CSS 子元素选择器

与后代选择器相比,子元素选择器(Child selectors)只能选择作为某元素子元素的元素。

如果您不希望选择任意的后代元素,而是希望缩小范围,只选择某个元素的子元素,就使用子元素选择器(Child selector)。

与后代的区别在于,子元素选择器只能选择儿子。

示例:搜狗搜索页面元素示例

p>input 只作为 p 元素子元素的 input元素

p>form>span>input p下的子元素form下的子元素span下的子元素input

p>form[name='sf']>span>input#query p下的子元素form[name='sf']下的子元素span下的子元素input#query

p#content form>span>input#query p#content下的子元素form下的子元素span下的子元素input#query

6、CSS 相邻兄弟选择器

相邻兄弟选择器(Adjacent sibling selector)可选择紧接在另一元素后的元素,且二者有相同父元素。

示例:搜狗搜索页面元素示例

input+input input后出现的input的元素

p#content form>span+input p#content下的form元素下的子元素span同级相邻的第一个弟弟元素

7、CSS 伪类

CSS 伪类用于向某些选择器添加特殊的效果。selenium中元素CSS定位用的伪类只有:first-child(元素的第一个子元素),其他的可靠性非常低要不就是不能使用。

示例:搜狗搜索页面元素示例

input:first-child 所有第一个input元素

form > input:first-child 所有 form子元素中的第一个 input 元素

form input:first-child 所有 form元素中以input 作为第一个元素的元素

form span:first-child input:first-child form下的第一个span元素下的第一个input元素

8、CSS选择器运用示例

例子是搜狗搜索中的元素为例。

9、CSS选择器参考手册

参考w3school的选择器参考手册为样本,进行了删减,将不适合自动化测试的选择器删除。

原文参考手册见: http://www.w3school.com.cn/cssref/css_selectors.asp

例子是搜狗搜索中的元素为例:

1.14JavaScript获取页面元素

1、DOM获取元素

HTML DOM 定义了访问和操作 HTML 文档的标准。每个页面都是一个DOM Tree 结果,如下图

通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。我们通过JavaScript返回该节点就是我们的元素。

document.getElementById() 获取带有指定 ID 的元素

document.getElementsByClassName() 获取包含带有指定类名的所有元素的节点列表

document.getElementsByName() 获取指定Name的所有元素的节点列表

document.getElementsByTagName() 获取带有指定标签名称的所有元素的节点列表

注意:getElementsByClassName() 在 Internet Explorer 5,6,7,8 中无效

示例:通过DOM的JavaScript脚本获取元素

js='return document.getElementById("query")'
js='return document.getElementsByClassName("sec-input")[0]'
js='return document.getElementsByName("query")[0]'
js='return document.getElementsByTagName("input")[0]'
js='return document.getElementById("sf").getElementsByTagName("input") ' #  id=sf的input子元素
element=driver.execute_script(js)  # 执行js获取元素

注意:由于getElements返回的为列表所以需要使用[0]指定为第1个元素,如果查找出对应元素存在多个可以指定第几个。

2、JQuery获取元素

JQuery获取元素也是通过返回值获取,比DOM的兼容性高。

常用语法格式如下:

return $("p:contains('包含的字符')")[0] 根据页面文本获取元素

return $(css定位)[0] css定位获取对象

return $x(xpath定位)[0] xpath定位获取对象

示例:

js = 'return $("input[name=w]+input")[0]'
js = 'return $("form#sf input[type=text]")[0]'
js = 'return $x("//input[@name='w']/following-sibling::input")[0]'
js='$("p:contains('搜狗搜索APP')")[0]'
element=driver.execute_script(js)  # 执行js获取元素

附件:JQuery选择器

来自于:http://www.w3school.com.cn/jquery/jquery_ref_selectors.asp

1.15JavaScript操作元素对象

avaScript操作元素对象可以使用DOM操作元素,如果应用有JQuery可以使用JQuery操作元素对象。

selenium运行JavaScript有两种形式,一种是接收JavaScript脚本语言,另一种是将WebElement传入JavaScript中执行脚本。如下:

driver.execute_script("window.open('https://www.qqcom')")
driver.execute_script('arguments[0].scrollIntoViewIfNeeded(true);',element)

1、打开新窗口

DOM操作:

window.open("https://www.qqcom") 

2、滚动浏览器滚动条

DOM操作:

document.body.scrollWidth;    //网页正文全文宽,包括有滚动条时的未见区域
document.body.scrollHeight;   //网页正文全文高,包括有滚动条时的未见区域
document.documentElement.clientWidth;    //可见区域宽度,不有滚动条时的未见区域
document.documentElement.clientHeight;   //可见区域高度,不有滚动条时的未见区域
document.documentElement.scrollTop=100;  //设置或返回匹配元素相对滚动条顶部的偏移
document.documentElement.scrollLeft=100 ; //设置或返回匹配元素相对滚动条左侧的偏移
window.scrollTo(100,400);   //设计滚动条left=100,top=400
document.getElementsByClassName("name")[0].scrollIntoViewIfNeeded(true)  //滚动到name元素显示

JQuery操作:

JQueryelement.height() 设置或返回匹配元素的高度

JQueryelement.width() 设置或返回匹配元素的宽度

JQueryelement.scrollTop() 设置或返回匹配元素相对滚动条顶部的偏移。

JQueryelement.scrollLeft() 设置或返回匹配元素相对滚动条左侧的偏移。

示例:

$(window).scrollTop(300);    //拖动页面距离顶部300像素
$(document).scrollTop(300)  
$("html,body").scrollTop(300);   
$(window).scrollTop(document.body.scrollHeight); //拖动到底部
$(document).scrollTop($(window).height());   //拖动到底部

3、拖动窗口内元素滚动条

DOM操作:

document.getElementsByClassName("scroll")[0].scrollTop=10000  
document.getElementsByClassName("scroll")[0].scrollLeft=10000

JQuery操作:

$("p.id").scrollTop(300);   
$("p.id").scrollLeft(300);

4、新增与修改元素属性

DOM操作:

改变属性

document.getElementById('query').value='selenium'    // 设置元素值,如果是输入框则输入内容
document.getElementsByClassName("sec-input")[0].disabled=false   // 取消置灰

使元素隐藏或可见

document.getElementById("query").style.display="none"  // 隐藏
document.getElementById("query").style.display="block"  // 可见

JQuery操作:

JQueryelement.attr() 设置或返回匹配元素的属性和值。

$("#query").attr('value','selenium')   //设置元素值,如果是输入框则输入内容
$("#query").attr('disabled',false)      //取消置灰
$("#query").attr('style','display: none;')   // 隐藏

$("#query").attr('style','display: block;') # 可见

5、删除元素属性

DOM操作:移除元素属性

document.getElementById("query").removeAttribute('readonly') // 移除'readonly'属性,是元素可输入
document.getElementById('query').value   // 获取value值

JQuery操作:移除元素属性

JQueryelement.removeAttr() 从所有匹配的元素中移除指定的属性。

$("#query").removeAttr('readonly')  // 移除'readonly'属性,是元素可输入

6、获取元素的内容

DOM操作:

document.getElementById("query").innerHTML     // 获取HTML内容
document.getElementsByClassName('top-nav')[0].innerText   // 获取文本内容
document.getElementsByClassName("sec-input")[0].attributes.属性    //获取元素属性

JQuery操作:

JQueryelement.html() 设置或返回匹配的元素集合中的 HTML 内容。

JQueryelement.val() 设置或返回匹配元素的value属性值

JQueryelement.text() 设置或返回匹配元素的内容。

$('.top-nav').html()  // 获取HTML
$('.top-nav').text()  // 获取text
$('#query').val()  //获取val值

7、操作页面元素

DOM操作:

document.getElementById('stb').click()   // 单击元素

JQuery操作:

$('#stb').click()

8、传入WebElement元素对象js操作

js=’arguments[0].click()’
driver.execute_script(js,element)

注意:execute_script接收两个参数arguments[0] 表示元素,element为需要传入的元素

示例:搜狗浏览器输入值

element=driver.find_element_by_id('query')
driver.execute_script('arguments[0].value="selenium"',element)

示例:符文框输入带html格式的值

driver.get('http://ueditor.baidu.com/website/onlinedemo.html')  # 打开网页
driver.switch_to.frame(driver.find_element_by_xpath('//p[@id="edui1_iframeholder"]/iframe'))  # 切换iframe
WebDriverWait(driver, 15).until(lambda driver: driver.find_element_by_css_selector('body.view'))
element = driver.find_element_by_css_selector('body.view') 
driver.execute_script('arguments[0].innerHTML="selenium

selenium

"', element)

示例:滚动条拖动到元素位置

driver.get('http://news.sogou.com/')  
element=driver.find_element_by_id('auto')
driver.execute_script('arguments[0].scrollIntoViewIfNeeded(true);',element)

1.16cookie 处理

river.get_cookies() # 获得cookie 信息

driver.get_cookies(name) # 获得对应name的cookie信息

add_cookie(cookie_dict) # 向cookie 添加会话信息

delete_cookie(name) # 删除特定(部分)的cookie

delete_all_cookies() # 删除所有cookie

示例:

from selenium import webdriver
driver=webdriver.Chrome()
driver.get('https://www.sogou.com/')
cookies = driver.get_cookies()  # 获得所有cookie 信息
print('删除前cookies:',cookies)  # 打印cookie信息
driver.add_cookie({'name': 'key-name', 'value': 'value-123456'})  #添加cookie信息
print('key-name cookie信息:',driver.get_cookie('key-name')) # 查看添加的key-name的cookie信息
driver.delete_cookie("key-name")  # 删除一个特定的cookie
driver.delete_all_cookies()  # 删除所有cookie
print('删除后cookies:',driver.get_cookies())
driver.quit()

2.unittest单元测试框架

2.1 unittest单元测试实例

创建计算器类calculator

# Calculator.py
class calculator(object):
   def __init__(self, a, b):
       self.a = a
       self.b = b

   def add(self):
       return (self.a + self.b)

   def minus(self):
       return (self.a - self.b)

   def multip(self):
       return (self.a * self.b)

   def pide(self):
       return (self.a / self.b)

创建一个简单的单元测试用例

import unittest  # 导入unittest  包
from unittest_doc.com.Calculator.Calculator import calculator  # 引入需要测试的包

# 所有用例需继承TestCase类或者其子类
class simple_test(unittest.TestCase):
   def setUp(self):
       print('@@@初始化test_simple@@@')
       self.a = calculator(1, 2)

   def test_add(self):
       print('---测试用例test_simple add---')
       self.assertEqual(self.a.minus(), -1, '两值不相等')
       self.assertEqual(self.a.add(), 3, '两值不相等')
       self.assertNotEqual(self.a.pide(), 1, '两值不相等')

   def test_pide(self):
       print('---测试用例test_simple pide---')
       self.assertEqual(self.a.pide(), 0.5)

   def tearDown(self):
       print('@@@结束test_simple@@@')

if __name__ == '__main__':
   unittest.main()

运行结果:

@@@初始化test_simple@@@
---测试用例test_simple add---
@@@结束test_simple@@@
@@@初始化test_simple@@@
---测试用例test_simple pide---
@@@结束test_simple@@@

2.2 TestCase详解

测试用例由setUp(),test_add(),test_pide(),tearDown() 4个部分组成,它们放在一个继承于unittest.TestCase 的测试类下。

2.2.1继承

unittest提供一个基类TestCase,如果我们要编写一个测试用例,就需要继承这个抽象基类,这样当我们运行测试程序时它会自动的运行这些测试用例。

2.2.2测试方法的名称

测试方法要以test开头,这样测试程序能够自动找到要运行的方法,在上述例子中包含3个测试方法,

2.2.3setUp和tearDown

setUp() 用于测试用例执行前的准备工作。如测试用例中需要访问数据库,可以在setUp中建立数据库连接并进行初始化;用例需要使用web,可以先实例化浏览器;app测试需先要启动app,可先实例化app。

tearDown() 用于用例执行之后的善后工作。如关闭数据库连接,关闭浏览器,关闭app。当用例没运行成功是他也会执行。

setUpClass() 所有测试用例运行前运行,必须使用@classmethod装饰器装饰,在setUp()方法前执行,整个测试过程只执行一次,主要作用是单元测试前的准备工作。

tearDownClass() 所有测试用例运行后运行,必须使用@classmethod装饰器装饰,在tearDown()方法后执行,整个测试过程只执行一次,主要作用是单元测试后的清理工作。

2.2.4断言

assertEqual()来检查预期的输出;调用assertTrue()assertFalse()来验证一个条件;调用assertRaises()来验证抛出了一个特定的异常。

2.3TestSuite测试套件

2.3.1TestSuite 测试套件简介

对一个功能的验证往往是需要很多多测试用例,可以把测试用例集合在一起执行,这就产生了测试套件TestSuite 的概念,它是用来组装单个测试用例,规定用例的执行的顺序,而且TestSuite也可以嵌套TestSuite。

2.3.2初始化套件

suite = unittest.TestSuite()

2.3.3添加测试用例

2.4 TestLoader 加载测试用例

unittest.TestLoader()根据目录批量创建测试套件,可以指定用例存放目录,根据文件名称匹配测试用例。

注意:用例存放的子目录中必须具备init.py 文件,否则无法加载用例。

语法:

unittest.TestLoader().discover(start_dir, pattern='test*.py', top_level_dir=None)*
'''
start_dir要测试的模块名或测试用例目录。
pattern='test.py' 表示用例文件名的匹配原则。星号“*”表示任意多个字符。
top_level_dir=None 测试模块的顶层目录。None <=> 测试用例不是放在多级目录中
'''

示例:

suites=unittest.defaultTestLoader.discover('./testDirectory', pattern='*_test.py')

suites=unittest.TestLoader().discover('./testDirectory', pattern='*_test.py')

2.5 TestsRunner 执行测试用例

2.5.1TextTestRunner

创建测试套件后,执行测试用例使用unittest.TextTestRunner().run(TestSuite)

示例:执行加载simple_test用例的测试套件

suites = unittest.TestLoader().discover('./testDirectory', pattern='*_test.py') #加载测试用例
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suites)  # 执行测试用例

测试套件灵活运用

import unittest  # 导入unittest  包
from unittest_doc.com.Calculator.Calculator import calculator  # 引入需要测试的包

# 所有用例需继承TestCase类或者其子类
class simple_test(unittest.TestCase):
   def setUp(self):
       print('@@@初始化test_simple@@@')
       self.a = calculator(1, 2)

   def test_add(self):
       print('---测试用例test_simple add---')
       self.assertEqual(self.a.minus(), -1, '两值不相等')
       self.assertEqual(self.a.add(), 3, '两值不相等')
       self.assertNotEqual(self.a.pide(), 1, '两值不相等')

   def test_pide(self):
       print('---测试用例test_simple pide---')
       self.assertEqual(self.a.pide(), 0.5)

   def tearDown(self):
       print('@@@结束test_simple@@@')

def test_suite():  # 创建测试添加测试套件函数
    suite = unittest.TestSuite()  # 建立测试套件
    suite.addTests([simple_test('test_add'), simple_test('test_pide')])
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(test_suite())
suite1 = unittest.TheTestSuite()
suite2 = unittest.TheTestSuite()
alltests = unittest.TestSuite((suite1, suite2))

2.5.2 HTMLTextRunner

fp=open(filename, 'wb')  # 写方式打开报告文件
runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='报告标题',description='报告说明' )
#执行测试
runner.run(Suite)  # Suite为TestSuite测试套件
#构建测试用例集
suite=unittest.defaultTestLoader.discover('../testDirectory', pattern='*_test.py')
#测试套件组合在一起
now=time.strftime("%Y%m%d%H%M%S", time.localtime())  
filename=r'./report/'+now+r'result.html'  # 根据时间生成文件名
with openopen(filename, 'wb') as fp:
	runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='报告标题',description='报告说明' )
	runner.run(suite)#执行测试

2.6跳过测试

class SkipCase(unittest.TestCase):

    def setUp(self):
        self.test_class = TestClass()


    @unittest.skip("Skip test.")
    def test_add_5_5(self):
        self.assertEqual(self.test_class.add(5, 5), 10)

    @unittest.skipIf(NUM < 3, "Skiped: the number is too small.")
    def test_bool_value(self):
        self.assertTrue(self.test_class.is_string("hello world!"))

    @unittest.skipUnless(NUM==3, "Skiped: the number is not equal 3.")
    def test_raise(self):
        self.assertRaises(KeyError, self.test_class.raise_error)

unittest中使用装饰器的方式来实现跳过测试与预计的失败,常用的主要有3中,

2.7断言assert

assertEqual(a,b,[msg]):断言a和b是否相等,相等则测试用例通过。

assertNotEqual(a,b,[msg]):断言a和b是否相等,不相等则测试用例通过。

assertTrue(x,[msg]):断言x是否True,是True则测试用例通过。

assertFalse(x,[msg]):断言x是否False,是False则测试用例通过。

assertIs(a,b,[msg]):断言a是否是b,是则测试用例通过。

assertNotIs(a,b,[msg]):断言a是否是b,不是则测试用例通过。

assertIsNone(x,[msg]):断言x是否None,是None则测试用例通过。

assertIsNotNone(x,[msg]):断言x是否None,不是None则测试用例通过。

assertIn(a,b,[msg]):断言a是否在b中,在b中则测试用例通过。

assertNotIn(a,b,[msg]):断言a是否在b中,不在b中则测试用例通过。

assertIsInstance(a,b,[msg]):断言a是是b的一个实例,是则测试用例通过。

assertNotIsInstance(a,b,[msg]):断言a是是b的一个实例,不是则测试用例通过。

assertRaises(Exceptm,a,value,[msg]):value值是否有异常

msg='测试失败时打印的信息'

2.8参数化

2.8.1参数化代码 1.导包 unittest/parameterized 2.定义测试类 3.书写测试方法(用到的测试数据使用变量代替) 4.组织测试数据并传参

2.8.2代码实现

3.自动化框架搭建

根目录下放:

展开阅读全文

页面更新:2024-02-27

标签:测试   断言   套件   示例   属性   元素   浏览器   窗口   页面   操作

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top