selenium学习(二)

第八课–元素定位八种方式

要想操作Web界面上的元素,首先要定位到该元素,Selenium提供了定位元素的API,这些方法都被定义在WebDriver类中,浙西额方法都是以find开头。

方法名称 描述 可能带来的问题
find_element_by_id 通过id定位元素 开发代码id应该是唯一的,常用的id进行定位
find_element_by_xpath 通过xpath定位元素 通过浏览器插件来获得xpath路径,选中元素右键copy- copy xpath
find_element_by_link_text 通过链接文本定位元素
find_element_by_partial_link_text 通过部分链接文本定位元素 链接部分文本可能会存在同一个界面多个链接,返回结果就可能是个集合
find_element_by_name 通过属性名称定位元素 可能会返回多个元素,因为名字重复,仅返回第一个;使用find_elements_by_name()返回一个集合
find_element_by_tag_name 通过标签名称定位元素 一个界面可能会存在多个相同标签的组建,返回的是一个集合
find_element_by_class_name 通过css class定位元素 class的name不重复的情况下可用,反之会返回一个集合
find_element_by_css_selector 通过css选择器定位元素 通过浏览器插件来获取selector,选中元素右键copy- copy selector

将以上定位元素的方法封装一下,使用的是driver.find_element(*loc),通过哪种方式定位引入By,例如By.ID

def get_element(driver, *loc):
    element = driver.find_element(*loc)
    return element

if __name__ == '__main__':
    driver = webdriver.Chrome()
    driver.get('https://www.baidu.com/')
    input = get_element(driver,By.ID,'kw')  #使用方式
    # loc = (By.ID, 'kw')
    # input = get_element(driver, *loc)  #第二种方式
    input.send_keys('即可时间')
    sleep(1)
    get_element(driver,By.ID,'su').click()
    sleep(1)
    driver.quit()

传参的时候注意也需要加*号

第九课–webdirver的工作原理

客户端API怎样和驱动进行通信,驱动又怎么驱动浏览器进行工作,其之间的通信协议是什么,又是怎样协同工作的

WebDriver的工作原理

举一个打车的例子,会有三个角色:

  • 乘客:告诉出租车司机去哪里,大概怎么走
  • 出租车司机:按照乘客的要求来操控出租车
  • 出租车:按照司机的操控完成行驶任务,把乘客送到目的地

与WebDriver映射关系:

  • 工程师写的自动化测试代码:自动化测试代码发送请求给浏览器的驱动(如火狐驱动、谷歌驱动)
  • 浏览器的驱动:解析这些自动化代码,解析后把他们发送给浏览器
  • 浏览器:执行浏览器驱动发来的指令,并最终完成工程师想要的操作

WebDriver和浏览器是如何通信

selenium学习(二)_第1张图片
API和驱动之间是一个C/S,驱动中包含一个http 服务器,有一个端口用来监听请求

  • 对于每一条Selenium脚本,一个http请求会被创建并且发送给浏览器的驱动
  • 浏览器驱动中包含一个http Server ,用来接收这些http请求
  • http Server 接收到请求后根据请求来具体操控对应的浏览器
  • 浏览器执行具体的测试步骤
  • 浏览器将步骤执行结果返回给http Server
  • Http Server 又将结果返回给Selenium的脚本,如果是错误的http代码就会在控制台看到对应的报错信息

WebDriver的协议

webdriver使用的协议是:JSON Wire protocol
通信的数据格式是JSON

第十课–WebDriver核心方法和属性的使用

属性

# 属性 属性描述
1 driver.name 浏览器名称
2 driver.title 当前页面的标题
3 driver.current_url 当前页面url
4 driver.page_source 当前页面源码
5 driver.current_window_handle 窗口句柄
6 driver.window_handles 当前窗口所有句柄

方法

# 方法 方法描述
1 driver.back() 后退一个界面
2 driver.refresh() 刷新界面
3 driver.forward() 前进一个界面
4 driver.close() 关闭当前窗口
5 driver.quit() 退出浏览器
6 driver.switch_to.frame() 切换到frame
7 driver.switch_to.alert 切换到alert
8 driver.switch_to.active_element 切换到活动元素

