【python接口自动化】- 正则用例参数化

 🔥 交流讨论:欢迎加入我们一起学习!

🔥 资源分享耗时200+小时精选的「软件测试」资料包

🔥 教程推荐:火遍全网的《软件测试》教程  

📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

前言

​ 我们在做接口自动化的时候,处理接口依赖的相关数据时,通常会使用正则表达式来进行提取相关的数据。

​ 正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(Regular Expression,在代码中常简写为regex、regexp或RE) 。它是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。而Python 自1.5版本起增加了re模块,它提供 Perl 风格的正则表达式模式。

正则表达式语法

表示单字符

​ 单字符:即表示一个单独的字符,比如匹配数字用\d,匹配非数字用\D

​ 除以下语法,也可以匹配指定的具体字符,可以是1个也可以是多个。

字符功能说明
.匹配任意1个字符(除了\n)
[2a]匹配[]中括号中列举的字符,如这里就是匹配2或者a这两个字符其中的一个
\d匹配数字,即0-9
\D匹配非数字
\s匹配空白,即空格、tab键(tab键为两个空格)
\S匹配非空白
\w匹配单词字符,即a-z、A-Z、0-9、_(数字、字母、下划线)
\W匹配非单词字符

​ 实例如下,这里先说明一下findall(匹配规则,要匹配的字符串)这个方法是查找所有匹配的数据,以列表的形式返回,后面会在re模块进行详解:

python

import re


# .:匹配任意1个字符
re1 = r'.'
res1 = re.findall(re1, '\nj8?0\nbth\nihb')
print(res1)	# 运行结果:['j', '8', '?', '0', 'b', 't', 'h', 'i', 'h', 'b']

# []:匹配列举中的其中一个
re2 = r"[abc]"
res2 = re.findall(re2, '1iugfiSHOIFUOFGIDHFGFD2345a6a78b99cc')
print(res2)	# 运行结果:['a', 'a', 'b', 'c', 'c']

# \d:匹配一个数字
re3 = r"\d"
res3 = re.findall(re3, "dfghjkl32212dfghjk")
print(res3)	# 运行结果:['3', '2', '2', '1', '2']

# \D:匹配一个非数字
re4 = r"\D"
res4 = re.findall(re4, "d212dk?\n$%3;]a")
print(res4)	# 运行结果:['d', 'd', 'k', '?', '\n', '$', '%', ';', ']', 'a']

# \s:匹配一个空白键或tab键(tab键实际就是两个空白键)
re5 = r"\s"
res5 = re.findall(re5,"a s d a  9999")
print(res5)	# 运行结果:[' ', ' ', ' ', ' ', ' ']

# \S: 匹配非空白键
re6 = r"\S"
res6 = re.findall(re6, "a s d a  9999")
print(res6)	# 运行结果:['a', 's', 'd', 'a', '9', '9', '9', '9']

# \w:匹配一个单词字符(数字、字母、下划线)
re7 = r"\w"
res7 = re.findall(re7, "ce12sd@#a as_#$")
print(res7)	# 运行结果:['c', 'e', '1', '2', 's', 'd', 'a', 'a', 's', '_']

# \W:匹配一个非单词字符(不是数字、字母、下划线)
re8 = r"\W"
res8 = re.findall(re8, "ce12sd@#a as_#$")
print(res8)	# 运行结果:['@', '#', ' ', '#', '$']

# 匹配指定字符
re9 = r"python"
res9 = re.findall(re9, "cepy1thon12spython123@@python")
print(res9)	# 运行结果:['python', 'python']

表示数量

​ 如果要匹配某个字符多次,就可以在字符后面加上数量进行表示,具体规则如下:

字符功能说明
*匹配前一个字符出现0次或者无限次,即可有可无
+匹配前一个字符出现1次或无限次,即至少1次
?匹配前一个字符出现0次或1次,即要么没有,要么只有1次
匹配前一个字符出现m次
匹配前一个字符至少出现m次
匹配前一个字符出现从m到n次

​ 实例如下:

python

import re


# *:表示前一个字符出现0次以上(包括0次)
re21 = r"\d*"   # 这里匹配的规则,前一个字符是数字
res21 = re.findall(re21, "343aa1112df345g1h6699")  # 如匹配到a时,属于符合0次,但因为没有值所以会为空
print(res21)	# 运行结果:['343', '', '', '1112', '', '', '345', '', '1', '', '6699', '']

# ? : 表示0次或者一次
re22 = r"\d?"
res22 = re.findall(re22, "3@43*a111")
print(res22)	# 运行结果:['3', '', '4', '3', '', '', '1', '1', '1', '']

