【软件测试】自动化测试常用函数 -- 详解

一、WebDriver API

一个简单自动化脚本的构成:

脚本解析

  • # coding = utf-8
    from selenium import webdriver
    import time
    browser = webdriver.Firefox()
    time.sleep(3)
    browser.get("http://www.baidu.com")
    time.sleep(3)
    browser.find_element_by_id("kw").send_keys("selenium")
    time.sleep(3)
    browser.find_element_by_id("su").click()
    browser.quit()
防止乱码,在编辑器里面可以不用加,因为编辑器默认的就是  UTF-8  模式。
  • coding = utf-8
导入 webdriver 工具包,这样就可以使用里面的  API
  • from selenium import webdriver
获得被控制浏览器的驱动,这里是获得  Firefox  的,当然还可以获得  Chrome  浏览器,不过要想使这一段代码有效,必须安装相应的浏览器驱动。
  • browser = webdriver.Firefox()
通过元素的  ID  定位想要操作的元素,并且向元素输入相应的文本内容 。
  • browser.find_element_by_id("kw").send_keys("selenium")
通过元素的  ID  定位到元素,并进行点击操作。
  • browser.find_element_by_id("su").click()
退出并关闭窗口。
  • browser.quit()

browser.close() 也可以关闭窗口。

两者的区别是:close 方法关闭当前的浏览器窗口,quit 方法不仅关闭窗口,还会彻底的退出 WebDriver,释放与 driver server 之间的连接。所以简单来说 quit 是更加彻底的 closequit 会更好的释放资源。


1、元素的定位

对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象。一个对象就是一个人一样,他会有各种的特征(属性),比如我们可以通过一个人的身份证号,姓名,或者他住在哪个街道、楼层、门牌找到这个人。那么一个对象也有类似的属性,我们可以通过这些属性找到这对象。

注意:不管用那种方式,必须保证页面上该属性的唯一性。

web 自动化测试的操作核心是能够找到页面对应的元素,然后才能对元素进行具体的操作。

WebDriver 提供了一系列的对象定位方法,常用的有以下几种:

  • id
  • name
  • class name
  • link text
  • partial link text
  • tag name
  • xpath
  • css selector

我们可以看到,一个百度的输入框,可以用这么多种方式去定位。


(1)cssSelector(常用)

CSS(Cascading Style Sheets)是一种语言,它被用来描述 HTML 和 XML 文档的表现。

CSS 使用选择器来为页面元素绑定属性。这些选择器可以被 Selenium 用作另外的定位策略。

CSS 的比较灵活可以选择控件的任意属性,上面的例子中,find_element_by_css_selector("#kw") 通过 find_element_by_css_selector( ) 函数,选择取百度输入框的 id 属性来定义。

CSS 的获取可以用 Chrome 的 F12 开发者模式中 Element-右键-copy-copy selector 来获取。

css 选择语法:

  • id 选择器:#id
  • 类选择:class
  • 标签选择:标签名
  • 后代选择器:父级选择器、子级选择器

选择器的功能:选中页面中指定的标签元素。

选择器的种类分为基础选择器和复合选择器,常见的元素定位方式可以通过 id 选择器和子类选择器来进行定位。

定位百度首页的 “百度热搜” 元素,可以使用通过 id 选择器和子类选择器进行定位:#s-hotsearch-wrapper > div

“搜索输入框元素”:#kw

“百度一下按钮”:#su

若要获取页面多个元素时,可以使用 find_elements:

注意:因为自动化打开的页面是未登录状态,而我们手动打开的百度网页可能是有登录态的,二者页面可能不同,可能造成无法正确打印信息。


A. id 定位

id 是页面元素的属性,我们最常用元素定位方式,但是不是所有的元素都有 id 的。如果一个元素有 id 属性,那么一般在整个页面是唯一的。所以我们一般可以用 id 来唯一的定位到这个元素。

通过前端工具,例如 Edge 浏览器的 F12,找到了百度输入框的属性信息,如下:

<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">

属性 id=”kw” 通过 find_element_by_id("kw") 函数就可以定位到百度输入框。


(2)name 定位

如果这个元素有 name,并且元素的 name 命名在整个页面是唯一的,那么我们可以用 name 来定位这个元素。