通过window_handles以及switch_to.window方法实现不同窗口切换:

self.driver.get('https://www.baidu.com')
        self.driver.find_element_by_link_text('新闻').click()
        handles = self.driver.window_handles
        while 1:    #往复切换
            for handle in handles:
                self.driver.switch_to.window(handle)
                sleep(2)

第十一课–WebElement核心方法和属性的使用

测试网站:https://sahitest.com/demo/
元素属性

# 属性 属性描述
1 element.id 元素id
2 element.tag_name 标签名称(input)
3 element.size 元素宽高
4 element.rect 宽高以及坐标
5 element.text 文本内容

没有value的属性

元素方法

# 方法 方法描述
1 element.send_keys() 输入框中输入内容
2 element.clear() 清空内容
3 element.click() 按钮或者超链接点击
4 element.get_attribute() 获得元素属性值(type、text、value)
5 element.is_selected() 是否被选中(返回true、false)
6 element.is_enabled() 是否可用(返回true、false)
7 element.is_displayed() 是否显示(返回true、false)
8 element.value_of_css_property() css属性值(font、color)

第十二课–form表单操作步骤

form表单的流程:

  1. 定位表单元素
  2. 输入测试值
  3. 判断表单元素属性
  4. 获得表单元素属性
  5. 提交表单进行验证

代码举例
本地建立html界面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>form表单事例</title>
</head>
<body>
<form action="javascript:alert('提交成功')">
    Username:<input type = 'text' name = 'username' id = 'username'><br/>
    Password:<input type = 'password' name = 'password' id = 'password'><br/>
    <input type="submit" value="submit" id="submit">
</form>
</body>
</html>

获取本地建立的html界面并打开

    def __init__(self):
        self.driver = webdriver.Chrome()
        #os.path.abspath(__file__)  当前文件的路径
        #os.path.dirname(path)  当前路径的文件所在的文件夹
        path = os.path.dirname(os.path.abspath(__file__))
        file_path = 'file:///' + path + '/formex.html'
        self.driver.get(file_path)

进行form的系列操作

username = self.driver.find_element_by_id('username')
        username.send_keys('wqq')
        password = self.driver.find_element_by_id('password')
        password.send_keys('123456')
        sleep(2)
        print(username.get_attribute('value'))   #获取元素属性,可以进行校验
        print(password.get_attribute('value'))
        self.driver.find_element_by_id('submit').click()
        sleep(2)
        self.driver.switch_to.alert.accept()  #     进入alert界面后选择接受后,关闭alert
        sleep(2)
        username.clear()  #清空输入框
        password.clear()
        self.driver.quit()

第十三课-- checkbox和ratiobutton定位技巧

checkbox-多选框,定位到之后,可以先判断一下是否已经选择,以防已经选择再click一下就取消选择了

swimming = self.driver.find_element_by_name('swimming')
if not swimming.is_selected():
   swimming.click()

ratio-单选框

gender:<input type="radio" name="gender" value="male"><input type="radio" name="gender" value="female"><br/>

可以发现那么是一样的,所以元素定位后返回的是一个集合,ratio没有判断是否被选中的属性,所以可以根据下标判断选中哪个

gender = self.driver.find_elements_by_name('gender')
        gender[0].click()

第十四课-select操作

select-下拉框,分位单选和多选
单选

城市:
    <select name="provide" id="provide">
        <option value="bj">Beijing</option>
        <option value="sd">Shandong</option>
        <option value="sh">Shanghai</option>
    </select>

多选,区别在于加一个multiple参数

城市:
    <select name="provide" id="provide" multiple>
        <option value="bj">Beijing</option>
        <option value="sd">Shandong</option>
        <option value="sh">Shanghai</option>
    </select>

select定位需要两步,先找到下拉框元素,然后定义成Select类型

