# UI自动化测试阶段目标
  • 1.掌握使用Selenium实现Web自动化测试的流程和方法,并且能够完成自动化测试脚本的编写。
  • 2.掌握使用Appium实现移动自动化测试的流程和方法,并且能够完成自动化测试脚本的编写。
  • 3.掌握如何通过PyTest管理用例脚本,并使用Allure生成HTML测试报告。
  • 4.掌握使用PO模式来设计自动化测试代码的架构。
  • 5.掌握使用数据驱动来实现自动化测试代码和测试数据的分离。
  • 6.掌握使用logging来实现日志的收集。

认识UI自动化测试

UI自动化介绍

  • UI:User Interface,简称UI,用户界面是系统和用户之间进行交互和信息交换的媒介
  • UI 自动化测试:使用程序、脚本对系统界面体现的功能和数据信息展示等进行的测试技术
  • 分类:
    • Web自动化
    • APP自动化

为什么需要UI自动化

  • 大量的版本回归

  • 手工回归效率低

  • 测试工程师价值得不到体现

  • 体现价值:测试人员需要从重复的回归测试抽离出来投入更重要功能模块测试中

  • 目的 : 提高测试效率,保证软件产品质量

  • 自动化测试能解决什么问题:

    • 1.回归测试:重复性高/执行频率高
    • 2.压力测试:多用户/手工测试不好实现
    • 3.兼容性测试:测试条件多/手工执行效率差

前置条件

  • 项目需要实施UI自动化测试需要满足以下前置条件:
    • 项目需要回归测试
    • 项目需要实现自动化的功能模块需求变更不频繁
      • 一般只实现核心功能模块
      • 页面功能也展示信息变更
    • 项目周期要长
      • Time:功能测试:UI自动化测试= 1 : 3

执行时机

  • 项目UI界面还没有,能编写脚本吗?项目刚提测时,能执行吗??

    • 不能
      • 无UI无法确认UI界面信息,脚本无法编写
      • 功能不稳定,问题多,UI 界面可能发生变化
      • 无法执行脚本调试
  • 项目实施UI自动化测试的时机:

    • 一般情况下在手工测试完成之后

      • 版本或项目功能趋于稳定
    • 注意 : 部分公司存在独立的自动测试小组,可能在项目刚开始时就已经同步启动UI自动化测试工作,例如:环境部署、计划制定等… …

自动化的优缺点

  • 互联网项目现状:

    • 快速送代
    • 文档缺失
  • 项目实现UI自动化测试之后:

    • 节省人力成本:回归测试工作由脚本代替人去执行, 较少的时间内运行更多的测试用例;
    • 提高回归测试效率:脚本执行测试速度更快,自动化脚本可以重复运行
    • 提高测试质量:一旦自动化脚本库完善后测试执行过程更标准和准确 , 较少人为的错误
    • 构建测试数据
    • 克服手工测试的局限性
    • 做为项目文档辅助
  • UI自动化测试劣势:

    • 对测试人员要求提高
    • 前期投入成本大
    • 对项目要求高
    • 缺点:
      • 自动化测试实现步骤要依赖手工实现
      • UI 界面布局一类的问题,自动化测试无法解决
      • 功能测试逻辑复杂的/设计第三方交互的都太适合使用自动化测试实现

自动化测试工具Selenium

学习目标

  • 了解常见的自动化测试工具
  • 理解Selenium特点
  • 知道Selenium核心组件和其作用

自动化测试工具介绍

image-20240118191210729

  • web项目实施自动化:
    • web : python+selenium+unittest
    • app : python+appium+unitest

Selenium 特点

  • 基于web项目回归测试,会考虑:

    • 项目的兼容性:平台、浏览器
  • 基于脚本编写和维护,会考虑:

    • 是否方便迁移
    • 是否可以定制、开发个性功能
    • 编程语言选择
    • 工具本身使用成本
  • Selenium 是一个用于 Web 应用程序的自动化测试工具

  • Selenium特点:

    • 开源软件 : 代码开放可以根据需要来增加工具的某些功能
    • 跨平台 : linux、windows、mac
    • 支持多种浏览器 : 器:Firefox、Chrome、IE、Edge、Opera、Safari等
    • 支持多种语言:Python、Java、C#、JavaScript、Ruby、FHP等
    • 功能强大、成熟稳定 :
      • 目前已经被 google、百度、腾讯等公司广泛使用
      • 能够实现类似商业工具的大部分功能,因为开源性,可实现定制化功能

Selenium 的发展史

image-20240119170308975

Selenium 核心组件

image-20240118191535118

Selenium环境搭建

学习目标

  • 能力独立搭建 Selenium 自动化测试实施环境

环境搭建步骤

环境搭建步骤

  • 所需环境:
    • python 解释器
    • pycharm
    • selenium
    • 浏览器
    • 浏览器驱动
      • 浏览器驱动版本需要和浏览器版本一致
      • 将浏览器驱动版本 chromedriver.exe 复制至 python.exe 所在目录即可(避免再次将 chromedriver.exe 添加 path 变量)

image-20240118191837091

安装Selenium

  • 安装包
    • pip instalselenium
  • 查看包
    • pip show selenium
  • 卸载包
    • pip uninstalselenium

安装浏览器驱动

  • 1、下载浏览器驱动程序:
    • 不同浏览器都有自己独立驱动程序
    • 不同的版本需要下载匹配其版本的驱动程序
      • 浏览器版本要与驱动版本一致,否则运行代码时会报错
  • 2、配置驱动文件环境变量:

入门示例

  • 通过程序启动浏览通过程序启动浏览器,并打开百度首页,暂停3秒,关闭浏览器器,并打开百度首页,暂停3秒,关闭浏览器
    • 通过代码生成的浏览器与系统中自己使用的浏览器不是同一个,代码执行结束后会被销毁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1.导包
import time
from selenium import webdriver

# 2.创建浏览器驱动对象
# Firefox浏览器:
# driver = webdriver.Firefox()
# Chrome浏览器:
driver = webdriver.Chrome()

# 3.打开Web页面
driver.get("http://www.baidu.com/")

# 4.暂停
time.sleep(3)

# 5.关闭驱动对象
driver.quit()

元素定位

学习目标

  • 能运用8种元素定位找到界面元素

为什么要进行元素定位

image-20240118193832163