用上面百度输入框的例子,其中元素的属性 name=”wd” 通过 find_element_by_name("wd") 函数同样也可以定位到百度输入框。


(3)tag name 定位和 class name 定位

从上面的百度输入框的属性信息中,我们看到,不单单只有 id 和 name 两个属性, 比如 class 和 tag name(标签名)。

input 就是一个标签的名字,可以通过 find_element_by_tag_name("input") 函数来定位,class="s_ipt" 通过 find_element_by_class_name("s_ipt") 函数定位百度输入框。

注意 :不是所有的元素用 tag name  或者 class name 来定位元素,首先要保证该元素的这两种属性在页面上是唯一的,才能够准确的定位。

(4)XPath 定位(重点)(常用)

A. 什么是 XPath

Cover page | xpath | W3C standards and drafts | W3C

XML 路径语言,不仅可以在 XML 文件中查找信息,还可以在 HTML 中选取节点。

xpath 使用路径表达式来选择 xml 文档中的节点。

B. XPath 基础教程

W3Schools Online Web Tutorials


相对路径:/html/head/title(不常用)

绝对路径: 

  • 相对路径+索引://form/span[1]/input
  • 相对路径+属性值://input[@class="s_ipt"]
  • 相对路径+通配符://*[@*="su"]
  • 相对路径+文本匹配://a[text()="新闻"]

XPath 是一种在 XML 文档中定位元素的语言。因为 HTML 可以看做 XML 的一种实现,所以 Selenium 用户可是使用这种强大语言在 Web 应用中定位元素。

XPath 扩展了上面 id 和 name 定位方式,提供了很多种可能性。

XPATH 的获取可以用 Chrome 的 F12 开发者模式中 Element-右键-copy-copy xp。

//*[@id="kw"]

  • 获取 HTML 页面所有的节点://*


  • 获取 HTML 页面指定的节点://[指定节点]
//ul:获取 HTML 页面所有的 ul 节点
//input:获取 HTML 页面所有的 input 节点

  • 获取⼀个节点中的直接子节点:/
//span/input

  • 获取⼀个节点的父节点:..
//input/..:获取 input 节点的父节点

  • 实现节点属性的匹配:[@...]


  • 使用指定索引的方式获取对应的节点内容

注意:xpath 的索引是从 1 开始的。

百度首页通过://div/ul/li[3] 定位到第三个百度热搜标签

更便捷的生成 selector/xpath 的方式:右键选择复制 "Copy selector/xpath"

注意 :元素的定位方法必须唯⼀。

既然可以手动复制 selector/xpath 的方式,为什么还有了解语法?

手动复制的 selector / xpath 表达式并不一定可以满足上面的唯一性的要求,有时候也需要手动的进行修改表达式。


css 选择器和 xpath 选择器哪个更好? 

css 选择器定位元素效率更高。


(5)link text 定位

有时候不是一个输入框也不是一个按钮,而是一个文字链接,我们可以通过链接内容,也就是 link text 来定位。

注意:链接内容必须这个页面唯一,否则会报错。


(6)Partial link text 定位

通过部分链接定位,这个有时候也会用到,我还没有想到很好的用处。拿上面的例子,我可以只用链接的一部分文字进行匹配:


二、操作测试对象

前面讲到了不少知识都是定位元素,定位只是第一步,定位之后需要对这个元素进行操作。是鼠标点击还是键盘输入,或者清除元素的内容,或者提交表单等。这个取决于定位元素需要进行的下一步操作。

Webdriver 中比较常用的操作对象的方法有下面几个:

  • click 点击对象。
  • send_keys 在对象上模拟按键输入
  • clear 清除对象输入的文本内容。
  • submit 提交。
  • text 用于获取元素的文本信息
  • get_attribute 获得属性值。

1、click 点击 / 提交对象

click() # 用于点击一个按钮

页面上任意元素都可以进行点击操作。


2、sendKeys 模拟按键输入

键盘上可以输入的内容都能填入。

sendKeys("")
# send_keys("xx") 用于在一个输入框里输入 xx 内容


3、clear 清除文本内容

输入文本后又想换一个新的关键词,这里就需要用到 clear()。

