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 ddddocr

def recognize_captcha(image):
    """
    对验证码图片进行识别
    :param image: 验证码图片
    :return: 识别结果
    """
    # 1. 预处理(例如:调整大小、灰度化等操作)
    image = image.resize((100, 50))  # 假设调整大小为 100x50
    gray_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 pytest

def test_01():
    print('hello')

@pytest.mark.do
def test_add():
    print('happy')

def test_02():
    print('fun')

  • 创建test_03.py
import pytest

class TestMark():
    def test_01(self):
        print('hello')

    @pytest.mark.test
    def 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 pytest

def 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 items

test_02.py::test_01 PASSED                                                 [ 33%]hello

test_02.py::test_add SKIPPED (unconditional skip)                          [ 66%]
Skipped: unconditional skip

tes_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测试报告

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

K8S - Deployment 的版本回滚

当前状态 先看deployment rootk8s-master:~# kubectl get deploy -o wide --show-labels NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES …

武汉星起航:深耕全球市场,拓展国际影响力,共赢未来跨境新篇章

在瞬息万变的跨境电商领域&#xff0c;武汉星起航凭借其敏锐的创新意识和卓越的执行力&#xff0c;为行业注入了新的活力。作为一家追求卓越、勇于创新的企业&#xff0c;武汉星起航深知创新是成功的关键。公司通过不断探索新的商业模式、引入先进技术和优化运营流程&#xff0…

【pycharm】在debug循环时,如何快速debug到指定循环次数

【pycharm】在debug循环时&#xff0c;如何快速debug到指定循环次数 【先赞后看养成习惯】求关注收藏点赞&#x1f600; 在 PyCharm 中&#xff0c;可以使用条件断点来实现在特定循环次数后停止调试。这可以通过在断点处右键单击&#xff0c;然后选择 “Add Breakpoint” -&g…

【精品教程】护网HVV实战教程资料合集(持续更新,共20节)

以下是资料目录&#xff0c;如需下载&#xff0c;请前往星球获取&#xff1a; 01-HW介绍.zip 02-HTTP&Burp课程资料.zip 03-信息收集_3.zip 04-SQL注入漏洞_2.zip 05-命令执行漏洞.zip 06-XSS漏洞.zip 07-CSRF.zip 08-中间件漏洞.zip 09-SSRF.zip 10-XXE.zip 11-Java反序列…

2024 最新版 Proteus 8.17 安装汉化教程

前言 大家好&#xff0c;我是梁国庆。 今天给大家带来的是目前 Proteus 的最新版本——Proteus 8.17。 时间&#xff1a;2024年4月4日 获取 Proteus 安装包 我已将本篇所使用的安装包打包上传至百度云&#xff0c;扫描下方二维码关注「main工作室」&#xff0c;后台回复【…

Netty客户端发送数据给服务器的两个通道(1)

EventLoopGroup group new NioEventLoopGroup();// 设置的连接group。 Bootstrap bootstrap new Bootstrap().group(group).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) // 超时时间。 .channel(NioSocketChannel.class).handler(new ChannelInitializer() { Ov…

【stm32】I2C通信协议

【stm32】I2C通信协议 概念及原理 如果我们想要读写寄存器来控制硬件电路&#xff0c;就至少需要定义两个字节数据 一个字节是我们要读写哪个寄存器&#xff0c;也就是指定寄存器的地址 另一个字节就是这个地址下存储寄存器的内容 写入内容就是控制电路&#xff0c;读出内容就…

vue 浅解watch cli computed props ref vue slot axios nexttick devtools说明使用

Vue.js 是一个强大的前端框架&#xff0c;它提供了很多有用的功能和工具。你提到的这些特性&#xff08;watch、cli、computed、props、ref、slot、axios、nextTick、devtools&#xff09;在 Vue 中各自扮演着不同的角色。下面我会逐一解释这些特性如何在 Vue 中使用&#xff1…

蓝桥杯每日一题:约数个数(质因数)

题目描述&#xff1a; 输入 n 个整数&#xff0c;依次输出每个数的约数的个数。 输入格式 第一行包含整数 n。 第二行包含 n 个整数 ai。 输出格式 共 n 行&#xff0c;按顺序每行输出一个给定整数的约数的个数。 数据范围 1≤n≤1000, 1≤ai≤10^9 输入样例&#xff…