1
2
3
<input type="text" placeholder="手机号/邮箱" id="username" autocomplete="off">
<input type="password" placeholder="密码" id="username" autocomplete="off">
<input type="text" placeholder="验证码" id="username" autocomplete="off">
  • UI 界面本质上就是HTML直接体现,脚本通过HTML标签信息来找到具体的元素

查看标签信息

  • 浏览器开发者工具 :

    • 就是给专业的web应用和网站开发人员使用的工具,包含了对HTML查看和编辑、Javascript控制台、网络状况监视等功能。

    • 安装:无需安装,浏览器自带

    • 作用:快速定位元素,查看元素信息

image-20240119193216016

元素定位

image-20240119193309595

1
from selenium.webdriver.common.by import By
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# inputTag = driver.find_element_by_id("value")  # 利用ID查找
# 改为:
inputTag = driver.find_element(By.ID, "value")

# inputTags = driver.find_element_by_class_name("value") # 利用类名查找
# 改为:
inputTag = driver.find_element(By.CLASS_NAME, "value")

# inputTag = driver.find_element_by_name("value") # 利用name属性查找
# 改为:
inputTag = driver.find_element(By.NAME, "value")

# inputTag = driver.find_element_by_tag_name("value") # 利用标签名查找
# 改为:
inputTag = driver.find_element(By.TAG_NAME, "value")

# inputTag = driver.find_element_by_xpath("value") # 利用xpath查找
# 改为:
inputTag = driver.find_element(By.XPATH, "value")

# inputTag = driver.find_element_by_css_selector("value") # 利用CSS选择器查找
# 改为:
inputTag = driver.find_element(By.CSS_SELECTOR, "value")

# 总结如下:
from selenium.webdriver.common.by import By

• find_element(By.ID,”loginName”)
• find_element(By.NAME,”SubjectName”)
• find_element(By.CLASS_NAME,”u-btn-levred”)
• find_element(By.TAG_NAME,”input”)
• find_element(By.LINK_TEXT,”退出”)
• find_element(By.PARTIAL_LINK_TEXT,”退”)
• find_element(By.XPATH,”.//*[@id=’Title”])
# 具有名为id的属性和值为loginForm的表单元素
• login_form = driver.find_element_by_xpath("//form[@id='loginForm']")
• find_element(By.CSS_SELECTOR,”[type=submit]”)

ID定位

ID定位

  • 概念:通过元素的id属性来定位元素。
  • 前置:所要定位的元素必须有id属性
  • 方法:
    • driver.find_element_by_id(id属性值) , 旧版本的写法,会报错
    • driver.find_element(By.ID, "userA") , 新版本的写法,使用方法参考案例
  • 方法返回的是什么?
    • 元素对象

image-20240119193540565

案例

  • 使用 ID 定位方式

    • 需求:打开注册A.html页面,完成以下操作

      • 1).使用id定位,输入用户名:admin

      • 2).使用id定位,输入密码:123456

      • 3).3秒后关闭浏览器窗口

    • 分析:

      • ①.创建浏览器驱动
      • ②.打开测试网址
      • ③.定位元素,调用模拟操作方法
      • ④.操作完毕关闭浏览器
    • 注意要使用新版本的写法,旧版本的写法会报错,仅在此做一次提示,后面的案例将采用新版本的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By # 新版本的写法

# 2. 创建浏览器驱动对象
# Firefox浏览器:
# driver = webdriver.Firefox()
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面 (参数为要打开的网页的 ur地址)
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 3.1).使用id定位,输入用户名:admin
# username = driver.find_element_by_id('userA') # 旧版本的写法
username = driver.find_element(By.ID, "userA") # 新版本的写法
username.send_keys('admin')
# 3.2).使用id定位,输入密码:123456
# password = driver.find_element_by_id('passwordA') # 旧版本的写法
password = driver.find_element(By.ID, "passwordA") # 新版本的写法
password.send_keys('123456')

# 4. 3秒后关闭浏览器窗口
time.sleep(3)

# 5. 关闭驱动对象
driver.quit()

Name定位

Name定位

  • 概念:通过元素的name属性来定位元素。

  • 前置:所要定位的元素必须有name属性。

  • 方法:driver.find_element(By.NAME, "userA")

  • 如果匹配多个符合条件的元素对象,返回哪个元素?

    • 第一个元素对象

image-20240119193823096

案例

  • 需求:
    • 打开注册A.html页面,完成以下操作
      • 1).使用name定位,输入用户名:admin
      • 2).使用name定位,输入密码:123456
      • 3).3秒后关闭浏览器窗口
  • 分析:
    • ①.创建浏览器驱动
    • ②.打开测试网址
    • ③.定位元素,调用模拟操作方法
    • ④.操作完毕关闭浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Firefox浏览器:
# driver = webdriver.Firefox()
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 3.1).使用id定位,输入用户名:admin
username = driver.find_element(By.NAME, "userA")
username.send_keys('admin')
# 3.2).使用id定位,输入密码:123456
password = driver.find_element(By.NAME, "passwordA")
password.send_keys('123456')

# 4. 3秒后关闭浏览器窗口
time.sleep(3)

# 5. 关闭驱动对象
driver.quit()

class_name 定位

class_name 定位

  • 概念:通过元素的class_name属性来定位元素。

  • 方法:driver.find_element(By.CLASS_NAME, "telA")

  • class 属性有多个类名,该如何挑选?

    • 只能选择一个其中的一个类名 , 即挑选所要定位的元素所特有一个类名即可

image-20240119194003678

案例

  • 使用 CLASS_NAME 定位方式完成下面操作

  • 需求:

    • 打开注册A.html页面,完成以下操作
      • 1).通过class_name定位电话号码A,并输入:18611111111
      • 2).通过class_name定位电子邮箱A,并输入:123@qq.com
      • 3).3秒后关闭浏览器窗口
  • 分析:

    • ①.创建浏览器驱动
    • ②.打开测试网址
    • ③.定位元素,调用模拟操作方法
    • ④.操作完毕关闭浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Firefox浏览器:
# driver = webdriver.Firefox()
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 3.3) 通过class_name定位电话号码A,并输入:18611111111
te= driver.find_element(By.CLASS_NAME, "telA")
tel.send_keys('18611111111')

# 3.4) 通过class_name定位电子邮箱A,并输入:123@qq.com
mai= driver.find_element(By.CLASS_NAME, "c1")
mail.send_keys("123@qq.com")

# 4. 3秒后关闭浏览器窗口
time.sleep(3)

# 5. 关闭驱动对象
driver.quit()