se = self.driver.find_element_by_id('provide')
select = Select(se)
# 方法/属性 方法/属性描述
1 select.select_by_value(‘sd’) 根据值选择
2 select.select_by_index(0) 根据索引下标选择(下标从0开始)
3 select.select_by_visible_text(‘Shanghai’) 根据界面显示文本选择
4 select.deselect_all() 取消选择所有
5 select.deselect_by_index(1) 根据索引下标取消选择
6 select.deselect_by_value(‘sd’) 根据值取消选择
7 select.deselect_by_visible_text(‘Shanghai’) 根据界面显示文本取消选择
8 select.options 所有选项
9 select.all_selected_options 所有被选中的选项
10 select.first_selected_option 第一个被选中的选项

属性8、9返回的是一个list,需要通过循环输出,展示内容使用option.text

第十五课–弹框处理(alert、confirm、prompt)

页面弹框有三种:

  • alert:用来提示
  • confirm:用来二次确认
  • prompt:输入内容
# 方法/属性 方法/属性描述 适用弹窗
1 accept() 接受 alert、confirm、prompt
2 dismiss() 取消 alert(右上角取消)、confirm(右上角以及取消按钮)、prompt(右上角取消以及取消按钮)
3 text 显示弹框内容 alert、confirm、prompt
4 send_keys(‘20’) 输入内容 prompt

弹窗元素定位到后,需要切换到弹窗界面,再进行后续操作

self.driver.find_element_by_id('alert').click()  #元素定位
alert = self.driver.switch_to.alert #切换到弹窗

注:confirm、prompt的切换到弹窗也是使用self.driver.switch_to.alert

第十六课-- Selenium的三种的等待方式

在UI自动化测试中,必然会遇到环境不稳定、网络慢的情况,这时不做任何处理的话代码会由于没有找到元素而报错;另外一种情况就是页面使用ajax异步加载机制;这时就要用到wait,而在Selenium中,一共有三种等待方式。

# 等待方式 优点 缺点
1 time.sleep(2) 脚本调试过程中,方便快捷 python自带模块的time的sleep方式进行等待,虽然可以自定义等待时间,但是当网络条件良好时,依旧会按照预设的时间继续等待,导致整个项目的自动化时间无限长。不建议使用
2 self.driver.implicitly_wait(10) 隐式等待实际是设置了一个最长的等待时间,如果在规定时间内页面加载完成,则执行下一步;否则一致等待到时间结束,然后执行下一步。 隐式等待在整个driver周期都起作用,在最开始这只一次就可以了 Javascript一般都是放在body的最后进行加载,实际这个页面的元素已经加载完毕,我们却还在等待全部页面加载结束,也会导致时间很长
3 WebDriverWait(driver=self.driver,timeout=10) 显式等待,可以设置等待到什么条件后执行下一步,在任何地方都可以设置

WebDriverWait介绍

  • Selenium提供的显式等得模块引入路径
  • 导入from selenium.webdriver.support.wait import WebDriverWait
  • WebDriverWait参数
    poll_frequency和 ignored_exception参数有需要可以随意设置
wait = WebDriverWait(driver=self.driver,timeout=10)
# 参数 参数说明
1 driver 传入WebDriver事例
2 timeout 设置超时时间,等待的最长时间
3 poll_frequency 调用until或者until_not中的方法的间隔时间,默认是0.5s
4 ignored_exceptions 忽略异常,默认是None
  • 有两种方法until与until_not
# 参数 参数说明
1 method 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False
2 message 如果超时,跑出TimeoutException,将message传入异常

获取当前界面的内容

from selenium.webdriver.support import expected_conditions as EC


wait = WebDriverWait(driver=self.driver,timeout=10)  #定义等待参数
wait.until(method=EC.title_is('百度一下,你就知道'),message='')  #循环到是true

等待条件下一课详细讲解

第十七课–selenium等待条件

使用以下等待条件需要提前导入一个python自带的模块,from selenium.webdriver.support import expected_conditions as EC

