几乎所有的编程语言都支持正则表达式。
字符串的模糊匹配技术。(基于一个规则去匹配字符串当中的内容)
只要是想在字符串当中找符合规则的字串,基本上都可以使用正则表达式。
正则表达式在python当中的应用,需要使用到re模块,使用前需要先导入,不需要安装。
一.正则表达式语法 1.表示单字符单字符:即表示一个单独的字符,比如匹配数字用d,匹配非数字使用D,具体规则如下:
2.表示数量如果要匹配某个字符多次,就可以在字符后面加上数量进行表示,具体规则如下:
3.表示边界 4.匹配分组 5.贪婪模式贪婪模式:python里数据词默认是贪婪的,总是尝试匹配尽可能多的字符;
如下案例:匹配任意一个字符0次或者无数次,贪婪模式会尽可能匹配更多字符,无数次就是更多,那么这里匹配的结果就是所有字符。
string = 'aa27bc245' res = re.search(pattern='.*', string=string) print(res)
非贪婪模式:总是尝试匹配尽可能少的字符,在"*","?","+","{m,n}","{m,}"后面加上?,可以关闭贪婪模式。关闭贪婪模式之后,尽可能获取更少的,如下,就是获取到最少0个字符
string = 'aa27bc245' res = re.search(pattern='.*?', string=string) print(res)
在python中使用正则表达式,需要用到re模块来进行操作。
re.search 扫描整个字符串并返回第一个成功的匹配。
语法:re.search(pattern, string) pattern:匹配的模式,string:要匹配的字符串
import re
string = '{"member_id":"#member_id#","amount":"#money#"}'
result = re.search('#.*?#', string)
print(result)
# 分组
result = re.search('#(.*?)#', string)
# result.group()正则表达式匹配的整个结果,默认索引0
print(result.group())
# result.group(1)正则表达式匹配的结果当中第一个括号里面的内容
print(result.group(1))
运行结果:
三.实战演练
re.finditer,匹配并返回所有符合正则表达式的子字符串
字符串替换前,必须先存在同名属性。
import re
string = '{"member_id":"#member_id#","amount":"#money#"}'
class data:
member_id = 123
money = 100
# 方法1:if实现
if '#member_id#' in string:
string_if = string.replace("#member_id#", str(getattr(Data, 'member_id')))
if '#money#' in string_if:
string_if = string_if.replace("#money#", str(getattr(Data, 'money')))
print(string_if)
# 方法2 正则表达式
# re.finditer 返回所有符合正则表达式的子字符串
result = re.finditer('#(.*?)#', string)
for el in result:
# el表示匹配到的数据
# print(el.group(1))
# 字符串替换,replace
old = el.group()
prop_name = el.group(1)
string = string.replace(old, str(getattr(Data, prop_name)))
print(string)
运行结果:
知识点: 1,getattr()获取类/对象的属性值 2,re.finditer返回所有符合正则表达式的子字符串 3,.*? 非贪婪模式返回0次 4,group()-正则表达式匹配的整个结果,默认索引0;group(1)-正则表达式匹配的结果当中第一个括号里面的内容
封装成函数:
import re
class data:
member_id = 123
money = 100
def replace_date(string):
"""给指定的字符串替换成动态的数据"""
result = re.finditer('#(.*?)#', string)
for el in result:
# el表示匹配到的数据
# print(el.group(1))
# 字符串替换,replace
old = el.group()
prop_name = el.group(1)
string = string.replace(old, str(getattr(Data, prop_name)))
return string
封装成函数以后,我们就可以使用正则表达式来实现动态数据替换了,可以优化前之前的审核接口代码,首先将封装方法(replace_date)放在base.py文件的ApiCase类当中,因为ApiCase已经被测试用例类继承了。
import requests
import re
from setting.config import host
from jsonpath import jsonpath
from setting.secret import user, admin_user
class ApiCase:
"""访问项目接口需要用到的独立的方法或者属性"""
@classmethod
def login(cls):
"""访问登录接口"""
url = host + '/member/login'
method = 'post'
headers = {"X-Lemonban-Media-Type": "lemonban.v2"}
data = user
login_resp = requests.request(method=method, url=url, headers=headers, json=data).json()
# print(login_resp)
# 获取 member_id和token
# cls.member_id = str(login_resp['data']['id'])
# cls.token = login_resp['data']['token_info']['token']
# 通过jsonpath获取
cls.member_id = str(jsonpath(login_resp, '$..id')[0])
cls.token = jsonpath(login_resp, '$..token')[0]
# cls.before_money = jsonpath(login_resp, '$..leave_amount')[0]
# return cls.member_id, cls.token
@classmethod
def admin_login(cls):
"""访问登录接口"""
url = host + '/member/login'
method = 'post'
headers = {"X-Lemonban-Media-Type": "lemonban.v2"}
data = admin_user
login_resp = requests.request(method=method, url=url, headers=headers, json=data).json()
# 通过jsonpath获取
cls.admin_member_id = str(jsonpath(login_resp, '$..id')[0])
cls.admin_token = jsonpath(login_resp, '$..token')[0]
@classmethod
def add_project(cls, token, member_id):
"""访问添加项目的接口"""
url = host + '/loan/add'
method = 'post'
headers = {"X-Lemonban-Media-Type": "lemonban.v2", "Authorization": f"Bearer {token}"}
json_data = {"member_id": member_id,
"amount": 100, "title": "小目标",
"loan_rate": 18, "loan_term": 5, "loan_date_type": 1, "bidding_days": 1}
login_resp = requests.request(method=method, url=url, headers=headers, json=json_data).json()
# 通过jsonpath获取
cls.loan_id = str(jsonpath(login_resp, '$..id')[0])
def audit(self, admin_token, loan_id):
"""审核项目的接口"""
pass
@classmethod
def replace_date(cls,string):
"""给指定的字符串替换成动态的数据"""
result = re.finditer('#(.*?)#', string)
for el in result:
# el表示匹配到的数据
# print(el.group(1))
# 字符串替换,replace
old = el.group()
prop_name = el.group(1)
string = string.replace(old, str(getattr(cls, prop_name)))
return string
优化test_audit.py中动态替换相关代码
# 替换请求体
# if '#loan_id#' in json_data:
# json_data = json_data.replace("#loan_id#", self.loan_id)
# # 替换请求头
# if '#admin_token#' in headers:
# headers = headers.replace("#admin_token#", self.admin_token)
json_data = self.replace_date(json_data)
headers = self.replace_date(headers)
import unittest
import requests
import json
from common.excel import read_excel
from ddt import ddt, data
from setting.config import config_file, host
from tests.base import ApiCase
# 得到测试数据
excel_data = read_excel(file=config_file, sheet_name='audit')
@ddt
class TestAudit(unittest.TestCase, ApiCase):
@classmethod
def setUpClass(cls) -> None:
'''测试用例需要的前置夹具,每个测试类只执行一次的前置
1.登录
2.获取充值接口需要的member_id和token
'''
# TestAudit继承ApiCase,cls.login(),对象可以获取类属性
# 普通用户登陆
cls.login()
# 管理员登陆
cls.admin_login()
def setUp(self) -> None:
# 添加项目
self.add_project(token=self.token, member_id=self.member_id)
def tearDown(self) -> None:
pass
@data(*excel_data)
def test_audit(self, info):
url = host + info['url']
json_data = info['json']
headers = info['headers']
# 替换请求体
# if '#loan_id#' in json_data:
# json_data = json_data.replace("#loan_id#", self.loan_id)
# # 替换请求头
# if '#admin_token#' in headers:
# headers = headers.replace("#admin_token#", self.admin_token)
json_data = self.replace_date(json_data)
headers = self.replace_date(headers)
# 将json数据转化为字典
json_data = json.loads(json_data)
headers = json.loads(headers)
expected = json.loads(info['expected'])
audit_resp = requests.request(method=info['method'],
url=url,
headers=headers,
json=json_data).json()
for key, value in expected.items():
self.assertEqual(value, audit_resp[key])
四.正则表达式的应用
注意事项:
1.在使用正则表达式ApiCase下的replace_data这个方法需要去使用两次,第一次是对jason请求体当中的数据进行替换,第二次是对headers中的数据进行替换。
2.调用这个方法之前,必须在ApiCase里设置同名属性。