Tag_name 定位

Tag_name 定位

  • 概念:通过元素的标签名来定位元素。
  • 方法:driver.find_element(By.TAG_NAME, "input")

image-20240119194113979

案例

  • 使用TAG_NAME定位方式完成下面操作

  • 需求:

    • 打开注册A.html页面,完成以下操作
      • 1).使用tag_name定位用户名输入框,并输入:admin
      • 2).3秒后关闭浏览器窗口
  • 分析:

    • ①.创建浏览器驱动
    • ②.打开测试网址
    • ③.使用标签名定位确认符合条件的元素是第几个?
    • ④.操作完毕关闭浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Firefox浏览器:
# driver = webdriver.Firefox()
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 需求 : 使用tag_name定位用户名输入框,并输入:admin
username = driver.find_element(By.TAG_NAME, "input")
username.send_keys('admin')

# 4. 3秒后关闭浏览器窗口
time.sleep(3)

# 5. 关闭驱动对象
driver.quit()
  • 概念:专门用来定位超链接元素(<a>标签)。

  • 方法:driver.find_element_by_link_text(超链接的全部文本内容)

image-20240119194241805

案例

  • 使用Link_Text定位方式完成下面操作

  • 需求:

    • 打开注册A.html页面,完成以下操作
      • 1).使用link_text定位(访问新浪网站)超链接,并点击
      • 2).3秒后关闭浏览器窗口
  • 分析:

    • ①.创建浏览器驱动
    • ②.打开测试网址
    • ③.获取要定位超链接文本类容,用拷贝的形式,定位元素
    • ④.操作完毕关闭浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
```

### partial_link_text 定位

#### partial_link_text 定位

- 使用link_text定位图片标记的元素会有什么问题?
- 代码过长
- 定位不到

- 使用局部文本来定位元素:
- 方法:driver.find_element_by_partial_link_text(超链接的局部文本内容)
- 局部文本:从字符串任意位置开始,一截连续字符集。

![image-20240119194441668](https://s1.vika.cn/space/2024/01/19/c2268c00581345f681e80c047c6e5879)

#### 案例

- 使用Partail_Link_Text定位方式完成下面操作

- 需求:

- 打开注册A.html页面,完成以下操作

- 1).使用partial_link_text定位(访问新浪网站)超链接,并点击

- 2).3秒后关闭浏览器窗口

- 分析:

- ①.创建浏览器驱动

- ②.打开测试网址

- ③.获取要定位超链接文本部分类容(能表示该元素唯一性),用拷贝的形式,定位元素

- ④.操作完毕关闭浏览器

```mysql
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Firefox浏览器:
# driver = webdriver.Firefox()
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 需求 : 使用partial_link_text定位(访问新浪网站)超链接,并点击
driver.find_element(By.LINK_TEXT,'访问 新浪 网站').click()

# 4. 3秒后关闭浏览器窗口
time.sleep(3)

# 5. 关闭驱动对象
driver.quit()

定位一组元素

定位一组元素

  • 含义:定位所有符合条件的元素

  • Return:返回的数据为所有符合条件的元素对象的列表

  • 在定位元素时,如果出现下面的情况:

    • 定位到多个符合条件的元素且所需要定位元素不是第一个
  • 如何从返回的列表中取某一个的元素对象?

    • 定位符合条件的一组元素后,通过下标取指定的元素对象。

案例

  • 需求:

    • 打开注册A.html页面,完成以下操作

      • 1).使用定位一组元素(标签名)定位密码输入框,并输入:123456

      • 2).3秒后关闭浏览器窗口

1
# ...

Xpath定位

认识Xpath定位

  • XMPath 简称,用于在XML文档中查找元素信息的语言。

  • Selenium提供了根据Xpath来查找元素的方法:

    • 方法 : inputTag = driver.find_element(By.XPATH, "value")
    • 策略 :
      • 路径定位
      • 属性定位
      • 属性与逻辑结合
      • 层级与属性结合

路径定位

  • 绝对路径 :

    • 对界面依赖强,不建议使用
    • 概念:从最外层元素到指定元素之间所有经过的元素层级的路径。
    • 表达式写法:绝对路径以 /htm 根节点开始,使用/来分隔元素层级。
  • 相对路径·

    • 概念:从目标定位元素的任意层级的上级元素开始到目标元素所经过的层级的路径。
    • 表达式写法:以//开始,后续每个层级都使用/来分隔。
  • 案例 :

    • 使用 xpath 路径定位策略完成下面操作

    • 需求:

      • 打开注册A.html页面,完成以下操作
        • 1).使用相对路径定位用户名输入框,并输入:admin
        • 2).暂停2s
        • 3).使用绝对路径定位密码输入框,并输入:123
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 需求:
# - 打开注册A.html页面,完成以下操作
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# - 1).使用绝对路径定位用户名输入框,并输入:admin
inputTag = driver.find_element(By.XPATH, "//*[@id='userA']")
inputTag.send_keys("admin")
# - 2).暂停2s
time.sleep(5)

# - 3).使用相对路径定位密码输入框,并输入:123
driver.find_element(By.XPATH, "/html/body/form/div/fieldset/center/p[2]/input").send_keys("123")

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

属性定位

  • 属性定位概念:

    • 利用元素的属性来进行定位
  • 挑选哪个属性来定位呢?

    • 挑选元素所特有的挑选较为常用的:id、name、class、value…
    • 总之:尽量挑选能精准定位到唯一元素的属性
  • 案例 :

    • 需求:打开注册 A.htm页面。完成以下操作:
      • 1). 利用元素的属性信息精准定位用户名输入框,并输入:admin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 需求:打开注册A.html页面。完成以下操作:
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")
# 利用元素的属性信息精准定位用户名输入框,并输入:admin
driver.find_element(By.XPATH, "//input[@placeholder='账号A']").send_keys("admin")

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

属性与逻辑结合

  • 属性与逻辑结合

    • 概念:利用元素的多个属性来进行定位
  • 案例 :

    • 需求:打开注册 A.htm页面。完成以下操作:
      • 1). 利用属性与逻辑结合在输入框输入:admin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 需求:打开注册A.html页面。完成以下操作:
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")
# 利用元素的属性信息精准定位用户名输入框,并输入:admin
driver.find_element(By.XPATH, '//input[@name="userA" and @placeholder="账号A"]').send_keys("admin")

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