clear() 用于清除输入框的内容,比如百度输入框里默认有个 请输入关键字” 的信息,再比如我们的登陆框一般默认会有 “账号”、“密码” 这样的默认信息。clear 可以帮助我们清除这些信息。

连续的 sendKeys 会将多次输入的内容拼接在一起,如果想要重新输入,需要使用清除方法:


4、submit 提交表单

打开百度搜索页面,按钮 百度一下” 元素的类型 type=“submit”,所以把百度一下的操作从 click 换成 submit 可以达到相同的效果:

driver.find_element_by_id("su").submit()
  • 如果点击的元素放在 form 标签中,此时使用 submit 实现的效果和 click 是一样的。
  • 如果点击的元素放在非 form 标签中,此时使用 submit 报错。

5、text 获取元素文本

如何判断获取到的元素对应的文本是否符合预期呢?

获取元素对应的⽂本并打印⼀下。

getText()

“百度一下” 在这里是作为元素属性值,而不是文本信息。

不应该是获取文本信息,而是获取属性值:

注意 :文本和属性值不要混淆了,获取属性值需要使用方法: getAttribute(" 属性名称 ")。

6、title 获取当前页面标题 & current_url 获取当前页面 URL

getTitle()
​
getCurrentUrl()

适用场景:页面元素可点击跳转的情况下,用来检测跳转的结果是否为正确的。


三、等待(重点)

通常代码执行的速度比页面渲染的速度要快,如果避免因为渲染过慢出现的自动化误报的问题呢?

可以使用 selenium 中提供的三种等待方法。


1、强制等待

添加休眠非常简单,我们需要引入 time 包,就可以在脚本中自由的添加休眠时间了,这里的休眠指固定休眠。
import time
time.sleep() # 单位:秒
# 当调用该方法时,程序会直接阻塞,等待指定秒数后继续执行后面的代码

  • 优点:使用简单,调试的时候比较有效。
  • 缺点:影响运行效率,浪费大量的时间。 

2、隐式等待

隐式等待是⼀种智能等待,它可以规定在查找元素时,在指定时间内不断查找元素。如果找到则代码继续执行,直到超时没找到元素才会报错。

通过添加 implicitly_wait() 方法就可以方便的实现智能等待。implicitly_wait(30) 的用法比 time.sleep() 更智能,后者只能选择一个固定的时间的等待,而前者可以在一个时间范围内智能的等待。

隐式等待的生命周期:隐式等待作用域整个脚本的所有元素。即只要 driver 对象没有被释放掉(driver.quit()),隐式等待就一直生效。

  • 优点:智能等待,作用于全局

隐式地等待并非一个固定的等待时间,当脚本执行到某个元素定位时,如果元素可以定位,则继续执行;如果元素定位不到,则它以轮询的方式不断的判断元素是否被定位到。直到超出设置的时长。若等待指定秒数后还是查找不到元素,则报错。

隐式等待扫描的是整个页面的元素,页面中所有的元素都被加载到之后才去执行后续的代码。


3、显示等待

显示等待也是一种智能等待在指定超时时间范围内只要满足操作的条件就会继续执行后续代码

# new WebDriverWait(driver, Duration.ofSeconds(3)).until($express)
# $press:涉及到selenium.support.ui.ExpectedConditions包下的ExpectedConditions类
# 返回值:boolean

# 示例:
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 2)
wait.until(EC.invisibility_of_element((By.XPATH, '//*[@id="2"]/div/div/div[3]/div[1]/div[1]/div')))

ExpectedConditions 预定义方法的一些示例:

  • title_is(title):检查页面标题的期望值。
  • title_contains(title):检查标题是否包含区分大小写的子字符串的期望值。
  • visibility_of_element(locator)用于检查元素的期望是可见的并已启用,以便我们可以单击它。
  • invisibility_of_element(locator):用于检查元素的不可见性。
  • visibility_of_element_located(locator, str]):用于检查元素是否存在于页面的 DOM 上的期望值。
  • visibility_of(element):检查已知存在于页面 DOM 上的元素是否可见的期望。
  • alert_present():检查是否出现弹窗。(可以等待隐式等待(无法等待弹窗,因为弹窗不是页面的元素,无法通过页面元素来定位到弹窗)无法处理的问题)
  1. 优点:显示等待是智能等待,可以自定义显示等待的条件,操作灵活。
  2. 缺点:写法复杂。

