UI自动化测试重点思考(上)--元素定位/验证码/测试框架

UI自动化测试重点思考--元素定位

  • Selenium定位元素
    • selenium中如何判断元素是否存在?
      • 定位页面元素
        • webdriver打开页面
        • id定位
        • name定位
        • class_name定位
        • tag_name 定位
        • xpath定位
        • css_selector定位
        • link_text 定位
        • partial_link 定位
        • 总结
    • selenium中元素定位的难点?
  • Selenium验证码识别
    • 自动化测试如何处理验证码?
      • 01 简单验证码思路和代码实现
      • 02 复杂验证码思路和代码实现
    • 验证码识别的函数怎么写?
  • pytest测试框架
    • 编写规则
    • pytest标记
      • 创建test_02.py和test_03.py
      • 显式指定函数名
          • 格式
        • 显示制定
      • 模糊匹配函数名
          • 格式
      • 使用pytest.mark在函数上进行标记
        • 格式
        • 内置标记
    • 参数化测试(数据驱动测试)DDT思想
    • pytest fixture
      • 定义
      • 示例
    • pytest的up和down
    • allure测试报告

Selenium定位元素

selenium中如何判断元素是否存在?

定位页面元素

以我们熟知的 CSDN 为例,我们进入首页,按 【F12】 进入开发者工具。红框中显示的就是页面的代码,我们要做的就是从代码中定位获取我们需要的元素。
在这里插入图片描述

webdriver打开页面

想要定位并获取页面中的信息,首先要使用 webdriver 打开指定页面,再去定位。

from selenium import webdriver
# Chrome浏览器
driver = webdriver.Chrome()
driver.get('https://www.csdn.net/')

执行上面语句后会发现,浏览器打开 CSDN 主页后会马上关闭,想要防止浏览器自动关闭,可以添加下面代码。

# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)# 将option作为参数添加到Chrome中
driver = webdriver.Chrome(chrome_options=option)

这样将上面的代码组合再打开浏览器就不会自动关闭了。

from selenium import webdriver# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)# 注意此处添加了chrome_options参数
driver = webdriver.Chrome(chrome_options=option)
driver.get('https://www.csdn.net/')
id定位

标签的 id 具有唯一性,就像人的身份证,假设有个 input 标签如下。

<input id="toolbar-search-input" autocomplete="off" type="text" value="" placeholder="Python难在哪里?">

id="toolbar-search-input":定义了该元素的唯一标识符为 “toolbar-search-input”。这使得在HTML文档中可以通过这个标识符来识别和操作这个特定的输入框。
autocomplete="off":禁用了浏览器的自动填充功能,即不会提供输入建议。
type="text":指定了输入框的类型为文本输入框,用户可以在其中输入任意文本
value="":指定了输入框的初始值为空。
placeholder="Python难在哪里?":为输入框设置了一个占位符,当输入框为空时,显示此文本,提示用户输入的内容。

我们可以通过 id 定位到它,由于 id 的唯一性,我们可以不用管其他的标签的内容。

driver.find_element_by_id("toolbar-search-input")
name定位

name 指定标签的名称,在页面中可以不唯一。假设有个 meta 标签如下

<meta name="keywords" content="CSDN博客,CSDN学院,CSDN论坛,CSDN直播">

我们可以使用 find_element_by_name 定位到 meta 标签。

driver.find_element_by_name("keywords")
class_name定位

class 指定标签的类名,在页面中可以不唯一。假设有个 div 标签如下

<div class="toolbar-search-container">

我们可以使用 find_element_by_class_name 定位到 div 标签

driver.find_element_by_class_name("toolbar-search-container")
tag_name 定位

每个 tag 往往用来定义一类功能,所以通过 tag 来识别某个元素的成功率很低,每个页面一般都用很多相同的 tag ,比如:<div>、<input> 等。这里还是用上面的 div 作为例子。

<div class="toolbar-search-container">

我们可以使用 find_element_by_class_name 定位到 div 标签。

driver.find_element_by_tag_name("div")
xpath定位

xpath 是一种在 XML 文档中定位元素的语言,它拥有多种定位方式,下面通过实例我们看一下它的几种使用方式。

<html><head>...<head/><body><div id="csdn-toolbar"><div class="toolbar-inside"><div class="toolbar-container"><div class="toolbar-container-left">...</div><div class="toolbar-container-middle"><div class="toolbar-search onlySearch"><div class="toolbar-search-container"><input id="toolbar-search-input" autocomplete="off" type="text" value="" placeholder="Python难在哪里?">

