Web浏览器控制

一、Web浏览器控制

  • 模拟功能测试中对浏览器的操作:
操作 使用场景
get 打开浏览器 web自动化测试第一步
refresh 浏览器刷新 模拟浏览器刷新
back 浏览器退回 模拟退回步骤
maximize_window 最大化浏览器 模拟浏览器最大化
minimize_window 最小化浏览器 模拟浏览器最小化

实例:

代码:

from selenium import webdriver
import time

# 打开浏览器
def open_browers():
    driver = webdriver.Chrome()
    driver.get("https://ceshiren.com/t/topic/24679")
    time.sleep(2)
    # 刷新浏览器
    driver.refresh()
    # 通过get跳转到baidu
    driver.get("https://www.baidu.com/")
    # 退回操作:返回百度之前的页面
    driver.back()
    # 最大化
    driver.maximize_window()
    # 最小化
    driver.minimize_window()
    #关闭窗口
    driver.quit()

if __name__ == '__main__':
    open_browers()

二、常见控件定位方法

2.1 HTML铺垫

  • 标签:<a>
  • 属性:href
  • 类属性: class
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试人论坛</title>
</head>
<body>
<a href="https://ceshiren.com/" class="link">链接</a>
</body>
</html>

2.2 Selenium八大定位方式

参考教程:Locator strategies | Selenium

  • Selenium常用定位方式:
    • 格式:
      • driver.find_element_by_定位方式(定位元素)
      • driver.find_element(By.定位方式, 定位元素)
    • 两种方式作用一模一样,官方建议使用第二种方式。
方式 描述
class name class 属性对应的值
css selector(重点) css 表达式
id(重点) id 属性对应的值
name(重点) name 属性对应的值
link text 查找其可见文本与搜索值匹配的锚元素
partial link text 查找其可见文本包含搜索值的锚元素。如果多个元素匹配,则只会选择第一个元素。
tag name 标签名称
xpath(重点) xpath表达式

2.2.1 通过ID定位

  • 格式:driver.find_element(By.ID, “ID属性对应的值”)
from selenium import webdriver
from selenium.webdriver.common.by import By
import time

def position_method():
    # 实例化chromedriver
    driver = webdriver.Chrome()
    # 打开网站
    driver.get("http://www.ceshiren.com")
    # 等待一秒
    time.sleep(1)
    # 点击”测试内推“,通过ID定位
    driver.find_element(By.ID, "ember27").click()
    # 等待一秒
    time.sleep(1)

if __name__ == '__main__':
    position_method()

2.2.2 通过NAME定位

  • 格式:driver.find_element(By.NAME, "NAME属性对应的值")
from selenium import webdriver
from selenium.webdriver.common.by import By
import time

def position_method():
    # 实例化chromedriver
    driver = webdriver.Chrome()
    # 打开网站
    driver.get("http://www.baidu.com")
    # 等待一秒
    time.sleep(1)
    # 点击”更多“,通过NAME定位
    driver.find_element(By.NAME, "tj_briicon").click()
    # 等待一秒
    time.sleep(1)

if __name__ == '__main__':
    position_method()

2.2.3 通过CSS_SELECTOR定位

  • 格式:driver.find_element(By.CSS_SELECTOR, "css表达式")
  • 复制绝对定位:
  • 编写表达式。

2.2.4 通过XPATH定位

  • 格式: driver.find_element(By.XPATH, "xpath表达式")
  • 复制绝对定位;
  • 编写 xpath 表达式。

2.2.5 通过LINK定位

  • 格式:driver.find_element(By.LINK_TEXT,"文本信息")

综合练习:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

def position_method():
    # 实例化chromedriver
    driver = webdriver.Chrome()
    # 打开网站
    driver.get("http://vip.ceshiren.com/#/ui_study")
    # 等待一秒
    time.sleep(1)
    # 通过CSS_SELECTOR定位
    driver.find_element(By.CSS_SELECTOR, "#locate_id > a > span")
    # 等待一秒
    time.sleep(1)
    # 通过XPATH定位
    driver.find_element(By.XPATH, '//*[@id="locate_id"]/a/span')
    # 等待一秒
    time.sleep(1)
    # 通过LINK定位
    driver.find_element(By.LINK_TEXT, "元素定位")
    # 等待一秒
    time.sleep(1)

if __name__ == '__main__':
    position_method()

三、强制等待与隐式等待

3.1.1 强制(直接)等待

  • 问题:页面渲染完成之前操作,导致报错。

  • 解决方案:在报错的元素操作之前添加等待。如果没有报错,证明就是页面渲染速度导致的问题;如果依然报错,就可能是别的问题,比如定位错误等。

  • 适用场景:调试代码,临时性添加。

  • 原理:强制等待,线程休眠一定时间。

  • 格式:time.sleep(等待时间)

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

def wait_sleep():
    """
    如果直接执行,不添加任何等待,可能会报错
    """
    driver = webdriver.Chrome()
    driver.get("https://vip.ceshiren.com/#/ui_study/frame")
    # 不加等待,可能会因为网速等原因产生报错
    driver.find_element(By.XPATH, '//*[@id="locate"]/span')
    # 强制等待2秒
    time.sleep(2)

if __name__ == '__main__':
    wait_sleep()


强制等待的问题

  1. 不确定页面的加载时间,可能会因为等待时间过长,而影响用例的执行效率;
  2. 不确定页面的加载时间,可能会因为等待时间过短,导致代码依然会报错。