# 等待条件 说明 返回结果
1 EC.title_is() 判断title,是否出现 布尔
2 EC.title_contains() 判断title,是否包含某些字符 布尔
3 EC.presence_of_element_located((By.ID, ‘div2’)) 判断某个元素是否被加到了dom树里,并不代表该元素一定可见 WebElement
4 EC.visibility_of_element_located((By.ID, ‘div2’)) 判断某个元素是否被添加到了dom里并且可见,宽和高都大于0 WebElement
5 EC.visibility_of(self.driver.find_element_by_id(‘btn’)) 判断元素是否可见,如果可见久返回这个元素 WebElement
6 EC.presence_of_all_elements_located() 判断是否至少有1个元素存在于dom树中 列表
7 EC.visibility_of_any_elements_located() 判断是否至少有一个元素在页面中可见 列表
8 EC.text_to_be_present_in_element() 判断指定的元素中是否包含了预期的字符串 布尔
9 EC.text_to_be_present_in_element_value() 判断指定元素的属性值中是否包含了预期的字符串 布尔
10 EC.frame_to_be_available_and_switch_to_it() 判断该frame是否可以switch进去 布尔
11 EC.invisibility_of_element_located() 判断某个元素是否存在于dom或者不可见 布尔
12 EC.element_to_be_clickable() 判断某个元素中是否可见并且是enable的,代表可点击 布尔
13 EC.staleness_of() 等待某个元素从dom树中移除 布尔
14 EC.element_to_be_selected() 判断某个元素是否被选中了,一般用在下拉列表 布尔
15 EC.element_selection_state_to_be() 判断某个元素的选中状态是否符合预期 布尔
16 EC.element_located_selection_state_to_be() 判断某个元素的选中状态是否符合预期 布尔
17 EC.alert_is_present() 判断页面上是否存在alert alert

dom树-这个元素不一定能看到,可能是被隐藏

第十八课-- 鼠标和键盘的操作

Selenium中的鼠标和键盘事件被封装在ActionChains类中,正确的使用方法,先事例化,再使用,执行用到perform()

action = ActionChains(self.driver)
action.double_click(btn).perform()

鼠标、键盘操作方法

# 方法 介绍
1 click(on_element=None) 单击鼠标左键
2 click_and_hold(on_element=None) 点击鼠标左键,不松开
3 content_click(on_element=None) 点击鼠标右键
4 double_click(on_element=None) 双击鼠标左键
5 drag_and_drop(source,target) 拖拽到某个元素然后松开
6 drag_and_drop_by_offset(source,xoffset,yoffset) 拖拽到某个坐标然后放开
7 action.key_down(value, element=None) 按下键盘上某个见
8 action.key_up(value, element=None) 松开某个键
9 action.move_by_offset(xoffset, yoffset) 鼠标从当前位置移动到某个坐标
10 action.move_to_element(to_element) 鼠标从当前位置移动到某个元素
11 action.move_to_element_with_offset(to_element, xoffset, yoffset) 鼠标从当前位置移动到距某个元素(左上角坐标)多少距离的位置
12 action.release(on_element=None) 在某个元素位置松开鼠标左键
13 action.send_keys(*keys_to_send) 发送某个键到当前焦点的元素
14 action.send_keys_to_element(element, *keys_to_send) 发送某个键到指定的元素
15 perform() 执行上面方法的动作

对于键盘的操作,还需要引入Keys模块,包含键盘上的按钮kw.send_keys(Keys.CONTROL,'a'),意思是Control+a

第十九课-- Selenium执行JavaScript脚本

WebDriver又两个方法来执行JavaScript

  • execute_script 同步执行
  • execute_async_script 异步执行

举例
alert弹框

    def test1(self):
        self.driver.get("http://www.baidu.com")
        self.driver.execute_script("alert('test')")
        sleep(2)
        self.driver.switch_to.alert.accept()
        sleep(2)
        self.driver.quit()

返回页面title

    def test2(self):
        self.driver.get("http://www.baidu.com")
        js = 'return document.title'  #返回title
        title = self.driver.execute_script(js)
        print(title)
        sleep(2)
        self.driver.quit()