层级与属性结合

  • 层级与属性结合
    • 概念:先定位到其父级元素,然后再找到该元素。
  • 案例 :
    • 需求:打开注册 A.htm页面。完成以下操作:
      • 1). 利用层级与属性结合在输入框输入:admin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 需求:打开注册A.html页面。完成以下操作:
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")
# 利用层级与属性结合在输入框输入:admin
driver.find_element(By.XPATH, '//*[@id="p1"]/input').send_keys("admin")

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()
  • 案例 :
    • 需求:打开注册 A.htm页面。完成以下操作:
      • 1). 利用局部属性定位方式定位用户名输入框输入:admin
      • 2). 利用文本定位的方式定位百度超链接,并点击
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
```

#### 案例

- 按要求完成下面的操作流程:
- 1. 打开Tpshop首页;
- 2. 使用Xpath 文本定位策略定位登陆超链接,并点击;
- 3. 使用Xpath 属性定位策略定位用户名输入框,输入:15800000001
- 4. 使用Xpath 属性包含定位策略定位密码输入框,输入:123456
- 5. 使用Xpath 属性与逻辑结合策略定位验证码输入框,输入:8888
- 6. 使用Xpath 层级与属性结合策略定位登陆按钮,并点击;
- 每步操作之后暂停2s

```python

CSS定位

认识CSS定位

  • CSS

    • 概念:(Cascading Style Sheets)是一种语言,用来描述HTML元素的显示样式。
    • 选择器:一种表达式,可以找到HTML中的标签元素。
  • CSS定位

    • 概念:selenium利用选择器定位元素的定位方式。
    • 方法 :
    • 策略 :
      • ID选择器
        • 说明:利用元素ID属性来选择
        • 格式:#id属性值
      • 类选择器
        • 说明:利用元素 class 属性来选择
        • 格式:.class属性值
      • 元素选择器
      • 属性选择器
      • 层级选择器
        • 父子关系
          • 后代关系包含了父子关系,一般只需记忆后代关系即可
          • 概念:据元素的父子关系来选择元素。
          • 表达式写法:element1>element2
        • 后代关系
          • 概念:根据元素的上级元素来选择元素(只要是目标元素上层元素即可)
          • 表达式写法:element1 element2
  • 案例:

    • 需求:打开注册 A.htm页面,完成以下操作
      • 1).使用CSS定位方式中id选择器定位用户名输入框,并输入:admin
      • 2).使用CSS定位方式中属性选择器定位密码输入框,并输入:123456
      • 3).使用CSS定位方式中class选择器定位电话号码输入框,并输入:18600000000
      • 4).使用CSS定位方式中元素选择器定位注册按钮,并点击
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 需求:打开注册A.html页面。完成以下操作:
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")
# 使用CSS定位方式中id选择器定位用户名输入框,并输入:admin
driver.find_element(By.ID, "userA").send_keys("admin")
# 使用CSS定位方式中属性选择器定位密码输入框,并输入:123456
driver.find_element(By.XPATH, "//*[@id='passwordA']").send_keys("123456")
# 使用CSS定位方式中class选择器定位电话号码输入框,并输入:18600000000
driver.find_element(By.CLASS_NAME, "telA").send_keys("18600000000")
time.sleep(5)
# 使用CSS定位方式中元素选择器定位注册按钮,并点击
driver.find_element(By.TAG_NAME, "button").click()
# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()
  • 案例
    • 需求:打开注册A.html页面。完成以下操作:
      • 1).使用CSS定位方式中的层级选择器定位用户名输入框,并输入:admin
1
# ...
  • 案例
    • 需求:打开注册A.html页面。完成以下操作:
      • 1). 利用局部属性定位方式定位用户名输入框输入:admin
1
# ...
  • 案例
    • 使用元素定位的另外一种写法完成下面的操作:
    • 需求:打开注册A.html页面,完成以下操作
      • 1).使用id定位用户名输入框,并输入:admin
      • 2).使用name定位密码输入框,并输入:123456
      • 3).使用class定位电话号码输入框,并输入:18600000000
      • 4).使用标签名定位注册按钮,并点击
1
# ...

案例-刷步数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
driver.get("https://shuabu.org//")

# 3.1 关闭弹窗 .ant-modal-close-x
driver.find_element(By.CLASS_NAME, "ant-modal-close-x").click()

# 3.2 填写账号
username =driver.find_element(By.XPATH,"//input[@placeholder='请输入Zepp Life账号']")
username.send_keys("13838383388")

# 3.3 填写密码
password =driver.find_element(By.XPATH,"//input[@placeholder='请输入Zepp Life密码']")
password.send_keys("12345678aa")

# 3.4 填写运动步数
buShu =driver.find_element(By.XPATH,"//input[@placeholder='1~100000']")
buShu.send_keys("33333")

# 3.5 点击提交
driver.find_element(By.XPATH,"//button[@type='button']").click()

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

交互操作

元素操作和元素信息获取

学习目标

  • 掌握元素操作Api实现模拟手工操作
  • 掌握获取元素信息Api

元素常用操作方法

常用操作方法

image-20240124191828314

  • 要完成测试用例操作步骤:

    • 绿色部分通过元素定位实现
    • 红色部分通过元素操作方法实现
  • 模拟点击 element.click()

  • 模拟输入 element.send_keys(value)

  • 模拟清除 element.clear()

案例

  • 需求:打开注册A.html页面,完成以下操作
    • 1).通过脚本执行输入用户名:admin,密码:123456,电话号码:18611111111,电子邮箱:123@qq.com
    • 2).间隔3秒,修改电话号码为:18600000000
    • 3).间隔3秒,点击【注册】按钮
    • 4).间隔3秒,关闭浏览器
    • 5).元素定位方法不限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
```

## 获取元素信息方法

### 获取元素信息方法

- 场景:执行商品搜索测试步骤后需要验证测试结果

- 获取元素大小 `element.size`

- 获取元素文本 `element.text`

- 获取元素属性值 `element.get_attribute(属性名")`

![image-20240124192223258](https://s1.vika.cn/space/2024/01/24/dcb3c898d80943dcbdcbccd46f2684b9)

- 判断元素是否可见 `element.is_displayed()`
- 判断元素是否可用 `element.is_enabled()`
- 判断元素是否可见 `element.is_displayed()`
- 返回的结果都是Boolean数据:True or False

![image-20240124192435103](https://s1.vika.cn/space/2024/01/24/336e111cd44f489c925ea8ca00fd68b5)

### 案例

- 需求:打开注册A.html页面,完成以下操作
- 1).获取用户名输入框的大小
- 2).获取页面上第一个超链接的文本内容
- 3).获取页面上第一个超链接的地址
- 4).判断页面中的span标签是否可见
- 5).判断页面中取消按钮是否可用
- 6).判断页面中'旅游'对应的复选框是否为选中的状态