显示等待相较于隐式等待的好处:

隐式等待和显示等待一起使用效果如何呢?

不建议这么做。混合隐式和显示等待可能会导致不可预测的等待时间。

但是强制等待可以任意配合隐式等待或显示等待来使用。

重复多次,设置 10 秒的隐式等待和 15 秒的显示等待导致 20 秒后发生超时:


四、窗口

打开一个新的页面之后获取到的 title 和 URL 仍然还是前一个页面的。当我们手工测试的时候,我们可以通过眼睛来判断当前的窗口是什么,但对于程序来说它是不知道当前最新的窗口应该是哪一个的。

对于程序来说,它如何来识别每一个窗口呢?

每个浏览器窗口都有一个唯一的属性句柄(handle)来表示,我们就可以通过句柄来切换。


1、切换窗口

  • 获取当前页面句柄:driver.current_window_handle
  • 获取所有页面句柄:driver.windowhandles

  • 通常情况下会打开两个标签页来实现标签页的切换测试,多个标签页切换到某一个标签页的场景在测试中不常见。
  • 更多时候是输入对应页面的链接在当前标签页下进行测试。


2、窗口设置大小

仅作了解即可,在自动化脚本执行过程中通常测试人员不关注页面的变化。


3、屏幕切换

我们的自动化脚本⼀般部署在机器上自动的去运行,当自动化运行出现了报错,仅仅通过终端的错误提示给到的有用信息是一定的,若能将当时的页面变化截图抓拍下来,记录当时的错误场景,能更好的定位问题并解决问题。

指定图片存储路径(需要提前创建好):

如果多次运行,由于图片给定的名称是固定的,那么历史的图片会被覆盖。

如何让我们每次生成的图片都是唯一的呢,如何将我们的历史图片都保存下来?

需要让我们每次生成的图片对应的名称都不一样,最好通过保存当前图片的时间来作为其名称。


4、关闭窗口

driver.close(); # 退出一个窗口

driver.quit(); # 退出浏览器

注意:窗口关闭后 driver 要重新定义。


五、弹窗

弹窗是在页面是找不到任何元素的,这种情况怎么处理?
使用 Selenium 提供的 alert 接口。

1、警告弹窗 + 确认弹窗

(1)警告弹窗

 出现了弹窗,页面其他元素也无法定位:

页面出现了弹窗,必须先处理弹窗之后才能定位到页面的元素。

  1. 切换到弹窗。
  2. 关闭弹窗(点击确认 / 取消)
Alert alert = driver.switchTo.alert();
# 确认
alert.accept()
# 取消
alert.dismiss()

# 注意:switch_to.alert() 只能处理原生的 alert


(2)确认弹窗

 

  • 确定:

  • 取消:


2、提示弹窗

Alert alert = driver.switchTo.alert();
alert.sendKeys("xxxx");
alert.accept();
alert.dismiss();
  • 输入文本 + 确定:

肉眼看不到在弹窗上输入的文本信息:

  • 输入文本 + 取消:


六、浏览器的操作

1、浏览器最大化

我们知道调用启动的浏览器不是全屏的,这样不会影响脚本的执行,但是有时候会影响我们 观看” 脚本的执行。

browser.maximize_window()

2、设置浏览器宽、高

最大化还是不够灵活,能不能随意的设置浏览的宽、高显示?
当然是可以的。
browser.set_window_size(width, high)

3、浏览器导航

(1)打开网站

// 更⻓的⽅法
driver.navigate().to("https://selenium.dev");

// 简洁的⽅法
driver.get("https://selenium.dev");

(2)浏览器的前进、后退、刷新 

非页面元素,所以需要 selenium 提供的现成的方法:

driver.navigate().back();
driver.navigate().forward();
driver.navigate().refresh();


4、控制浏览器滚动条(重点)

浏览器滚动条的控制需要依靠 js 脚本。


5、浏览器参数设置

(1)设置无头模式

程序在后端运行,界面看不到页面的表现。

自动化打开浏览器默认情况下为有头模式。


(2)设置浏览器加载策略

  options.page_load_strategy = '加载方式';  

 