改变组建样式-未成功

    def test3(self):
        self.driver.get("http://www.baidu.com")
        sleep(2)
        #改变组件样式
        js = 'var q = document.getElementById("kw");q.style.border="2px solid red"'
        self.driver.execute_script(js)
        sleep(2)
        self.driver.quit()

界面滚动条拉到最下面

    def test4(self):
        self.driver.get("http://www.baidu.com")
        sleep(2)
        self.driver.find_element_by_id('kw').send_keys('selenium')
        self.driver.find_element_by_id('su').click()
        sleep(2)
        js = 'window.scrollTo(0,document.body.scrollHeight)'
        self.driver.execute_script(js)
        sleep(2)
        self.driver.quit()

第二十课 捕获屏幕

# 方法 方法描述
1 self.driver.save_screenshot(filename) 获取当前屏幕截图并保存为指定文件,filename指保存的文件名或者图片的文件名
2 self.driver.get_screenshot_as_base64() 获取当前屏幕截图base64位编码字符串
3 self.driver.get_screenshot_as_file(file_path) 获取当前屏幕截图,参数是保存路径
4 self.driver.get_screenshot_as_png() 获取当前屏幕截图的二进制数据

在实际项目中,常常或是用当前时间来命名文件,代码如下

st = strftime("%Y-%m-%d-%H-%M-%S",localtime(time()))  #获取当前时间
file_name = st+'.png'
path = os.path.abspath('screenshot')
file_path = path + '/' + file_name  #图片存放位置在screenshot文件夹下面
self.driver.get_screenshot_as_file(file_path)

第二十一课–WebDriver定位frame、iframe

frame标签有frame set、frame、iframe三种,frameset跟其他标签没有区别,不会影响正常定位,而frame、iframe对selenium定位而言是一样的

# 方法 方法描述
1 self.driver.switch_to.frame(reference) 切换frame,reference是传入参数,用来定位frame,可以传入id、name、index以及webelement
2 self.driver.switch_to.default_content() 返回主文档,焦点移到主文档,不能再访问frame中的内容
3 self.driver.switch_to.parent_frame() 返回父文档,可以访问框架外部

事例代码

    def test_frame(self):
        self.driver.get('https://sahitest.com/demo/framesTest.htm')
        sleep(2)
        top = self.driver.find_element_by_name('top')
        self.driver.switch_to.frame(top) #先进入到frame窗口再进行窗口内操作
        self.driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[1]').click()
        sleep(3)
        self.driver.switch_to.default_content()  #焦点回到主文档
        sleep(3)
        second = self.driver.find_element_by_xpath('/html/frameset/frame[2]')
        sleep(2)
        self.driver.switch_to.frame(second)
        self.driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[1]').click()
        sleep(2)
        self.driver.quit()

补充内容-- PyAutoGUI

PyAutoGUI是一个图形用户界面自动化工具,通过屏幕xy坐标系统确认目标位置,控制鼠标和键盘发送虚拟击键和鼠标点击,完成点击按钮、填写表单等操作。常用在常规方法定位不到元素的情况。
需要安装PyAutoGUI插件

# 方法 方法描述
1 pyautogui.position() 确认鼠标当前位置
2 pyautogui.moveTo(x=None, y=None[, duration=t]) 移动
3 pyautogui.mouseDown()、pyautogui.mouseUp()、pyautogui.click()、pyautogui.doubleClick()、pyautogui.rightClick()、pyautogui.middleClick() 点击
4 pyautogui.dragTo(x=None, y=None[, duration=t]) 拖动
5 pyautogui.typewrite(x=None, y=None[, duration=t]) 控制键盘
element = self.driver.find_element_by_id('agree')
rect = element.rect  #元素所在位置
pyautogui.click(rect['x']+10,rect['y']+130)  #点击位置内容

元素位置返回的是一个字典类型

方法 描述
self.driver.maximize_window() 窗口放大全屏命令

你可能感兴趣的:(selenium,python,chrome)