Regular use case parameterization of Python interface automation

foreword

​When we are doing interface automation, we usually use regular expressions to extract relevant data when dealing with the relevant data that the interface depends on.

​ Regular expression, also known as regular expression, regular expression, regular expression, regular expression, regular expression (Regular Expression, often abbreviated as regex, regexp or RE in code). It is a special character sequence that helps you easily check whether a string matches a certain pattern. In many text editors, regular expressions are often used to retrieve and replace text that matches a certain pattern. Python has added the re module since version 1.5, which provides Perl-style regular expression patterns.

1. Regular expression syntax

1.1 represents a single character

​ Single character: means a single character, for example, \d is used to match numbers, and \D is used to match non-numbers.

​ In addition to the following syntax, you can also match specified specific characters, which can be one or more.

The example is as follows, here is a description of findall (matching rules, the string to be matched) This method is to find all the matching data and return it in the form of a list, which will be explained later in the re module :

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']

 1.2 Indicates the quantity

​ If you want to match a certain character multiple times, you can add the number after the character to indicate, the specific rules are as follows:

​ Examples are as follows:

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']

  1.2.1 Match grouping

​Instances  are as follows:

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']

 1.3 Representing boundaries

​ Examples are as follows:

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']

 2. Greedy mode

Quantifiers in python are greedy by default, and always try to match as many characters as possible, while the non-greedy mode tries to match as few characters as possible, and adding a question mark (?) after the expression indicating the quantity can turn off greed model.

​ The following example matches more than 2 numbers. If it meets the conditions, it will match until it does not match. For example, 34656fya, 34656 matches more than 2 numbers, then it will match until 6. If the greedy mode is turned off, Then it will stop when it meets 2 numbers, and finally it can match 34 and 65.

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']

Three, re module

​ When using regular expressions in python, the re module will be used for operations. The methods provided generally require two parameters to be passed in:

  • Parameter 1: The matching rule
  • Parameter 2: The string to be matched

3.1 re.findall()

​ Find all strings that meet the specification and return them as a list.

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

3.2re.search()

​ Find the first string that meets the specification, and return a matching object, and the matched data can be directly extracted through group().

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

​ In the returned matching object, span is the subscript range of the matched data, and match is the matched value.

​ group() parameter description:

  • No parameters are passed: all the matched content is obtained
  • Incoming value: It can be specified by parameters to get the content of the first group (get the first group, pass in parameter 1, get the second group, pass in parameter 2, and so on.)
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))

3.3 re.match()

​ Match from the starting position of the string, and return the matched object if the matching is successful. If the starting position does not meet the matching rules, it will not continue to match and return None directly. Both re.match() and re.search() match only one. The difference is that the former only matches the beginning of the string, while the latter matches the entire string, but only gets the first matching data.

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

3.4re.sub()

​ Retrieve and replace: used to replace matches in a string

​ re.sub() parameter description:

  • Parameter 1: the string to be replaced
  • Parameter 2: target string
  • Parameter 3: The string to be replaced
  • Parameter 4: You can specify the maximum number of replacements, which is not required (by default, all strings that meet the specification are replaced)
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

4. Use case parameterization

​In the interface automation test, our test data is stored in excel. If some parameters are written to death, they may not be available in a different scene or environment. When switching environments, we need to test the new environment first. The data is ready and can support running our scripts, or modify the excel data to test data suitable for the new environment, and the maintenance cost is relatively high. Therefore, we need to parameterize our automated script test data as much as possible to reduce maintenance costs.

Let’s first look at the parameterization of the simple version. Taking login as an example, the account number, password and other information used for login can be extracted and placed in the configuration file. When modifying data or changing the environment, it can be directly modified in the configuration file.

 

​ But if there are multiple different data that need to be parameterized, should each parameter add a judgment to replace the data? Such code is long-winded and difficult to maintain. At this time, the re module can be used. Let's look at an example directly:

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

​ Note that the regular expression here is used? Turn off the greedy mode, because the test data may need to parameterize 2 or more data, if the greedy mode is not turned off, it can only match and match one data, for example:

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

In addition, a class for temporarily saving data is mentioned, which is mainly used to save the data returned by the interface, because some test data changes dynamically and may depend on a certain interface, and later test cases need these data, then When the interface returns, we can save it in this class as a class attribute, and then extract this class attribute and replace it in the test data when we need a test case that uses this data. Tip: set the attribute setattr (object, attribute name, attribute value), get the attribute value getattr (object, attribute name).

Finally, I would like to thank everyone who has read my article carefully. Reciprocity is always necessary. Although it is not a very valuable thing, you can take it away if you need it:

insert image description here

Software testing interview applet

The software test question bank maxed out by millions of people! ! ! Who is who knows! ! ! The most comprehensive quiz mini program on the whole network, you can use your mobile phone to do the quizzes, on the subway or on the bus, roll it up!

The following interview question sections are covered:

1. Basic theory of software testing, 2. web, app, interface function testing, 3. network, 4. database, 5. linux

6. web, app, interface automation, 7. performance testing, 8. programming basics, 9. hr interview questions, 10. open test questions, 11. security testing, 12. computer basics

These materials should be the most comprehensive and complete preparation warehouse for [software testing] friends. This warehouse has also accompanied tens of thousands of test engineers through the most difficult journey. I hope it can help you too!  

Guess you like

Origin blog.csdn.net/qq_48811377/article/details/132428529