分布式任务调度框架XXL-JOB

1、概述 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 官方文档&#xff1a;https://www.xuxueli.com/xxl-job/#%E4%BA%8C%E3%80%81%E5%BF%AB%E9%80%9F%E…

c# wpf Template ContentTemplate

1.概要 1.1 定义内容的外观 2.2 要点分析 2.代码 <Window x:Class"WpfApp2.Window1"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schem…

深入浅出 -- 系统架构之分布式系统底层的一致性

在分布式领域里&#xff0c;一致性成为了炙手可热的名词&#xff0c;缓存、数据库、消息中间件、文件系统、业务系统……&#xff0c;各类分布式场景中都有它的身影&#xff0c;因此&#xff0c;想要更好的理解分布式系统&#xff0c;必须要理解“一致性”这个概念。 其实关于…

Day83:服务攻防-开发组件安全JacksonFastJson各版本XStreamCVE环境复现

目录 J2EE-组件Jackson-本地demo&CVE 代码执行 (CVE-2020-8840) 代码执行 (CVE-2020-35728&#xff09; J2EE-组件FastJson-本地demo&CVE FastJson < 1.2.24 FastJson < 1.2.47 FastJson < 1.2.80 (利用条件比较苛刻) J2EE-组件XStream-靶场&CVE …

redis进阶入门配置与持久化

一、Redis.conf详解 容量单位 1、配置大小单位&#xff0c;开头定义了一些基本的度量单位&#xff0c;只支持bytes&#xff0c;不支持bit,不区分大小写&#xff0c;G和GB有区别 2、对 大小写 不敏感 可以使用 include 组合多个配置问题 网络配置 bind 127.0.0.1 # 绑定的i…

ES学习日记(八)-------ik安装和简易使用

一、下载和安装 https://github.com/infinilabs/analysis-ik.git 网络不好可以用这个地址,注意:ik版本要和es版本保持一致 现成地址 注意es用户操作或给es用户权限 plugins新建ik文件夹,并把压缩包解压到ik unzip elasticsearch-analysis-ik-7.4.2.zip /bin目录启动es: 二…

【Rust】生命周期

Rust 生命周期机制是与所有权机制同等重要的资源管理机制。 之所以引入这个概念主要是应对复杂类型系统中资源管理的问题。 引用是对待复杂类型时必不可少的机制&#xff0c;毕竟复杂类型的数据不能被处理器轻易地复制和计算。 但引用往往导致极其复杂的资源管理问题&#x…

MyBatis 上

预备知识&#xff1a;JAVA基础、JDBC 文章目录 一、MyBatis简介二、搭建MyBatis1. 开发环境2. 创建模块&#xff0c;导入坐标3. 创建MyBatis的核心配置文件 --> 替换连接信息解决硬编码问题4. 创建mapper接口5. 创建SQL的映射文件 --> 统一管理sql语句&#xff0c;解决硬…

【Linux】线程概念及线程互斥

目录 线程概念 线程优点 线程缺点 线程异常 线程系统编程接口 线程创建及终止 线程等待 使用线程系统接口封装一个小型的C线程库并实现一个抢票逻辑 线程互斥 互斥量的接口 线程互斥实现原理 使用系统加锁接口封装LockGuard 实现自动化加锁 线程安全和可重入函数 …

20240405,数据类型,运算符,程序流程结构

是我深夜爆炸&#xff0c;不能再去补救C了&#xff0c;真的来不及了&#xff0c;不能再三天打鱼两天晒网了&#xff0c;真的来不及了呜呜呜呜 我实在是不知道看什么课&#xff0c;那黑马吧……MOOC的北邮的C正在进行呜呜 #include <iostream> using namespace std; int…

【微服务】------核心组件架构选型

1.微服务简介 微服务架构&#xff08;Microservice Architecture&#xff09;是一种架构概念&#xff0c;旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦&#xff0c;从而降低系统的耦合性&#xff0c;并提供更加灵活的服务支持。 2.微服务技术选型 区域内容…