使用 Python 中 re 模块对测试用例参数化,进行搜索 search、替换 sub
参数化的目的:运行自动化测试用例的时候参数都不需要改变,直接使用封装好的类进行参数化,发起请求时直接使用替换后参数;
自动化测试用例,如果一百个接口要在Excel写100个sheet表单,每个接口有10个字段,里面有5个都可能是变化的,需要使用参数化,先试用特定的字符在用例中进行站位,在发起请求构造参数时在进行替换占位符;----------我们可以每个接口分别创建一个参数化;
一、用例中手机号的替换,以字符串中的方法,使用 replace (译:瑞破类似) 进行替换
# 原始字符串:{"mobilephone": "${not_existed_tel}", "pwd":"123456"}
# json 字符串
src_str = '{"mobilephone": "${not_existed_tel}", "pwd":"123456"}'
# 替换 json 字符串中 ${not_existed_tel} 为 18845820369
print(src_str.replace("${not_existed_tel}", "")) # 结果:{"mobilephone": "18845820369", "pwd":"123456"}
二、使用 re 模块进行替换
re 正则表达式,是一个查找、搜索、替换文本的一种格式语言
搜索方法一,re 模块中的 match(译:马驰)方法,match方法是从头开始匹配
import re # 1. 创建原始字符串(待替换的字符串)
src_str4 = '{"mobilephone": "${not_existed_tel}", "pwd":"123456"}' # 2. 定义模式字符串去进行匹配
# 模式字符串 == 模子,以这个模板去原始字符串中进行比对 # 方法一,re 正则中的 match(译:马驰)方法,match方法是从头开始匹配
# 从 { 开始,匹配不上, 那么就回复None
res = re.match("{not_existed_tel}", src_str4)
print(res) # 结果:None # 从 { 开始,能匹配上, 会返回Match对象,加r不需要转义
res = re.match(r'{"mobilephone"', src_str4)
print(res) # 返回Match对象结果:<re.Match object; span=(0, 14), match='{"mobilephone"'> # 获取匹配的结果内容 group (译:歌如破)
a = res.group()
print(a) # 结果:{"mobilephone"
搜索方法二:search (译:涩吃)方法,只匹配一次
import re # 1. 创建原始字符串(待替换的字符串)
src_str1 = '{"mobilephone": "${not_existed_tel}", "pwd":"123456"}' # 2. 定义模式字符串去进行匹配
# 模式字符串 == 模子,以这个模板去原始字符串中进行比对:"${not_existed_tel}" # 方法二:search (译:涩吃)方法,只匹配一次
# 如果能匹配上会返回Match对象,匹配不上会返回None
# 美元符号需要转义加 r,特殊字符都需要转义
res1 = re.search(r"\${not_existed_tel}", src_str1)
print(res1) # Match对象结果:<re.Match object; span=(17, 35), match='${not_existed_tel}'> # 获取匹配到的结果,group(译:格如破)方法
b = res1.group()
print(b) # 结果:${not_existed_tel}
搜索方法三:findall (译:范德奥)方法,会匹配很多次
src_str1 = '{"mobilephone": "${not_existed_tel}", "pwd":"123456"}'
res2 = re.findall(r'o', src_str1)
print(res2) # 直接返回列表结果:['o', 'o', 'o']
替换方法: sub (译:萨博)方法
import re # 1. 创建原始字符串(待替换的字符串)
src_str2 = '{"mobilephone": "${not_existed_tel}", "pwd":"123456"}' # 第一个参数为模式字符串:${not_existed_tel}
# 第二个参数为新的字符串:18845820369
# 第三个参数为原始的字符串
# sub 方法如果能匹配上, 那么会返回替换之后的字符串
# sub 方法如果匹配不上, 那么直接返回原始的字符串 # 使用 search 方法先搜索,搜索到再用 sub 方法进行替换;count=0 默认匹配一次
if re.search(r"\${not_existed_tel}", src_str2): # 先搜索
res2 = re.sub(r"\${not_existed_tel}", "", src_str2) # 在替换
print(res2)
else:
print("无法匹配原始字符串")
# 替换后结果:{"mobilephone": "18845820369", "pwd":"123456"} # 使用正则匹配:\w+ 单词字符[A-Za-z0-9_],+ 多次匹配;通过正则在原始字符串中匹配
if re.search(r"\${\w+}", src_str2): # 先搜索
res2 = re.sub(r"\${not_existed_tel}", "", src_str2) # 在替换
print(res2)
else:
print("无法匹配原始字符串")
# 替换后结果:{"mobilephone": "18845820369", "pwd":"123456"}
re 模块基本参数化封装
import re from scripts.handle_mysql import HandleMysql # 数据库封装
from scripts.handle_config import HandleConfig # 配置文件封装
from scripts.constants import CONFIGS_USER_ACCOUTS_DIR # 要读取的配置文件路径 class Context:
"""
处理上下文参数化
"""
not_existed_tel_pattern = r'\${not_existed_tel}'
invest_user_tel_pattern = r'\${invest_user_tel}' # 配置${invest_user_tel} 的正则表达式
invest_user_pwd_pattern = r'\${invest_user_pwd}' # 配置${invest_user_pwd} 的正则表达式 handle_config = HandleConfig(filename=CONFIGS_USER_ACCOUTS_DIR) # 配置文件:需要指定用户账号所在的配置文件路径,为了读取数据 @classmethod
def not_existed_tel_replace(cls, data):
"""
参数化未注册手机号(调用随机生成手机号方法)----常用替换方法以下面的方式
:param data: 发起请求时传入的data
:return: 参数化后data 或 匹配不上不需要参数化的原始data
"""
if re.search(cls.not_existed_tel_pattern, data): # 使用search方法在用例中匹配,匹配不上不需要替换,返回原始字符串
do_mysql = HandleMysql() # 创建会话
data = re.sub(cls.not_existed_tel_pattern, # 使用sub方法替换
do_mysql.create_not_existed_mobile(), # 随机生成一个在数据库不存在的手机号
data)
do_mysql.close() # 关闭会话
return data @classmethod
def invest_user_tel_replace(cls, data):
"""
参数化已注册的手机号(配置文件中获取已注册手机号码)
:param data: 发起请求时传入的data
:return: 参数化后data 或 匹配不上不需要参数化的原始data
"""
if re.search(cls.invest_user_tel_pattern, data): # 使用search方法在用例中匹配,匹配不上不需要替换,返回原始字符串
invest_user_tel = cls.handle_config.get_value("invest_user", "mobilephone") # 配置文件中获取手机号码
data = re.sub(cls.invest_user_tel_pattern, invest_user_tel, data) # 使用sub方法替换
return data @classmethod
def invest_user_pwd_replace(cls, data):
"""
参数化已注册的密码(配置文件中账号的密码)
:param data: 发起请求时传入的data
:return: 参数化后data 或 匹配不上不需要参数化的原始data
"""
if re.search(cls.invest_user_pwd_pattern, data): # 使用search方法在用例中匹配,匹配不上不需要替换,返回原始字符串
invest_user_pwd = cls.handle_config.get_value("invest_user", "pwd") # 配置文件中获取密码
data = re.sub(cls.invest_user_pwd_pattern, invest_user_pwd, data) # 使用sub方法替换
return data @classmethod
def register_parameterization(cls, data):
"""
对某个接口批量参数化
:param data: 发起请求时传入的data
:return: 参数化后data 或 匹配不上不需要参数化的原始data
"""
data = cls.not_existed_tel_replace(data) # 参数化未注册的手机号
data = cls.invest_user_tel_replace(data) # 参数化已注册的手机号
data = cls.invest_user_pwd_replace(data) # 再参数化已注册的用户密码
return data if __name__ == '__main__':
one_str = '{"mobilephone": "${not_existed_tel}", "pwd":"${invest_user_pwd}", "regname": "KeYou"}'
two_str = '{"mobilephone": "${not_existed_tel}", "pwd": ""}'
three_str = '{"mobilephone": "", "pwd": "123456"}' # 不需要参数化,返回原始data
six_str = '{"mobilephone": "${invest_user_tel}", "pwd": "123456", "regname": "KeYou"}' # 参数化
print(Context.register_parameterization(one_str))
print(Context.register_parameterization(two_str))
print(Context.register_parameterization(three_str))
print(Context.register_parameterization(six_str)) # 结果
# {"mobilephone": "13218495762", "pwd":"123456", "regname": "KeYou"}
# {"mobilephone": "13278293460", "pwd": ""}
# {"mobilephone": "", "pwd": "123456"}
# {"mobilephone": "13226834715", "pwd": "123456", "regname": "KeYou"}
*******请大家尊重原创,如要转载,请注明出处:转载自:https://www.cnblogs.com/shouhu/ 谢谢!!*******
使用 Python 中 re 模块对测试用例参数化,进行搜索 search、替换 sub的更多相关文章
- Python中optionParser模块的使用方法[转]
本文以实例形式较为详尽的讲述了Python中optionParser模块的使用方法,对于深入学习Python有很好的借鉴价值.分享给大家供大家参考之用.具体分析如下: 一般来说,Python中有两个内 ...
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
- 【转】关于python中re模块split方法的使用
注:最近在研究文本处理,需要用到正则切割文本,所以收索到了这篇文章,很有用,谢谢原作者. 原址:http://blog.sciencenet.cn/blog-314114-775285.html 关于 ...
- Python中的模块介绍和使用
在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一 ...
- python中导入模块的本质, 无法导入手写模块的解决办法
最近身边一些朋友发生在项目当中编写自己模块,导入的时候无法导入的问题. 下面我来分享一下关于python中导入模块的一些基本知识. 1 导入模块时寻找路径 在每一个运行的python程序当中,都维护了 ...
- Python中time模块详解
Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...
- Python中collections模块
目录 Python中collections模块 Counter defaultdict OrderedDict namedtuple deque ChainMap Python中collections ...
- Python中pathlib模块
Python中pathlib模块 Path.cwd():返回当前目录的路径 Path.home():返回当前用户的家目录 Path.stat():返回此路径信息 Path.touch():创建文件 P ...
- Python 中包/模块的 `import` 操作
版权声明:博客为作者原创,允许转载,但必须注明原文地址: https://www.cnblogs.com/byronxie/p/10745292.html 用实例来说明 import 的作用吧. 创建 ...
随机推荐
- SDUT-2133_数据结构实验之栈与队列三:后缀式求值
数据结构实验之栈与队列三:后缀式求值 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 对于一个基于二元运算符的后缀表示式 ...
- mysql数据库之mysql下载与设置
下载和安装mysql数据库 mysql为我们提供了开源的安装在各个操作系统上的安装包,包括ios,liunx,windows. mysql的安装,启动和基础配置-------linux版本 mysql ...
- CI框架下 新浪微博登录接口完整版
https://www.cnblogs.com/yznyzcw/p/3756622.html#top 说明:本贴只适合CI框架.功能实现:登录接口跳转链接成功,获取用户信息(包括最重要的u_id)成功 ...
- 【t001】不高兴的津津
Time Limit: 1 second Memory Limit: 50 MB [问题描述] 津津上初中了.妈妈认为津津应该更加用功学习,所以津津除了上学之外,还要参加妈妈为她报名的各科复习班.另外 ...
- Codeforces Round #170 (Div. 1 + Div. 2)
A. Circle Line 考虑环上的最短距离. B. New Problem \(n\) 个串建后缀自动机. 找的时候bfs一下即可. C. Learning Languages 并查集维护可以沟 ...
- 2018-2-13-WPF-DelegateCommand-出现Specified-cast-is-not-valid
title author date CreateTime categories WPF DelegateCommand 出现Specified cast is not valid lindexi 20 ...
- java 网络编程Socket
TCP: 通过TCP协议传输,得到的是一个顺序的无差错的数据流. 发送方和接收方的成对的两个socket之间必须建立连接, 以便在TCP协议的基础上进行通信,当一个socket(通常都是server ...
- echarts 图表自适应外部盒子大小
项目中用到了echarts,由于页面是自适应的,还得兼容移动, 因此图表还需要根据盒子的大小来变化. 自适应窗口及盒子大小 页面中有一个[放大.缩小]功能,及全屏展示和预览图表 窗口自适应 let m ...
- 写一个js配合rem
rem.js 目前笔者解决移动端的尺寸带来的样式问题,都是通过viewport + rem的.viewport 相信大家都用过了,而rem需要用js动态设置html的字体大小. 动态设置rem的根字体 ...
- UVA 1025 "A Spy in the Metro " (DAG上的动态规划?? or 背包问题??)
传送门 参考资料: [1]:算法竞赛入门经典:第九章 DAG上的动态规划 题意: Algorithm城市的地铁有 n 个站台,编号为 1~n,共有 M1+M2 辆列车驶过: 其中 M1 辆列车从 1 ...