# {m}:表示匹配一个字符m次
re23 = r"1[3456789]\d{9}" # 手机号:第1位为1,第2位匹配列举的其中1个数字,第3位开始是数字,且匹配9次
res23 = re.findall(re23,"sas13566778899fgh256912345678jkghj12788990000aaa113588889999")
print(res23)	# 运行结果:['13566778899', '13588889999']

# {m,}:表示匹配一个字符至少m次
re24 = r"\d{7,}"
res24 = re.findall(re24, "sas12356fgh1234567jkghj12788990000aaa113588889999")
print(res24)	# 运行结果:['1234567', '12788990000', '113588889999']

# {m,n}:表示匹配一个字符出现m次到n次
re25 = r"\d{3,5}"
res25 = re.findall(re25, "aaaaa123456ghj333yyy77iii88jj909768876")
print(res25)	# 运行结果:['12345', '333', '90976', '8876']

匹配分组

字符功能说明
|匹配左右任意一个表达式
(ab)将括号中字符作为一个分组

​ 实例如下:

python

import re


# 同时定义多个规则,只要满足其中一个
re31 = r"13566778899|13534563456|14788990000"
res31 = re.findall(re31, "sas13566778899fgh13534563456jkghj14788990000")
print(res31)	# 运行结果:['13566778899', '13534563456', '14788990000']

# ():匹配分组:在匹配规则的数据中提取括号里的数据
re32 = r"aa(\d{3})bb"	# 如何数据符合规则,结果只会取括号中的数据,即\d{3}
res32 = re.findall(re32, "ggghjkaa123bbhhaa672bbjhjjaa@45bb")
print(res32)	# 运行结果:['123', '672']

表示边界

字符功能说明
^匹配字符串开头,只能匹配开头
$匹配字符串结尾,只能匹配结尾
\b匹配一个单词的边界(单词:字母、数字、下划线)
\B匹配非单词的边界

​ 实例如下:

python

import re


# ^:匹配字符串的开头
re41 = r"^python"   # 字符串开头为python
res41 = re.findall(re41, "python999python")  # 只会匹配这个字符串的开头
res411 = re.findall(re41, "1python999python")  # 因为开头是1,第1位就不符合了
print(res41)	# 运行结果:['python']
print(res411)	# 运行结果:[]

# $:匹配字符串的结尾
re42=r"python$"	# 字符串以python结尾
res42 = re.findall(re42, "python999python")
print(res42)	# 运行结果:['python']

# \b:匹配单词的边界,单词即:字母、数字、下划线
re43 = r"\bpython"  # 即匹配python,且python的前一位是不是单词
res43 = re.findall(re43, "1python 999 python")  # 这里第1个python的前1位是单词,因此第1个是不符合的
print(res43)	# 运行结果:['python']

# \B:匹配非单词的边界
re44 = r"\Bpython"  # 即匹配python,且python的前一位是单词
res44 = re.findall(re44, "1python999python")
print(res44)	# 运行结果:['python', 'python']

贪婪模式

​ python里数量词默认是贪婪的,总是尝试匹配尽可能多的字符,而非贪婪模式则是尝试匹配尽可能少的字符,在表示数量的表达式后加上问号(?)就可以关闭贪婪模式。

​ 如下例子,匹配2个以上的数字,如果符合条件它会一直匹配到不符合才停止,如其中的34656fya,34656符合2个数字以上,那么它会一直匹配到6为止,如果关闭贪婪模式,那么在满足2个数字时就会停止,最后可以匹配到34、65。

python

import re


# 默认的贪婪模式下
test = 'aa123aaaa34656fyaa12a123d'
res = re.findall(r'\d{2,}', test)
print(res)	# 运行结果:['123', '34656', '12', '123']

# 关闭贪婪模式
res2 = re.findall(r'\d{2,}?', test)
print(res2)	# 运行结果:['12', '34', '65', '12', '12']

re模块

​ 在python中使用正则表达式,就会用到re模块来进行操作,提供的方法一般需要传入两个参数:

  • 📘参数1: 匹配的规则
  • 📒参数2:要进行匹配的字符串

re.findall()

​ 查找所有符合规范的字符串,以列表的形式返回。

python

import re


test = 'aa123aaaa34656fyaa12a123d'
res = re.findall(r'\d{2,}', test)
print(res)	# 运行结果:['123', '34656', '12', '123']

re.search()

​ 查找第一个符合规范的字符串,返回的是一个匹配对象,可以通过group()将匹配到的数据直接提取出来。

python

import re