3.1.2 隐式等待

  • 问题:难以确定元素加载的具体等待时间。

  • 解决方案:针对于寻找元素的这个动作,使用隐式等待添加配置。

  • 适用场景:解决找不到元素的问题,无法解决交互问题。

  • 原理:设置一个等待时间,轮询查找(默认0.5秒)元素是否出现,如果没出现就抛出异常。

  • 格式:driver.implicitly_wait(等待时间)

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

def wait_sleep():
    """
    如果直接执行,不添加任何等待,可能会报错
    """
    driver = webdriver.Chrome()
    driver.get("https://vip.ceshiren.com/#/ui_study/")
    driver.implicitly_wait(1)
    driver.find_element(By.XPATH, '//*[@id="locate"]/span')

if __name__ == '__main__':
    wait_sleep()


隐式等待的注意事项

  1. 在代码一开始运行时就添加隐式等待的配置。因为隐式等待是全局生效,所以在所有的find_element动作之前就要执行此代码;
  2. 隐式等待只能解决元素查找的问题,不能解决元素交互的问题。

隐式等待无法解决的问题

  • 元素可以找到,使用点击等操作,出现报错。
  • 原因:
    • 页面元素加载是异步加载过程,通常html会先加载完成,js、css其后;
    • 元素存在与否是由HTML决定,元素的交互是由css或者js决定;
    • 隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互;
  • 解决方案:使用显式等待。

3.1.3 显示等待

  • 原理:在最长等待时间内,轮询,是否满足结束条件。
  • 适用场景:解决特定条件下的等待问题,比如点击等交互行为。
  • 格式:WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)
    • until需要结合expected_conditions或者自己封装的方法进行使用;
    • expected_conditions的参数传入的都是一个元组,即多一层小括号。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
import time

def wait_sleep():
    """
    如果直接执行,不添加任何等待,可能会报错
    """
    driver = webdriver.Chrome()
    driver.get("https://vip.ceshiren.com/#/ui_study/")
    WebDriverWait(driver, 10).until(expected_conditions.element_to_be_clickable((By.ID, "success_btn")))

    driver.find_element(By.ID, 'success_btn').click()
    time.sleep(2)

if __name__ == '__main__':
    wait_sleep()

四、常见控件交互方法

4.1 元素操作

  • 点击、输入、清空。
    • 点击百度搜索框;
    • 输入”霍格沃兹测试开发”;
    • 清空搜索框中信息。
from selenium import webdriver
from selenium.webdriver.common.by import By
import time


def element_interaction():
    """
    元素的操作:点击、输入、清空
    """
    # 1. 实例化driver方法
    driver = webdriver.Chrome()
    # 2. 打开一个网页
    driver.get("https://www.sogou.com/")
    # 3. 定位到输入框,进行输入操作
    driver.find_element(By.ID, "query").send_keys("霍格沃兹测试开发")
    # 强制等待
    time.sleep(2)
    # 4. 对输入框进行清空
    driver.find_element(By.ID, "query").clear()
    # 强制等待
    time.sleep(2)
    # 5. 再次输入
    driver.find_element(By.ID, "query").send_keys("霍格沃兹测试开发啊")
    # 强制等待
    time.sleep(2)
    # 6. 点击搜索
    driver.find_element(By.ID, "stb").click()


if __name__ == '__main__':
    element_interaction()

4.2 获取元素属性信息

  • 原因:
    • 定位到元素后,获取元素的文本信息,属性信息等。
  • 目的:
    • 根据这些信息进行断言或者调试。
  • 方式:
    • 获取元素文本;
    • 获取元素的属性(html的属性值)。
from selenium import webdriver
from selenium.webdriver.common.by import By
import time


def element_get_attr():
    # 1. 实例化driver
    driver = webdriver.Chrome()
    # 2. 打开网页
    driver.get("https://vip.ceshiren.com/#/ui_study/")
    # 3. 定位一个元素
    web_element = driver.find_element(By.ID, "locate_id")
    # 4. 打印这个元素对象
    # 断点打在想看的对象的下一行
    print(web_element)
    # 5. 获取元素的文本信息
    # 注意:不是每个元素都含有文本信息的
    print(web_element.text)
    # 6. 获取元素的属性信息
    res = web_element.get_attribute("name")
    print(res)

if __name__ == '__main__':
    element_get_attr()


五、自动化测试定位策略

image

5.1 通用Web定位方式

定位策略 描述
class name 通过 class 属性定位元素
css selector 通过匹配 css selector 定位元素
id 通过 id 属性匹配元素
name 通过 name 属性定位元素
link text 通过 text 标签中间的 text 文本定位元素
partial link text 通过 text 标签中间的 text 文本的部分内容定位元素
tag name 通过 tag 名称定位元素
xpath 通过 xpath 表达式匹配元素

5.2 选择定位器通用原则

  1. 与研发约定的属性优先(class属性:[name=‘locate’]);
  2. 身份属性ID、NAME(web定位);
  3. 复杂场景使用组合定位;
    ①XPATH,CSS;
    ②属性动态变化(ID、TEXT);
    ③重复元素属性(ID、TEXT、CLASS);
    ④父子定位;
  4. JS定位。

5.3 Web弹框定位

  • 场景
    • web 页面 alert 弹框;
  • 解决:
    • web 需要使用 driver.switchTo().alert() 处理。

5.4 下拉框/日期控件定位

  • 场景:
    • <input>标签组合的下拉框无法定位;
    • <input>标签组合的日期控件无法定位;
  • 解决:
    • 面对这些元素,我们可以引入 JS 注入技术来解决问题。

5.5 文件上传定位

  • 场景:
    • input 标签文件上传;
  • 解决:
    • input 标签直接使用 send_keys()方法。