根据上面的标签需要定位 最后一行 input 标签,以下列出了四种方式,xpath 定位的方式多样并不唯一,使用时根据情况进行解析即可。

# 绝对路径(层级关系)定位
driver.find_element_by_xpath("/html/body/div/div/div/div[2]/div/div/input[1]")
# 利用元素属性定位
driver.find_element_by_xpath("//*[@id='toolbar-search-input']"))
# 层级+元素属性定位
driver.find_element_by_xpath("//div[@id='csdn-toolbar']/div/div/div[2]/div/div/input[1]")
# 逻辑运算符定位
driver.find_element_by_xpath("//*[@id='toolbar-search-input' and @autocomplete='off']")
css_selector定位

CSS 使用选择器来为页面元素绑定属性,它可以较为灵活的选择控件的任意属性,一般定位速度比 xpath 要快,但使用起来略有难度。
CSS 选择器常见语法:

选择器方法例子描述
#idID选择器#toolbar-search-input {}选择 id 属性为 ‘toolbar-search-input’ 的元素。
*通用选择器* {}选择文档中所有的元素。
element元素选择器input {}选择指定类型的元素,比如 <input> 元素。
element > element子元素选择器div > input {}选择作为 div 元素的直接子元素的 input 元素。
element + element相邻兄弟选择器div + input {}选择与 div 元素相邻的 input 元素。
[attribute=value]属性选择器[type='text'] {}选择具有指定属性和值的元素,比如 type 为 ‘text’ 的元素。

举个简单的例子,同样定位上面实例中的 input 标签

driver.find_element_by_css_selector('#toolbar-search-input')
driver.find_element_by_css_selector('html>body>div>div>div>div>div>div>input')
link_text 定位

link 专门用来定位文本链接,假如要定位下面这一标签。

<div class="practice-box" data-v-04f46969="">加入!每日一练</div>

我们使用 find_element_by_link_text 并指明标签内全部文本即可定位。

driver.find_element_by_link_text("加入!每日一练")
partial_link 定位

partial_link 翻译过来就是“部分链接”,对于有些文本很长,这时候就可以只指定部分文本即可定位,同样使用刚才的例子。

<div class="practice-box" data-v-04f46969="">加入!每日一练</div>

我们使用 find_element_by_partial_link_text 并指明标签内部分文本进行定位。

driver.find_element_by_partial_link_text("加入")
总结
序号方法名描述
1find_element_by_id通过 ID 属性定位单个元素
2find_element_by_name通过名称属性定位单个元素
3find_element_by_xpath通过 XPath 表达式定位单个元素
4find_element_by_link_text通过链接文本定位单个元素
5find_element_by_partial_link_text通过部分链接文本定位单个元素
6find_element_by_tag_name通过标签名称定位单个元素
7find_element_by_class_name通过类名定位单个元素
8find_element_by_css_selector通过 CSS 选择器定位单个元素
9find_elements_by_id通过 ID 属性定位多个元素
10find_elements_by_name通过名称属性定位多个元素
11find_elements_by_xpath通过 XPath 表达式定位多个元素
12find_elements_by_link_text通过链接文本定位多个元素
13find_elements_by_partial_link_text通过部分链接文本定位多个元素
14find_elements_by_tag_name通过标签名称定位多个元素
15find_elements_by_class_name通过类名定位多个元素
16find_elements_by_css_selector通过 CSS 选择器定位多个元素

selenium中元素定位的难点?

  • 在 PyAutoGUI 中,绝对定位元素的方法是使用屏幕坐标来定位元素,而不是像 Selenium WebDriver 那样使用 HTML 元素属性。用PyAutoGUI 定位一个绝对位置的元素并进行操作(所有的定位都定位不到)

Selenium验证码识别

自动化测试如何处理验证码?

01 简单验证码思路和代码实现

在这里插入图片描述

1.截取整个页面
2.获得验证码坐标数据
3.根据坐标数据进行抠图
4.使用pytesseract模块进行验证

02 复杂验证码思路和代码实现

在这里插入图片描述

第三方api实现,showapirequest,里面也有使用方法,是基于AI识别的功能,可以处理图片上有横线干扰的验证码

验证码识别的函数怎么写?

1、我们明确使用 ddddocr 模块和 pi
模块,然后将整个登录页面先截图保存,然后确定对应的验证码图片的左上坐标和右下角坐标,再根绝这两个坐标去抠图并存为另一张图片,最后使用
ddddocr 的 classification 方法去对图片做验证码识别,最后识别出来的验证码就写到对应的 input 框中 2、实际上
pil 模块用来截图,ddddocr 模块用来做图片识别