s = "123abc123aaa123bbb888ccc"
res2 = re.search(r'123', s)
print(res2)  # 运行结果:<re.Match object; span=(0, 3), match='123'>

# 通过group将匹配到的数据提取出来,返回类型为str
print(res2.group())   # 运行结果:123

​ 返回的匹配对象中,span为匹配到的数据的下标范围,match则是匹配到的值。

​ group()参数说明

  • 🍊不传参数:获取的是匹配到的所有内容
  • 🍋传入数值:可以通过参数来指定,获取第几个分组中的内容(获取第1个分组,传入参数1,获取第2个分组,传入参数2,依次类推。)

python

import re


s = "123abc123aaa123bbb888ccc"
re4 = r"aaa(\d{3})bbb(\d{3})ccc"	# 这里分组就是前面说到的匹配语法:()
res4 = re.search(re4, s)
print(res4)
# group不传参数:获取的是匹配到的所有内容
# group通过参数指定,获取第几个分组中的内容(获取第1个分组,传入参数1,获取第2个分组,传入参数2,依次类推..
print(res4.group())
print(res4.group(1))
print(res4.group(2))

re.match()

​ 从字符串的起始位置进行匹配,匹配成功则返回匹配到的对象,如果开头的位置不符合匹配的规则,不会继续往后面去匹配,直接返回None。re.match()re.search()都是只匹配一个,不一样的是,前者只匹配字符串的开头,后者则是会匹配整个字符串,但只获取第一个符合的数据。

python

import re


s = "a123abc123aaa1234bbb888ccc"
# match:只匹配字符串的开头,开头不符合就返回None
res1 = re.match(r"a123", s)
res2 = re.match(r"a1234", s)
print(res1)  # 运行结果:<re.Match object; span=(0, 4), match='a123'>
print(res2)  # 运行结果:None

re.sub()

​ 检索和替换:用于替换字符串中的匹配项

​ re.sub()参数说明

  • 🍇参数1:待替换的字符串
  • 🍉参数2:目标字符串
  • 🍑参数3:要进行替换操作的字符串
  • 🍓参数4:可以指定最多替换的次数,非必填(默认替换所有符合规范的字符串)

python

import re


s = "a123abc123aaa123bbb888ccc"
# <font color="#FF0000">参数1:</font>待替换的字符串
# <font color="#FF0000">参数2:</font>目标字符串
# <font color="#FF0000">参数3:</font>要进行替换操作的字符串
# <font color="#FF0000">参数4:</font>可以指定最多替换的次数,非必填(默认替换所有符合规范的字符串)
res5 = re.sub(r'123', "666", s, 4)
print(res5)  # 运行结果:a666abc666aaa666bbb888ccc

用例参数化

​ 在接口自动化测试中,我们的测试数据都是保存在excel中的,有些参数如果写死一个数据,可能换个场景或者换个环境就不能用了,那么切换环境时就需要先把新环境的测试数据准备好,并且能支持去跑我们的脚本,或者把excel的数据修改为适合新环境的测试数据,维护的成本较高。因此就需要把我们的自动化脚本测试数据尽量地参数化,降低维护成本。

​ 我们先看简单版的参数化,以登录为例,登录时用到的账号、密码等信息都可以提取出来放到配置文件,修改数据或更换环境时直接在配置文件中统一修改就可以了。

​编辑 ​编辑

​ 但如果有多个不同的数据需要参数化呢,每个参数都加个判断去替换数据吗?这样的代码既啰嗦又不好维护,这时re模块就可以用上了,直接看一个实例:

python

import re
from common.myconfig import conf


class TestData:
    """用于临时保存一些要替换的数据"""
    pass


def replace_data(data):
    r = r"#(.+?)#"	# 注意这个分组()内的内容
    # 判断是否有需要替换的数据
    while re.search(r, data):
        res = re.search(r, data)	# 匹配出第一个要替换的数据
        item = res.group()	# 提取要替换的数据内容
        key = res.group(1)	# 获取要替换内容中的数据项
        try:
            # 根据替换内容中的数据项去配置文件中找到对应的内容,进行替换
            data = data.replace(item, conf.get_str("test_data", key))
        except:
            # 如果在配置文件中找不到就在临时保存的数据中找,然后替换
            data = data.replace(item, getattr(TestData, key))
    return data

​ 注意这里的正则表达式是有使用?关闭贪婪模式的,因为测试数据中可能会需要参数化2个或以上的数据,如果不关闭贪婪模式,它就只能匹配搭配一个数据,举例如下:

python

import re