driver.get 默认情况下等待所有的资源加载完成之后才能继续往下执行,但是实际上主页面加载完成之后就可以继续执行自动化。若一直等待的话可能会造成页面超时、元素找不到等问题。

页面加载方式主要有三种类型:

  1. normal:默认值,等待所有资源下载完成(主体框架、图片、视频等资源)
  2. eager:DOM 访问已准备就绪,但诸如图像的其它资源可能仍在加载(推荐)
  3. none:完全不会阻塞 WebDriver,直接继续往下执行脚本(不推荐)


七、上传文件操作

点击文件上传的场景下会弹窗系统窗口,进行文件的选择。

Selenium 无法识别非 Web 的控件,上传文件窗口为系统自带,无法识别窗口元素。但是可以使用 Sendkeys 来上传指定路径的文件,达到的效果是一样的。

文件上传操作也是比较常见功能之一,上传功能没有用到新有方法或函数,关键是思路。

上传过程一般要打开一个本地窗口,从窗口选择本地文件添加。所以,一般会卡在如何操作本地窗口添加上传文件。

当通过页面元素调起上传的窗口后,文件窗口不能被作为页面元素被选中,此时要解决的问题是:如何定位到弹窗并选中文件呢?

只要定位上传按钮,通过 send_keys() 添加本地文件路径就可以了,可以实现将本地文件夹中的文件上传上来。完整绝对路径和相对路径都可以(注意需要添加转义字符),关键是上传的文件存在。


八、键盘事件

1、键盘按键用法

要使用键盘按键,必须引入  keys 包:
  • from selenium.webdriver.common.keys import Keys
通过  send_keys()  调用按键:
  • send_keys(Keys.TAB) # TAB
  • send_keys(Keys.ENTER) # 回车
  • send_keys(Keys.SPACE) #空格键
  • send_keys(Keys.ESCAPE) #回退键(Esc
  • .....

2、键盘组合键用法

  • send_keys(Keys.CONTROL,'a') #全选(Ctrl+A
  • send_keys(Keys.CONTROL,'c') #复制(Ctrl+C
  • send_keys(Keys.CONTROL,'x') #剪贴(Ctrl+X
  • send_keys(Keys.CONTROL,'v') #粘贴(Ctrl+V

九、鼠标事件

要使用鼠标事件需要导入工具包:
  • from selenium.webdriver.common.action_chains import ActionChains

语法示例如下:

#鼠标拖动事件
ActionChains(driver).move_to_element(element).perform()

ActionChains(driver) 生成用户的行为。所有的行动都存储在actionchains 对象。通过perform()存储的行为。

move_to_element(element) 移动鼠标到一个元素中,menu 上面已经定义了他所指向的哪一个元素。

perform() 执行所有存储的行为。

ActionChains
  • context_click() 右击
  • double_click() 双击
  • drag_and_drop() 拖动
  • move_to_element() 移动

十、定位一组元素

WebDriver 可以很方便的使用 findElement 方法来定位某个特定的对象,不过有时候我们却需要定位一组对象,这时候就需要使用 findElements 方法。

定位一组对象一般用于以下场景:
  • 批量操作对象,比如将页面上所有的checkbox 都勾上。
  • 先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的 checkbox,然后选择最后一个。

十一、多层框架 / 窗口定位

对于一个  web 应用,经常会出现框架( frame ) 或窗口( window )的应用,这也就给我们的定位带来了一定的困难。
  • 定位一个 frame switch_to.frame(name_or_id_or_frame_element)
  • 定位一个窗口 windowswitch_to.window(name_or_id_or_frame_element)

1、多层框架的定位

switch_to.frame(name_or_id_or_frame_element):通过 frame 的 id 或者 name 或者 frame 自带的其它属性来定位框架,这里 switch_to.frame() 把当前定位的主体切换了 frame 里。

switch_to.default_content:从 frame 中嵌入的页面里跳出,跳回到最外面的默认页面中。


2、多层窗口定位

有可能嵌套的不是框架,而是窗口,还有真对窗口的方法:switch_to.window 用法与 switch_to.frame 相同:driver.switch_to.window("windowName")

  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炫酷的伊莉娜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值