from PIL import Image
import ddddocrdef recognize_captcha(image):"""对验证码图片进行识别:param image: 验证码图片:return: 识别结果"""# 1. 预处理(例如:调整大小、灰度化等操作)image = image.resize((100, 50))  # 假设调整大小为 100x50gray_image = image.convert('L')  # 将图片转换为灰度图像# 2. 图像识别ocr = ddddocr.DdddOcr()captcha_text = ocr.classification(gray_image)# 3. 返回结果return captcha_text# 使用示例
image_path = 'captcha.png'  # 假设验证码图片的文件名为 captcha.png
captcha_image = Image.open(image_path)
result = recognize_captcha(captcha_image)
print("识别结果:", result)

pytest测试框架

编写规则

在这里插入图片描述

pytest标记

创建test_02.py和test_03.py

  • 创建一个test_02.py,代码如下:
import pytestdef test_01():print('hello')@pytest.mark.do
def test_add():print('happy')def test_02():print('fun')
  • 创建test_03.py
import pytestclass TestMark():def test_01(self):print('hello')@pytest.mark.testdef test_add(self):print('happy')def test_02(self):print('fun')

显式指定函数名

格式

显式指定函数名,通过::标记。

显示制定

例如:在test_02.py中执行test01函数

D:\pythonProject\my_selenium_project\testcases\pytest>pytest -v -s  test_02.py::test_01
======================================================================== test session starts ========================================================================
platform win32 -- Python 3.7.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- d:\python3.7.6\python.exe
cachedir: .pytest_cache
rootdir: D:\pythonProject\my_selenium_project\testcases\pytest, configfile: pytest.ini
collected 1 item                                                                                                                                                     test_02.py::test_01 hello
PASSED========================================================================= 1 passed in 0.01s =========================================================================

例如:在test_03.py中执行test01方法,这个就需要写上classname,不然找不到报错。

D:\pythonProject\my_selenium_project\testcases\pytest>pytest -v -s  test_03.py::test_01
======================================================================== test session starts ========================================================================
platform win32 -- Python 3.7.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- d:\python3.7.6\python.exe
cachedir: .pytest_cache
rootdir: D:\pythonProject\my_selenium_project\testcases\pytest, configfile: pytest.ini
collected 0 items                                                                                                                                                    ======================================================================= no tests ran in 0.01s =======================================================================
ERROR: not found: D:\pythonProject\my_selenium_project\testcases\pytest\test_03.py::test_01
(no name 'D:\\pythonProject\\my_selenium_project\\testcases\\pytest\\test_03.py::test_01' in any of [<Module test_03.py>])

写成pytest -v -s test_03.py::TestMark::test_01即可

D:\pythonProject\my_selenium_project\testcases\pytest>pytest -v -s  test_03.py::TestMark::test_01
======================================================================== test session starts ========================================================================
platform win32 -- Python 3.7.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- d:\python3.7.6\python.exe
cachedir: .pytest_cache
rootdir: D:\pythonProject\my_selenium_project\testcases\pytest, configfile: pytest.ini
collected 1 item                                                                                                                                                     test_03.py::TestMark::test_01 hello
PASSED========================================================================= 1 passed in 0.01s =========================================================================

模糊匹配函数名

格式

使用-k选项标识。例如在test_03.py中,找含有add的方法

D:\pythonProject\my_selenium_project\testcases\pytest>pytest -k add test_03.py
======================================================================== test session starts ========================================================================
platform win32 -- Python 3.7.6, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: D:\pythonProject\my_selenium_project\testcases\pytest, configfile: pytest.ini
collected 3 items / 2 deselected / 1 selected                                                                                                                        test_03.py .                                                                                                                                                   [100%]================================================================== 1 passed, 2 deselected in 0.01s ==================================================================

使用pytest.mark在函数上进行标记

格式
@pytest.mark.mark_name
内置标记
标记描述
pytest.mark.skip跳过测试函数
pytest.mark.skipif根据条件跳过测试函数
pytest.mark.parametrize参数化测试函数
pytest.mark.timeout设置测试函数的超时时间
pytest.mark.usefixtures指定测试函数使用的夹具
pytest.mark.filterwarnings过滤测试函数中的警告信息
pytest.mark.dependency指定测试函数之间的依赖关系
pytest.mark.run控制测试函数的运行次数和顺序
pytest.mark.parametrize_plus参数化测试函数,并指定参数的类型和顺序
pytest.mark.slow将测试函数标记为较慢的测试
pytest.mark.serial将测试函数标记为串行执行的测试

例如:

import pytestdef test_01():print('hello')@pytest.mark.skip()
def test_add():print('happy')def test_02():print('fun')if __name__ == '__main__':pytest.main(['-s', '-v','test_02.py'])

执行结果:

============================= test session starts =============================
collecting ... collected 3 itemstest_02.py::test_01 PASSED                                                 [ 33%]hellotest_02.py::test_add SKIPPED (unconditional skip)                          [ 66%]
Skipped: unconditional skiptes_t02.py::test_02 PASSED                                                 [100%]fun======================== 2 passed, 1 skipped in 0.02s =========================

参数化测试(数据驱动测试)DDT思想

知乎文章参考

pytest fixture

定义

在这里插入图片描述

示例

# test_example.py
import pytest# 定义一个夹具,用于返回一个固定的字符串
@pytest.fixture
def greeting():return "Hello, Pytest!"# 使用夹具进行测试
def test_greeting(greeting):assert greeting == "Hello, Pytest!"# 定义一个需要用到夹具的测试函数
def get_length(string):return len(string)# 使用多个夹具进行测试
def test_string_length(greeting):length = get_length(greeting)assert length == 13  # "Hello, Pytest!" 的长度为 13

在这里插入图片描述

pytest的up和down

在这里插入图片描述

allure测试报告

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/297775.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

典型病例(第二期):血糖18.3,小便多且泡沫难消,滋阴补肾效果显著

案例分享&#xff1a; 患者廖先生&#xff0c;男&#xff0c;43岁 主诉&#xff1a;身体明显特别消瘦&#xff0c;血糖检测达到18.3&#xff0c;患者口干口渴&#xff0c;小便频繁&#xff0c;且带有很难消散的泡沫&#xff0c;疲倦乏力&#xff0c;多食易饥&#xff0c;每天…

MySQL 主从复制架构搭建及其原理

前言 系统的性能瓶颈一般出现在数据库上&#xff0c;以 mysql 为例&#xff0c;如果存在高并发的写请求&#xff0c;势必会有锁表&#xff0c;锁数据行的情况发生&#xff0c;这时候如果有读请求刚好访问到被锁的数据&#xff0c;那么读请求会阻塞&#xff0c;直到写请求处理完…

前端三剑客 —— CSS (第六节)

目录 内容回顾&#xff1a; 弹性布局属性介绍 案例演示 商品案例 布局分析 登录案例 网格布局 内容回顾&#xff1a; 变量&#xff1a;定义变量使用 --名称&#xff1a;值&#xff1b; 使用变量&#xff1a; 属性名&#xff1a;var&#xff08;--名称&#xff09;&a…

爬虫实战三、PyCharm搭建Scrapy开发调试环境

#一、环境准备 Python开发环境以及Scrapy框架安装&#xff0c;参考&#xff1a;爬虫实战一、Scrapy开发环境&#xff08;Win10Anaconda&#xff09;搭建 PyCharm安装和破解&#xff0c;参考&#xff1a;爬虫实战二、2019年PyCharm安装&#xff08;激活到2100年&#xff09; …

基于ArgoCD和Testkube打造GitOps驱动的Kubernetes测试环境

本文介绍了一项新工具&#xff0c;可以基于Gitops手动或者自动实现Kubernetes集群应用测试&#xff0c;确保集群的健康状态与Git仓库定义的一致。原文: GitOps-Powered Kubernetes Testing Machine: ArgoCD Testkube 简介&#xff1a;GitOps 云原生测试面临的挑战 现代云原生应…