data = '{"mobile_phone":"#phone#","pwd":"#pwd#","user":#user#}'
r1 = "#(.+)#"
res1 = re.findall(r1, data)
print(res1)  # 运行结果:['phone#","pwd":"#pwd#","user":#user']	注意这里单引号只有一个数据
print(len(res1))      # 运行结果:1

r2 = "#(.+?)#"
res2 = re.findall(r2, data)
print(res2)  # 运行结果:['phone', 'pwd', 'user']
print(len(res2))      # 运行结果:3

​ 另外提到的一个用于临时保存数据的类,这里主要用于保存接口返回的数据,因为有些测试数据是动态变化的,可能要依赖于某个接口,后面的测试用例又需要这些数据,那么我们在接口返回时就可以保存到这个类里作为一个类属性,接着在需要用这个数据的测试用例时,把这个类属性提取出来替换到测试数据中即可。提示:设置属性setattr(对象, 属性名, 属性值),获取属性值getattr(对象, 属性名)

最后我邀请你进入我们的【软件测试学习交流群:785128166】, 大家可以一起探讨交流软件测试,共同学习软件测试技术、面试等软件测试方方面面,还会有免费直播课,收获更多测试技巧,我们一起进阶Python自动化测试/测试开发,走向高薪之路

作为一个软件测试的过来人,我想尽自己最大的努力,帮助每一个伙伴都能顺利找到工作。所以我整理了下面这份资源,现在免费分享给大家,有需要的小伙伴可以关注【公众号:程序员二黑】自提!

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

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

相关文章

鸿蒙开发有必要学吗?看完这篇再决定吧

在科技的潮流中&#xff0c;每一次新操作系统的诞生都是对旧秩序的挑战与新机遇的孕育。鸿蒙操作系统的出现&#xff0c;无疑是近年来科技界最引人注目的事件之一。自华为于2019年正式推出鸿蒙系统以来&#xff0c;这一我们自主研发的操作系统不仅在国内引起巨大反响&#xff0…

在windows平台上mysql的安装教程

1.下载 mysql下载网址&#xff1a;https://dev.mysql.com/downloads/installer/ 这里直接选择的是mysql的社区版。自己使用直接选择免费的就行 直接选择下载 2.安装过程 选择Server only 就行 下一步 下一步 下一步&#xff0c;选择弱密码把&#xff0c;方便学习和自己使用 设置…

Java对象属性设置方式

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 对象属性设置方式 直接赋值 SystemMappingCode systemMappingCode new SystemMappingCode();systemMappingCode.setCodeResp(request.getCodeResp());systemMapping…

POI操作word表格,添加单元格,单元格对齐方法(不必合并单元格)

添加单元格&#xff0c;直接对row进行create新的cell&#xff0c;则会导致新创建的单元格与前面的单元格不对齐的现象。 //表格信息XWPFTable table doc.createTable();table.setWidth("100%");//第一行XWPFTableRow row0table.getRow(0);XWPFTableCell cell00row0.…

基于Python的招聘网站爬虫及可视化的设计与实现

摘要&#xff1a;现在&#xff0c;随着互联网网络的飞速发展&#xff0c;人们获取信息的最重要来源也由报纸、电视转变为了互联网。互联网的广泛应用使网络的数据量呈指数增长&#xff0c;让人们得到了更新、更完整的海量信息的同时&#xff0c;也使得人们在提取自己最想要的信…

Linux - iptables 防火墙

一. 安全技术和防火墙 1.安全技术 入侵检测系统&#xff08;Intrusion Detection Systems&#xff09;&#xff1a;特点是不阻断任何网络访问&#xff0c;量化、定位来自内外网络的威胁情况&#xff0c;主要以提供报警和事后监督为主&#xff0c;提供有针对性的指导措施和安全…

【C++游戏开发-01】推箱子

C游戏开发 文章目录 C游戏开发[TOC](文章目录) 前言一、逻辑分析1.1地图实现1.2人物的移动1.2.1小人移动1.2.2其他移动 1.3墙壁的碰撞1.4箱子的推动1.4.1什么时候推箱子1.4.2什么情况可以推箱子 1.5胜利的判断1.6卡关的处理1.7关卡的切换 二、DEMO代码2.1游戏框架2.2各功能函数…

【亲测有效】无法获得下列许可 SOLIDWORKS Standard 无效的(不一致的) 使用许可号码 (-8,544,0)

在观看本文章前&#xff0c;请注意看你的报错代码是否和我的一致&#xff0c;如果不是&#xff0c;直接跳过本文章。 前言&#xff1a;我安装的是SOLIDWORKS2022版&#xff0c;软件已经安装完毕&#xff0c;SolidWorks_Flexnet_Server文件夹里面的两个注册表已经安装完毕&#…