```python

浏览器操作

学习目标

  • 掌握对浏览器操作的常用操作方法

浏览器操作

浏览器窗口大小

  • 设置浏览器显示范围 :
    • 窗口最大化 driver.maximize_window()
      • 如果能够在打开页面时,全屏显示页面。就能尽最大可能加载更多的页面元素,提高可定位性
    • 设置窗口大小 driver.set_window_size(width, height)
    • 设置窗口位置 dirver.set_window_position(x, y)
1
2
3
4
5
6
7
8
# 窗口最大化
driver.maximize_window()

# 设置窗口大小
driver.set_window_size(1920, 1080)

# 设置窗口位置
driver.set_window_position(0, 0) # 以屏幕左上角为原点
  • 浏览器显示页面操作 :
    • 后退操作 : dirver.back()
    • 前进操作 : dirver.forword()
    • 刷新页面 : dirver.refresh()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 打开百度
driver.get("http://www.baidu.com")
# 定位搜索框输入内容
driver.find_element(By.ID,"kw").send_keys("高德地图")

# 点击搜索框
driver.find_element(By.ID,"su").click()
time.sleep(2) # 停留 2s

# 后退
driver.back()
time.sleep(2) # 停留 2s

# 前进
driver.forward()
time.sleep(2) # 停留 2s

# 刷新页面
driver.refresh()
time.sleep(2) # 停留 2s

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

案例

  • 需求:
    • 打开注册A.html页面,完成以下操作
      • 1).最大化窗口
      • 2).暂停3s,设置窗口宽度:500px,高度:700px
      • 3).暂停3s,设置窗口位置:x=0px,y=500px
      • 4).暂停3s,点击界面百度超链接
      • 5).暂停3s,返回注册A页面
      • 6).暂停3s,前进到百度页面
      • 7).暂停3s,刷新百度页面
      • 8).暂停3s,关闭浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
```

### 关闭浏览器

- 在测试过程出现多个窗口.只需要关闭其中一个,如何处理?

- 浏览器关闭操作 :

- 关闭当前窗口 `dirver.close() `
- 在没有实现浏览器页面切换操作前,`close()`方法关闭的是原始页面 , 关闭单个页面时使用

- 关闭浏览器 `dirver.quit()`

- 获取浏览器信息 :
- 获取标题 `dirver.title`
- 获取网页地址 `dirver.current_url`

- 当前窗口:创建驱动时第一个打开的窗口,对于当前窗口的元素一般都可以直接定位和操作,如果弹出新的窗口,对于新的窗口元素是不能直接进行操作,需要学习后续的窗口切换。

```python
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 需求:打开注册A.html页面。完成以下操作:
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 点击打开新浪页面
driver.find_element(By.PARTIAL_LINK_TEXT,"访问").click()
time.sleep(2) # 停留 2s

# 关闭前的网页标题
print(driver.title)
# 关闭前的网页的 UR地址
print(driver.current_url)

# 关闭当前窗口
driver.close()

# 4. 5秒后关闭浏览器窗口
# time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

案例

  • 完成下面对浏览器的操作
    • 需求:
      • 打开注册A.html页面,完成以下操作
        • 1).最大化窗口
        • 2).打印当前窗口的标题和地址
        • 3).暂停3s,点击界面访问百度网站超链接
        • 4).暂停3s,再次打印当前窗口的标题和地址
        • 5).暂停3s,关闭当前窗口
        • 6).暂停3s,关闭浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
```

# 页面交互操作

## 学习目标

- 能编写代码来实现各类型下拉框选择
- 能识别弹出框类型并能通过脚本来处理
- 能编写代码控制下拉框进行滑动

## 下拉框

### 认识下拉框

![image-20240124194128059](https://s1.vika.cn/space/2024/01/24/82cb7fb9c0ec49e384ff678984ee8d0f)

- 在页面上面经常遇到上面的交互,该如何进行处理?
- 定位元素后调用点击的操作方法进行选择

### 案例

- 需求:使用‘注册A.html’页面,完成对城市的下拉框的操作:
- 1).选择‘广州’
- 2).暂停2秒,选择‘上海’
- 3).暂停2秒,选择‘北京

```python

Select下拉框

image-20240124194317490

  • Select类实现选项选择只适用于HTML原生态的 <select>+<option>的下拉框。

案例

  • 练习使用 Select 类的方式实现注册A地址选择操作,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
```

## 弹出框

### 认识弹出框

![image-20240124194544524](https://s1.vika.cn/space/2024/01/24/8573e88ba8f74081ace7241f4c43976a)

- 当界面存在弹出框时,必须先处理掉弹出框才能继续其它操作!

- 类型 :
- 自定义弹出框
- 可以直接通过web浏览器开发者工具查看到具体的元素信息
- 通过元素定位后直接可以处理掉·
- JS弹出框
- 通过JS函数实现,通过web浏览器开发者工具无法查看到元素信息
- 常见 JS 弹出框形式:`alert(警告框)`、`confirm(确认框)`、`prompt(提示框)`
- 不能通过元素定位进行处理

### 弹出框处理

![image-20240124194802510](https://s1.vika.cn/space/2024/01/24/eb6313f11713419b9abf06b41417e6d9)

### 案例

- 需求:打开注册A.html页面,完成以下操作:
- 1).点击alert 按钮
- 2).关闭警告框
- 3).输入用户名:admin

```python

滚动条

滚动条处理

滚动条处理

  • 所要操作的元素不在当前展示页,需要滑动滚动条才能找到。
    • 定义Js字符串 js = "window.scrollTo(0,1000)"
    • 执行Js字符串 driver.execute_script(js)

image-20240124194938786

案例

  • 需求:
    • 打开注册A.html页面,完成以下操作
      • 1).暂停2s,控制滚动条滑动到页面最底部
      • 2).暂停2S,点击返回顶部按钮
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
```

# 页面元素特殊操作

## 学习目标

- 能编写脚本控制鼠标模拟右击、悬停手工交互操作

## 鼠标操作

### 常见鼠标操作