SQLite的架构(十一)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite下一代查询规划器(十&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 介绍 本文档介绍SQLite库的架构。 这里的信息对那些想要了解或 修改SQLite的内部工作原理。 接口SQL 命令处理器虚拟机B-树…

PHP 插值搜索(Interpolation Search)

给定一个由 n 个均匀分布值 arr[] 组成的排序数组&#xff0c;编写一个函数来搜索数组中的特定元素 x。 线性搜索需要 O(n) 时间找到元素&#xff0c;跳转搜索需要 O(? n) 时间&#xff0c;二分搜索需要 O(log n) 时间。 插值搜索是对实例二分搜索的改进&#xff0c;…

Api网关-使用Grafana可视化Apisix指标

文章目录 前言一、Apisix部署二、安装配置Grafana1. 安装Grafana2. 设置中文3. 启动4. 登录5. 启停命令5.1 启动和停止5.2 启禁用开机自启动5.3 查看状态 三、安装配置prometheus1. 安装2. 配置服务3. 启动4. 登录5. prometheus启停命令5.1 启动和停止5.2 启禁用开机自启动5.3 …

element-ui breadcrumb 组件源码分享

今日简单分享 breadcrumb 组件的源码实现&#xff0c;主要从以下三个方面&#xff1a; 1、breadcrumb 组件页面结构 2、breadcrumb 组件属性 3、breadcrumb 组件 slot 一、breadcrumb 组件页面结构 二、breadcrumb 组件属性 2.1 separator 属性&#xff0c;分隔符&#xff…

钉钉事件订阅前缀树算法gin框架解析

当钉钉监测到发生一些事件&#xff0c;如下图 此处举例三个事件user_add_org、user_change_org、user_leave_org&#xff0c;传统的做法是&#xff0c;我们写三个if条件&#xff0c;类似下图 这样字符串匹配效率比较低&#xff0c;于是联想到gin框架中的路由匹配算法&#xff0…

【大数据存储】实验4 NoSQL数据库

实验4 NoSQL数据库 NoSQL数据库的安装和使用实验环境&#xff1a; Ubuntu 22.04.3 Jdk 1.8.0_341 Hadoop 3.2.3 Hbase 2.4.17 Redis 6.0.6 mongdb 6.0.12 mogosh 2.1.0 Redis 安装redis完成 新建终端启动redisredis-server新建一个终端redis-cli 建表操作 尝…

随机生成Long全范围数

随机生成Long全范围数 前言实现思路主要代码分区随机生成过程案例&#xff1a;随机生成100个数 朴素的比较总结 前言 使用自带的Random.nextLong()函数生成Long型的长整数&#xff0c;范围比较小&#xff0c;如下图。100个随机数没看见10以内的数字。所以考虑实现随机化生成大…

012——LED模块驱动开发(基于I.MX6uLL)

目录 一、 硬件原理图 二、 驱动程序 三、 应用程序 四、 Makefile 五、操作 一、 硬件原理图 又是非常经典的点灯环节 &#xff0c;每次学新语言第一步都是hello world&#xff0c;拿到新板子或者学习新的操作系统&#xff0c;第一步就是点灯。 LED 的驱动方式&#xff0…

Vue+Element UI 去掉el-input中 文本域 textarea的右下角标

如图&#xff1a;需将右下角 角标去掉 实现代码 ::v-deep .el-textarea {.el-textarea__inner {resize: none; // 去除右下角图标} }

Android JNI基础

目录 一、JNI简介1.1 什么是JNI1.2 用途1.3 优点 二、初探JNI2.1 新建cpp\cmake2.2 build.gradle配置2.3 java层配置2.4 cmake和c 三、API详解3.1 JNI API3.1.1 数据类型3.1.2 方法 3.2 CMake脚本 四、再探JNI 一、JNI简介 1.1 什么是JNI JNI&#xff08;Java Native Interfa…

微信小程序纯CSS实现好看的加载动画

进入下面小程序可以体验效果&#xff1a; WXML: <wxs module"img" src"./loading.wxs"></wxs> <view class"loading-container {{show?:loading-container-hide}}"><view class"loading-mask" wx:if"{{ma…

Springboot传参要求

Web.java(这里定义了一个实体类交Web) public class Web{ private int Page; public int getPage() {return Page;}public void setPage(int page) {Page page;} } 1、通过编译器自带的getter、Setter传参 。只是要注意参数的名字是固定的&#xff0c;不能灵活改变。 传参的…

渗透测试:数据库UDF提权(linux)

目录 开头: 1.UDF提权简介&#xff1a; 1.1共享库文件(UDF文件)指定目录&#xff1a; 版本特征&#xff1a; 操作系统版本&#xff1a; 2.靶场UDF提权复现 提权前提 1.要有一个高权限的MySQL的账号 ​编辑 2.MySQL的权限配置secure_file_priv为空 3.必须有存放UDF文件的…

webrtcP2P通话流程

webrtcP2P通话流程 在这里&#xff0c;stun服务器包括stun服务和turn转发服务。信令服服务还包括im等功能 webrtc多对多 mesh方案 适合人数较少的场景 webrtc多对多 mcu方案 &#xff08;multipoint control point&#xff09;将上行的视频/音频合成&#xff0c;然后分发。…

【零基础C语言】编译和链接

1.翻译环境和运行环境 翻译环境&#xff1a;将源代码转化为可执行的机器指令 运行环境&#xff1a;用于执行机器指令 1.1 翻译环境 翻译环境由编译和链接两大过程构建&#xff0c;编译又可以分为三大过程&#xff1a; 【1】预处理(预编译) 【2】编译 【3】汇编 不同的.c文件经…