Python tkinter (7) ——Scale控件

Python的标准Tk GUI工具包的接口 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— Button标签 Python tkinter (3) —— Entry标签 Python tkinter (4) —— Text控件 Python tkinter (5) 选项按钮与复选框 Pyt…

Stata收敛性分析(含详细代码说明和样例数据)

Stata收敛性分析&#xff08;含详细代码说明和样例数据&#xff09; 收敛性分析是管理科学和运筹学中重要的概念&#xff0c;是一种解决决策者对他们的管理策略的反馈的方式和手段。它的最终目的是帮助管理者从复杂的环境中筛选最优的解决方案。收敛性分析一般情况下会结合一些…

为客户解决痛点,电子纸增加制表功能

为客户解决痛点&#xff0c;电子纸增加制表功能 部分客户购买我们的电子纸后反馈效果很好&#xff0c;但是在配套组态软件制作电子纸模板时&#xff0c;遇到需要制作表格的时候比较麻烦。像是在画板作画一样&#xff0c;比较费时&#xff0c;而且效果不是很好&#xff0c;没办…

用VsCode写python

1.创建一个文件夹 2.创建.py文件 print("Hello World") print("*"*10) 4.运行 在终端版本fileName python3 app.py

MATLAB矩阵的操作(第二部分)

师从清风 矩阵的创建方法 在MATLAB中&#xff0c;矩阵的创建方法主要有三种&#xff0c;分别是&#xff1a;直接输入法、函数创建法和导入本地文件中的数据。 直接输入法 输入矩阵时要以中括号“[ ]”作为标识符号&#xff0c;矩阵的所有元素必须都在中括号内。 矩阵的同行元…

零基础学Python之核心基础知识

1.Python入门简介 &#xff08;1&#xff09;什么是Python Life is short, you need Python&#xff01;人生苦短&#xff0c;我用Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言…

笔记---中国剩余定理

全程学自y总 AcWing.204.表达整数的奇怪方式 给定 2 n 2n 2n 个整数 a a a1, a a a2,…, a a an 和 m m m1, m m m2,…, m m mn&#xff0c;求一个最小的非负整数 x x x&#xff0c;满足 ∀ i ∈ [ 1 , n ] , x ≡ m ∀i∈[1,n],x≡m ∀i∈[1,n],x≡mi ( m o d a (mod a (…

SpringMVC中的文件上传与下载功能,以及虚拟目录的配置

目录 文件下载 文件上传 第一步&#xff1a;添加依赖&#xff1a; 第二步&#xff1a;在SpringMVC的配置文件中添加配置&#xff1a; 三、控制器方法&#xff1a; 虚拟目录配置方式&#xff1a; 前端代码 SpringMVC中的文件上传与下载功能是通过MultipartResolver来实现…

华为鸿蒙DevEco Studio编辑器初体验

目录 前言DevEco Studio编辑器使用准备工作应用/服务运行可视化调试DevEco Studio配置参数列表番外篇&#xff1a;参加鸿蒙生态学堂创新实训营北京站的培训结束语 前言 众所周知华为鸿蒙作为移动应用开发的第三个热门领域&#xff08;前两个热门领域iOS原生、Android原生都已…

半桥式三相无刷直流电动机不同导通角的性能的变化

半桥式三相无刷直流电动机不同导通角的性能的变化 syms Omega clear clcOmega0pi/180*120 for Omega_x[pi/180*120,pi/180*130,pi/180*140,pi/180*150,pi/180*160,pi/180*170,pi/180*180]Omega_x*180/piOmega_x_0 (4*sin(Omega_x/2)/(Omega_xsin(Omega_x)))/(4*sin(Omega0/2)/…

数据结构—基础知识:哈夫曼编码

数据结构—基础知识&#xff1a;哈夫曼编码 哈夫曼编码的主要思想 在进行数据压缩时&#xff0c;为了使压缩后的数据文件尽可能短&#xff0c;可采用不定长编码。其基本思想是&#xff1a;为出现次数较多的字符编以较短的编码。为确保对数据文件进行有效的压缩文件和对压缩文…

基于数据挖掘的微博事件分析与可视化大屏分析系统

设计原理&#xff0c;是指一个系统的设计由来&#xff0c;其将需求合理拆解成功能&#xff0c;抽象的描述系统的模块&#xff0c;以模块下的功能。功能模块化后&#xff0c;变成可组合、可拆解的单元&#xff0c;在设计时&#xff0c;会将所有信息分解存储在各个表中&#xff0…