![image-20240124195253387](https://s1.vika.cn/space/2024/01/24/df296d7f6f4e4b239afc6ee7260c8b2e)

### 鼠标操作实现步骤

![image-20240124195332092](https://s1.vika.cn/space/2024/01/24/57213067bca2456a9e0a256da6e42820)

```python
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 3.1 打开注册A.html页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 3.2 定位目标元素
username = driver.find_element(By.ID,"userA")

# 3.3 实例化鼠标对象
action = ActionChains(driver)

# 3.4 调用鼠标右键方法 , 鼠标右键只能展示右键菜单内容,而菜单中的元素无法操作
action.context_click(username)

# 3.5 执行鼠标方法
action.perform()

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

鼠标操作练习

  • 练习一
    • 需求:打开注册页面A,模拟鼠标悬停在’注册’按钮上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 3.1 打开注册A.html页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 3.2 定位目标元素
btn = driver.find_element(By.TAG_NAME,"button")

# 3.3 实例化鼠标对象
action = ActionChains(driver)

# 3.4 调用鼠标悬停方法
action.move_to_element(btn) # 该方法执行时,不要动鼠标

# 3.5 执行鼠标方法
action.perform()

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()
  • 练习二
    • 需求:打开注册页面A,在用户名文本框上点击鼠标右键
  • 练习三
    • 需求:1、打开注册A,输入用户名 admin,暂停3秒钟后,双击鼠标左键,选中admin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 3.1 打开注册A.html页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/%E6%B3%A8%E5%86%8CA.html")

# 3.2 定位目标元素
username = driver.find_element(By.ID,"userA")
username.send_keys("admin")
time.sleep(3)

# 3.3 实例化鼠标对象
action = ActionChains(driver)

# 3.4 调用鼠标右键方法 , 鼠标右键只能展示右键菜单内容,而菜单中的元素无法操作
action.double_click(username)

# 3.5 执行鼠标方法
action.perform()


# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

鼠标拖拽操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1. 导入模块
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

# 2. 创建浏览器驱动对象
# Chrome浏览器:
driver = webdriver.Chrome()

# 3. 打开Web页面
# 3.1 打开注册A.html页面
driver.get("file:///E:/203_%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/5.0%E8%AF%BE%E4%BB%B6/5.0%E8%AF%BE%E4%BB%B6/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/UI%E8%87%AA%E5%8A%A8%E5%8C%96V5.0%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99/web%E7%AB%AF%E7%8E%AF%E5%A2%83/web%E8%AF%BE%E5%A0%82%E7%B4%A0%E6%9D%90/web/drop.html")

# 3.2 定位目标元素
red = driver.find_element(By.ID,"div1")
blue = driver.find_element(By.ID,"div2")

# 3.3 实例化鼠标对象
action = ActionChains(driver)

# 3.4 调用鼠标拖拽方法
action.drag_and_drop(red,blue) # 将 red 拖拽到 blue 位置

# 3.5 执行鼠标方法
action.perform()

# 4. 5秒后关闭浏览器窗口
time.sleep(5)

# 5. 关闭驱动对象
driver.quit()

键盘操作(空)

元素等待

学习目标

  • 理解元素等待的概念和作用
  • 能使用元素等待方法来提供脚本运行效率

元素等待

认识元素等待

image-20240124195647691

  • 界面渲染和脚本运行速速那个快?

    • 网络速度慢
    • 电脑配置低
    • 服务器处理请求慢
    • Time.sleep() 影响运行效率
  • 元素等待概念 :

    • 在定位页面元素时如未定位到,会在指定时间内一直等待的过程。
      • 隐式等待
      • 显示等待

隐式等待

隐式等待

image-20240124195922812

  • 隐式等待
    • 定位元素时,如果能定位到元素则直接返回该元素,不触发等待;
    • 如果不能定位到该元素,则间隔一段时间后再去定位元素;
    • 如果在达到最大时长时还没有找到指定元素,则抛出元素不存在的异常 NoSuchElementException。
      • driver.implicitly_wait(timeout)
        • 参数 timeout 为等待最大时长,单位为 s
    • 隐式等待为全局设置(只需要设置一次,就会作用于所有元素)
    • 当隐式等待被激活时,虽然目标元素已经出现了,但是还是会由于当前页面内的其他元素的未加载完成,而继续等待,进而增加代码的执行时长

案例

  • 需求:打开注册A.html页面,完成以下操作
    • 1).最大化窗口
    • 2).使用隐式等待定位延时加载输入框,输入admin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
```

### 显式等待

#### 显式等待

- 显式等待
- 定位指定元素时,如果能定位到元素则直接返回该元素,不触发等待;
- 如果不能定位到该元素,则间隔一段时间后再去定位元素;
- 如果在达到最大时长时还没有找到指定元素,则抛出超时异常常TimeoutException

![image-20240124200440473](https://s1.vika.cn/space/2024/01/24/88c72a7b87ea43b29f4d26c6f4f96579)

- `element = WebDriverWait(driver, 10, 1).until(lambda x: x.find_element_by_id("userA") )`

#### 案例

- 需求:打开注册A.html页面,完成以下操作
- 1).最大化窗口
- 2).使用显示等待定位延时加载输入框,输入admin

```python

隐式等待和显示等待对比

image-20240124200831127

image-20240126132329819

Frame切换

认识frame

image-20240124201156911

  • Frame HTML页面中的一种框架,主要作用是在当前页面中指定区域显示另一页面元素
    • frameset 形式
    • iframe 标签形式

Frame切换方法

image-20240124201324632

多窗口切换

认识多窗口

  • 多窗口 : 在HTML页面中,当点击超链接或者按钮时,有的会在新的窗口打开页面。

image-20240124201456109

多窗口切换方法

多窗口切换方法

  • 窗口切换:selenium 需要通过窗口的句柄来实现窗口的切换!
  • 说明:在浏览器的一个生命周期内(开启到关闭), 任意一个窗口都有唯一的一个句柄值,可以通过句柄值完成窗口切换操作

image-20240124201654615

案例

  • 需求:打开‘注册实例.html’页面,完成以下操作
    • 1). 点击‘注册A页面’链接
    • 2). 在打开的页面中,填写注册信息

切换操作小结

image-20240124201851937

窗口截图

窗口截图

  • UI自动测试统一运行时无人值守

  • 错误信息记录不是十分明确

  • 有截图结合错误信息方便快速分析错误

  • 获取所有窗口句柄 :

    • driver.get_screenshot_as_file(imgpath)
    • imgpath:图片保存路径
      • 若路径包含文件夹,则需要先手动创建文件夹
      • 可以拼接时间戳以防止文件名重复覆盖

案例

  • 需求:打开‘注册A.html’页面,完成以下操作
    • 1). 填写注册信息
    • 2). 截图保存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
```

# 验证码

## 认识验证码

- 一种随机生成的信息(数字、字母、汉字、图片、算术题)等为了防止恶意的请求行为,增加应用的安全性。
- 注意:在自动化测试过程中,必须处理验证码,否则无法继续执行后续测试

![image-20240124202226392](https://s1.vika.cn/space/2024/01/24/ec29c7fefd8f4291a33cb4333a49fa88)

## 验证码处理策略

- 要进行后续业务操就必须登陆,那自动化该如何处理这些验证码操作?
- 去掉验证码、万能验证
- 都是开发来完成
- 万能验证码 : 生产环境和测试环境下采用,必须注意保密不要外泄万能验证码
- 码验证码识别技术
- 成功率不高,验证码种类繁多,不太适合
- 记录cookie

## 认识cookie

![image-20240124202401385](https://s1.vika.cn/space/2024/01/24/1f24f820c6334fd1bf971d6d97c3612e)

- Cookie概念 :
- Cookie是由Web服务器生成的,并且保存在用户浏览器上的小文本文件,它可以包含用户相关的信息。
- Cookie数据格式:键值对组成(python中的字典)
- Cookie产生:客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie 数据
- Cookie使用:当浏览器再次请求该网站时,浏览器把请求的数据和Cookie数据一同提交给服务器,服务器检查该Cookie,以此来辨认用户状态。

## Cookie跳过登陆

![image-20240124202521604](https://s1.vika.cn/space/2024/01/24/d97512cd4af64e01a4d7fdad97920b30)

- Cookie操作方法:
- `driver.get_cookie(name)` 获取指定cookie
- `driver.get_cookies()` 获取本网站所有本地cookies
- `driver.add_cookie(cookie_dict)` 添加cookie
- `cookie_dict` :一个字典对象,必选的键包括:"name" and "value"

## 案例

- 需求:使用cookie实现跳过登录
- 1). 手动登录百度,获取cookie
- 2). 使用获取到的cookie,达到登录目的,然后就可以执行登录之后的操作BDUSS是登录百度后的唯一身份凭证(*.baidu.com),拿到BDUSS就等于拿到帐号的控制权, 通行贴吧、知道、百科、文库、空间、百度云等百度主要产品。

## 总结

- Selenium 常用的基本 Api 学习完成
- 通过不同操作步骤场景脚本编写来巩固学习记忆和理解
- 独立练习课后代码实现确认是否达到学习目标

# PyTest

## 概念

- pytest 是 python 的一种单元测试框架,同自带的 UnitTest 测试框架类似,相比于 UnitTe&t 框架使用起来更简洁,效率更高。
- 在自动化测试中同样充当测试执行的功能!并且可以跟UnitTest互换

## 特点

- 1.非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考
- 2.支持简单的单元测试和复杂的功能测试
- 3.支持参数化
- 4.执行测试过程中可以将某些测试跳过,或者对某些预期失败的Case 标记成失败
- 5.支持重复执行失败的 Case
- 6.支持运行由 Nose,UnitTest 编写的测试 Case
- 7.具有很多第三方插件,并且可以自定义扩展
- 8.方便的和持续集成工具集成

## 安装

```python
# 安装
pip install pytest

# 查看版本号
pytest --version

基本使用

函数形式

1
2
3
4
# 函数形式
def testfunc(): # 要求函数名必须要以 test 开头
"""测试函数"""
print("我是测试函数")
1
2
# 终端执行
pytest -s .\001_打开网页.py
1
2
3
4
5
6
7
8
9
10
11
12
# 另一种执行代码方式 , 直接右键运行 py 文件即可执行
import pytest

# 函数形式
def testfunc(): # 要求函数名必须要以 test 开头
"""测试函数"""
print("我是测试函数")


if __name__ == "__main__":
# 语法 : pytest.main(['-s','文件名.py'])
pytest.main(['-s', '.\001_打开网页.py'])

类形式

1
2
3
4
5
6
7
8
9
10
11
# 类形式
class TestDemo(object): # 测试类名必须要以 Test 开头
"""测试示例类"""

def test_method1(self): # 测试方法名必须要以 Test 开头
"""测试方法1"""
print("测试方法1")

def test_method2(self):
"""测试方法2"""
print("测试方法2")
1
2
# 终端执行
pytest -s .\001_打开网页.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 另一种执行代码方式 , 直接右键运行 py 文件即可执行
import pytest


# 类形式
class TestDemo(object): # 测试类名必须要以 Test 开头
"""测试示例类"""

def test_method1(self): # 测试方法名必须要以 Test 开头
"""测试方法1"""
print("测试方法1")

def test_method2(self):
"""测试方法2"""
print("测试方法2")


if __name__ == "__main__":
# 语法 : pytest.main(['-s','文件名.py'])
pytest.main(['-s', '.\001_打开网页.py'])

特殊方法

  • setup和teardown
    • pytest 在运行自动化脚本的前后会执行两个特殊的方法,分别是setup和teardown。
    • 在执行脚本之前会执行setup方法,在执行脚本之后会执行teardown方法。
    • 有了这两个方法,我们可以在setup中进行获取驱动对象的操作,在teardown中进行关闭驱动对象的操作。

函数级别

  • 运行于测试方法的始末,运行一次测试函数会运行一次setup和teardown。
1
2
3
4
5
6
7
```

#### 类级别方法

- 运行于测试类的始末,在一个测试内只运行一次 setup_class 和 teardown_class,不关心测试类内有多少个测试函数。

```python

函数与类级别同时使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
```

## 配置文件

### 应用场景

- 使用配置文件后可以快速的使用配置的项来选择执行哪些测试模块
- 注意 :
- 1.在 Windows 系统下,pytest 配置文件中,不允许写注释信息
- 2.一个工程内只需要一个 pytest 配置文件,并且需要保证文件名正确
- 3.一般情况,只需要将 pytest 配置文件,置于工程根目录下
- 4.配置有 pytest 配置文件的工程,只需要打开命令行,输入 pytest 指令,即可执行测试

### 使用方式

- 1.项目下新建 scripts 模块
- 2.将测试脚本文件放到 scripts 中
- 3.`pytest` 的配置文件放在自动化项目目录下
- 4.名称为 `pytest.ini`
- 5.命令行运行时会使用该配置文件中的配置
- 6.第一行内容为`[pytest]`

```python
# pytest.ini
...

image-20240127162650190

  • 说明:测试用例文件名/测试类名/测试方法名均为 Test/test 开头

  • 扩展 :指定单个文件/类/方法执行

image-20240127163125076

常用插件

学习目标

  • 1.能够生成 pytest-html 测试报告
  • 2.能够控制 pytest 函数执行的顺序
  • 3.能够掌握 pytest 失败重试

测试报告

应用场景

  • 自动化测试脚本最终执行是通过还是不通过,需要通过测试报告进行体现

安装

  • 使用命令 pip install pytest-html 进行安装

使用

  • 在配置文件中的命令行参数中增加 --html=用户路径/report.html
1
2
# pytest.ini
addopts =-s --html=report/report.html
  • 执行命令 pytest 即可

结果

  • 在项目目录下会对一个 report 文件夹,里面有个 report.html 即为测试报告

控制函数执行顺序

应用场景

现实生活中,如果想下订单,必须先登录,我们可以通过插件的形式来控制函数执行的顺序。

安装

  • 使用命令 : pip install pytest-ordering 进行安装

使用

  • 1.标记于被测试函数,@pytest.mark.run(order=1/2/3/....)
    • #扩展:序号支持正数和负数,以及正负混合
    • #1。纯正数:数越小,优先级越高
    • #2.纯负数:数越小,优先级越高
    • #3.正负混合:正数先按照顺序执行,负数最后执行
  • 2.根据order传入的参数来解决运行顺序
  • 3.order值全为正数或全为负数时,运行顺序:值越小,优先级越高
  • 4.正数和负数同时存在:正数优先级高

失败重试

应用场景

  • 自动化测试脚本可能会使用到网络,如果网络不好可能最终会使脚本不通过。
  • 像这种情况可能并不是脚本本身的问题,仅仅是因为网络忽快忽慢,那么我们可以使用失败重试的插件,当失败后尝试再次运行。
  • 一般情况最终成功可以视为成功,但最好进行进行排查时候是脚本问题。

安装

  • 使用命令 pip install pytest-rerunfailures 进行安装

使用

  • 在配置文件中的命令行参数中增加 --reruns n
    • 说明:正式脚本一般设置不超过3次 , 测试脚本设置1次即可
1
2
# pytest.ini
addopts=-s--reruns 3

高级用法

跳过测试函数

应用场景

  • 同一个软件在不同的设备上可能会有不同的效果,比如,iOS的3dtouch操作是需要6s以上设备支持的,6和6s都可以安装同一款应用,如果设备不支持,那么根本没有必要去测试这个功能。此时,我们可以让这种函数进行跳过。

数据参数化

应用场景

  • 登录功能都是输入用户名,输入密码,点击登录。但登录的用户名和密码如果想测试多个值是没有办法用普通的操作实现的。数据参数化可以帮我实现这样的效果。

方法名

1
2
3
4
5
#数据参数化
#参数:
#argnames:参数名
#argvalues:参数对应值,类型必须为可迭代类型,一般使用list
@pytest.mark.parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
  • 一个参数使用方式
    • 1.argnames 为字符串类型,根据需求决定何时的参数名
    • 2.argvalues 为列表类型,根据需求决定列表元素中的内容
    • 3.在测试脚本中,参数,名字与 argnames 保持一致
    • 4.在测试脚本中正常使用

PO模式

学习目标

  1. 深入理解方法封装的思想
  2. 能够使用方法封装的思想对代码进行优化
  3. 深入理解PO模式的思想
  4. 熟练掌握PO模式的分层思想

存在的问题分析

image-20240124204034512

  • 问题
    •  元素定位的代码对页面特别依赖,一旦页面发生变化所有用到该页面的元素定位代码都需要进行修改
    •  存在大量元素定位代码冗余

认识PO模式

image-20240124204129009

页面对象

image-20240124204325436

  • 编写步骤:
    • 定义页面元素实例属性
      • 根据测试用例场景定义好所要用到的元素的实例属性
    • 定义页面业务实例方法
      • 一个页面可能存在多个业务方法,如登陆页面:登陆、找回密码等
    • 抽取定位信息到实例属性
      • 将元素定位的信息抽离到实例属性中进行统一管理,方便维护

优化封装

image-20240124204405147

  • PO页面定位元素受隐式等待影响
    • 运行效率低:隐式等待依赖于界面的加载
    • 解决方式:给所有的元素等待操作加上显示等待
  • 模拟输入可能受输入框默认值影响输入的测试数据
    • 影响测试结果:输入数据就会变成:默认值+输入数据
    • 解决方式:每个模拟输入之前加上清除动作

元素定位

  • 给所有的元素等待操作加上显育示等待

image-20240124204631447

  • 二次封装
    • 对工具原有提供的方法或函数添加个性化设置的代码,
    • 保障原有作用的情况下加上了个性化功能的封装

image-20240124204656730

模拟输入

  • 所有模拟输入之前添加清除操作

image-20240124204721923

image-20240124204739212

案例

image-20240124204913919

  •  对 pshop 首页进行 PO 封装
  •  通过调用二次封装后元素定位方法和模拟输入的方法实现定位和输入

数据驱动

学习目标

  • 理解数据驱动的作用
  • 知道UI自动化测试数据驱动实现思路

认识数据驱动

数据驱动概念

  • 数据驱动 : 以数据来驱动整个测试用例的执行,也就是测试数据决定测试结果

image-20240124205153731

数据驱动实现方式

image-20240124205306923

  • 常见数据存储方式 :
    • 从文件读取数据,如JSON、excel、xml、txt等格式文件
    • 从数据库中读取数据
    • 调用接口、本地封装代码获取

PO数据驱动实现

组织Tpshop登陆测试数据

image-20240124205502403

封装测试数据读取函数

image-20240124205537292

image-20240124205604581

测试用例参数化引入

image-20240124205632334

数据驱动总结

  • 1、UI自动化测试中数据驱动的核心是:
    • 利用参数化技术使用同样的测试步骤来执行不同的测试数据,验证各种测试情况
    • 将测试数据和测试脚本分离,编写完成操作脚本后,将重点放到数据的维护和构建上
  • 2、数据存储的方式有多种,并不限于 json 文件存储形式,只要最终提供给参数化的数据是符合规定格式的即可。