[Python interface automation] - regular use case parameterization

miki_ peng 2021-02-22 11:20:30
python interface automation regular use


​ When we do interface automation , When dealing with related data that the interface depends on , Regular expressions are usually used to extract relevant data .

​ Regular expressions , Also known as normal expression 、 Normal representation 、 Normal expression 、 Regular expressions 、 Conventional representation (Regular Expression, In code it is often abbreviated as regex、regexp or RE) . It's a special sequence of characters , It can help you easily check whether a string matches a certain pattern . In many text editors , Regular expressions are often used for retrieval 、 Replace the text that matches a pattern . and Python since 1.5 Version has been added re modular , It provides Perl Style regular expression pattern .

regular expression syntax

Represents a single character

​ A single character : It means a single character , Like matching numbers with \d, Match non numbers with \D.

​ Except for the following syntax , You can also match specific characters specified , It can be 1 One or more .

character Functional specifications
. Match arbitrarily 1 Characters ( except \n)
[2a] matching [] The characters listed in brackets , So here's the match 2 perhaps a One of these two characters
\d Match the Numbers , namely 0-9
\D Match non numeric
\s Match blanks , That is, the space 、tab key (tab The key is two spaces )
\S Match non blank
\w Match word characters , namely a-z、A-Z、0-9、_( Numbers 、 Letter 、 Underline )
\W Match non word characters

​ Examples are as follows , Let's start with findall( Matching rules , String to match ) This method is to find all the matching data , Return... As a list , It'll be later re Module for detailed explanation :

import re
# .: Match arbitrarily 1 Characters
re1 = r'.'
res1 = re.findall(re1, '\nj8?0\nbth\nihb')
print(res1) # Running results :['j', '8', '?', '0', 'b', 't', 'h', 'i', 'h', 'b']
# []: Match one of the enumerations
re2 = r"[abc]"
res2 = re.findall(re2, '1iugfiSHOIFUOFGIDHFGFD2345a6a78b99cc')
print(res2) # Running results :['a', 'a', 'b', 'c', 'c']
# \d: Match a number
re3 = r"\d"
res3 = re.findall(re3, "dfghjkl32212dfghjk")
print(res3) # Running results :['3', '2', '2', '1', '2']
# \D: Match a non number
re4 = r"\D"
res4 = re.findall(re4, "d212dk?\n$%3;]a")
print(res4) # Running results :['d', 'd', 'k', '?', '\n', '$', '%', ';', ']', 'a']
# \s: Match a blank key or tab key (tab The key is actually two blank keys )
re5 = r"\s"
res5 = re.findall(re5,"a s d a 9999")
print(res5) # Running results :[' ', ' ', ' ', ' ', ' ']
# \S: Match non blank keys
re6 = r"\S"
res6 = re.findall(re6, "a s d a 9999")
print(res6) # Running results :['a', 's', 'd', 'a', '9', '9', '9', '9']
# \w: Match a word character ( Numbers 、 Letter 、 Underline )
re7 = r"\w"
res7 = re.findall(re7, "ce12sd@#a as_#$")
print(res7) # Running results :['c', 'e', '1', '2', 's', 'd', 'a', 'a', 's', '_']
# \W: Match a non word character ( Not numbers 、 Letter 、 Underline )
re8 = r"\W"
res8 = re.findall(re8, "ce12sd@#a as_#$")
print(res8) # Running results :['@', '#', ' ', '#', '$']
# Matches the specified character
re9 = r"python"
res9 = re.findall(re9, "cepy1thon12spython123@@python")
print(res9) # Running results :['python', 'python']

It means quantity

​ If you want to match a character more than once , You can add a number after the character to indicate , The specific rules are as follows :

character Functional specifications
* Match previous character appears 0 Times or infinite times , You can have it or not
+ Match previous character appears 1 Times or infinite times , At least 1 Time
? Match previous character appears 0 Time or 1 Time , That is, either there is no , Or only 1 Time
{m} Match previous character appears m Time
{m,} Match the previous character at least m Time
{m,n} Match previous character appears from m To n Time

​ Examples are as follows :

import re
# *: Indicates that the previous character appears 0 More than once ( Include 0 Time )
re21 = r"\d*" # The matching rules here , The previous character is a number
res21 = re.findall(re21, "343aa1112df345g1h6699") # If it matches a when , Belong to conform to 0 Time , But because there is no value, it will be empty
print(res21) # Running results :['343', '', '', '1112', '', '', '345', '', '1', '', '6699', '']
# ? : Express 0 Once or once
re22 = r"\d?"
res22 = re.findall(re22, "3@43*a111")
print(res22) # Running results :['3', '', '4', '3', '', '', '1', '1', '1', '']
# {m}: To match a character m Time
re23 = r"1[3456789]\d{9}" # cell-phone number : The first 1 Position as 1, The first 2 Bit matching is one of the 1 A digital , The first 3 Bits start with numbers , And match 9 Time
res23 = re.findall(re23,"sas13566778899fgh256912345678jkghj12788990000aaa113588889999")
print(res23) # Running results :['13566778899', '13588889999']
# {m,}: Means to match a character at least m Time
re24 = r"\d{7,}"
res24 = re.findall(re24, "sas12356fgh1234567jkghj12788990000aaa113588889999")
print(res24) # Running results :['1234567', '12788990000', '113588889999']
# {m,n}: Indicates that a matching character appears m Time to n Time
re25 = r"\d{3,5}"
res25 = re.findall(re25, "aaaaa123456ghj333yyy77iii88jj909768876")
print(res25) # Running results :['12345', '333', '90976', '8876']

Match groups

character Functional specifications
| Match any expression left or right
(ab) Use the characters in brackets as a group

​ Examples are as follows :

import re
# Define multiple rules at the same time , Just satisfy one of them
re31 = r"13566778899|13534563456|14788990000"
res31 = re.findall(re31, "sas13566778899fgh13534563456jkghj14788990000")
print(res31) # Running results :['13566778899', '13534563456', '14788990000']
# (): Match groups : Extract the data in brackets from the data of the matching rule
re32 = r"aa(\d{3})bb" # How data fits the rules , The result will only take the data in brackets , namely \d{3}
res32 = re.findall(re32, "ggghjkaa123bbhhaa672bbjhjjaa@45bb")
print(res32) # Running results :['123', '672']

Represent boundary

character Functional specifications
^ Match the beginning of a string , You can only match the beginning
$ Match string end , Can only match the end
\b Match the boundary of a word ( word : Letter 、 Numbers 、 Underline )
\B Match non word boundaries

​ Examples are as follows :

import re
# ^: Match the beginning of the string
re41 = r"^python" # The string begins with python
res41 = re.findall(re41, "python999python") # It only matches the beginning of the string
res411 = re.findall(re41, "1python999python") # Because it starts with 1, The first 1 It doesn't fit
print(res41) # Running results :['python']
print(res411) # Running results :[]
# $: Match the end of the string
re42=r"python$" # String to python ending
res42 = re.findall(re42, "python999python")
print(res42) # Running results :['python']
# \b: Match the boundaries of words , Words are : Letter 、 Numbers 、 Underline
re43 = r"\bpython" # Match python, And python Is the first word of the word
res43 = re.findall(re43, "1python 999 python") # Here I 1 individual python Before 1 Bits are words , So the first 1 It's not a match
print(res43) # Running results :['python']
# \B: Match non word boundaries
re44 = r"\Bpython" # Match python, And python The first word in English is the word
res44 = re.findall(re44, "1python999python")
print(res44) # Running results :['python', 'python']

Greedy mode

​ python The quantifier is greedy by default , Always try to match as many characters as possible , The non greedy pattern is trying to match as few characters as possible , Add a question mark after the expression for quantity (?) You can turn off greedy mode .

​ The following example , matching 2 More than one number , If it meets the criteria, it will match until it doesn't , Such as 34656fya,34656 accord with 2 More than a number , So it will match all the way to 6 until , If you turn off greedy mode , So in satisfaction 2 It stops when it reaches a number , In the end, we can match 34、65.

import re
# In the default greedy mode
test = 'aa123aaaa34656fyaa12a123d'
res = re.findall(r'\d{2,}', test)
print(res) # Running results :['123', '34656', '12', '123']
# Turn off greedy mode
res2 = re.findall(r'\d{2,}?', test)
print(res2) # Running results :['12', '34', '65', '12', '12']

re modular

​ stay python Using regular expressions , Will be used re Module to operate , The method provided usually needs to pass in two parameters :

  • Parameters 1: Matching rules
  • Parameters 2: The string to match

re.findall()

​ Find all the strings that match the specification , Return... As a list .

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

re.search()

​ Find the first qualified string , What is returned is a matching object , Can pass group() Extract the matched data directly .

import re
s = "123abc123aaa123bbb888ccc"
res2 = re.search(r'123', s)
print(res2) # Running results :<re.Match object; span=(0, 3), match='123'>
# adopt group Extract the matched data , The return type is str
print(res2.group()) # Running results :123

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

group() Parameter description

  • Don't pass parameters : What you get is all the content that matches
  • Pass in the value : You can specify... By parameters , Get the content in the number of groups ( For the first 1 Groups , Pass in the parameter 1, For the first 2 Groups , Pass in the parameter 2, By analogy .)
import re
s = "123abc123aaa123bbb888ccc"
re4 = r"aaa(\d{3})bbb(\d{3})ccc" # Here grouping is the matching syntax mentioned above :()
res4 = re.search(re4, s)
print(res4)
# group Don't pass parameters : What you get is all the content that matches
# group Specify... By parameters , Get the content in the number of groups ( For the first 1 Groups , Pass in the parameter 1, For the first 2 Groups , Pass in the parameter 2, By analogy ..
print(res4.group())
print(res4.group(1))
print(res4.group(2))

re.match()

​ Match from the beginning of the string , If the match is successful, the matching object will be returned , If the position of the beginning doesn't match the matching rule , It's not going to go back and match , Go straight back to None.re.match() And re.search() It's all about matching only one , The difference is , The former only matches the beginning of the string , The latter matches the entire string , But only get the first match .

import re
s = "a123abc123aaa1234bbb888ccc"
# match: Match only the beginning of the string , If the beginning does not match, return None
res1 = re.match(r"a123", s)
res2 = re.match(r"a1234", s)
print(res1) # Running results :<re.Match object; span=(0, 4), match='a123'>
print(res2) # Running results :None

re.sub()

​ Search and replace : Used to replace matches in strings

re.sub() Parameter description

  • Parameters 1: String to be replaced
  • Parameters 2: Target string
  • Parameters 3: The string to replace
  • Parameters 4: You can specify the maximum number of substitutions , Not required ( By default, all strings that meet the specifications are replaced )
import re
s = "a123abc123aaa123bbb888ccc"
# <font color="#FF0000"> Parameters 1:</font> String to be replaced
# <font color="#FF0000"> Parameters 2:</font> Target string
# <font color="#FF0000"> Parameters 3:</font> The string to replace
# <font color="#FF0000"> Parameters 4:</font> You can specify the maximum number of substitutions , Not required ( By default, all strings that meet the specifications are replaced )
res5 = re.sub(r'123', "666", s, 4)
print(res5) # Running results :a666abc666aaa666bbb888ccc

Use case parameterization

​ In the interface automation test , Our test data is stored in excel Medium , Some parameters if you write a dead data , Maybe it can't be used in a different scene or environment , When switching environments, you need to prepare the test data of the new environment first , And can support to run our script , Or the excel Change the test data of to fit the new environment , The cost of maintenance is high . Therefore, we need to parameterize our automated script test data as much as possible , Reduce maintenance costs .

​ Let's start with the simple version of parameterization , Take logging, for example , The account used to log in 、 Password and other information can be extracted and put into the configuration file , When modifying the data or changing the environment, you can modify it directly in the configuration file .

​ But if there are many different data that need to be parameterized , Does each parameter add a judgment to replace the data ? This kind of code is tedious and hard to maintain , At this time re The module can be used , Let's look at an example :

import re
from common.myconfig import conf
class TestData:
""" It is used to temporarily save some data to be replaced """
pass
def replace_data(data):
r = r"#(.+?)#" # Pay attention to this group () Internal content
# Determine if there is any data that needs to be replaced
while re.search(r, data):
res = re.search(r, data) # Match the first data to be replaced
item = res.group() # Extract the data content to be replaced
key = res.group(1) # Get the data item in the content to be replaced
try:
# Find the corresponding content in the configuration file according to the data item in the replacement content , Replace
data = data.replace(item, conf.get_str("test_data", key))
except:
# If you can't find it in the configuration file, find it in the temporarily saved data , Then replace
data = data.replace(item, getattr(TestData, key))
return data

​ Note that regular expressions are used here ? Turn off greedy mode , Because the test data may need to be parameterized 2 More than one data , If you don't turn off greedy mode , It can only match one data , Examples are as follows :

import re
data = '{"mobile_phone":"#phone#","pwd":"#pwd#","user":#user#}'
r1 = "#(.+)#"
res1 = re.findall(r1, data)
print(res1) # Running results :['phone#","pwd":"#pwd#","user":#user'] Note that there is only one data in a single quotation mark
print(len(res1)) # Running results :1
r2 = "#(.+?)#"
res2 = re.findall(r2, data)
print(res2) # Running results :['phone', 'pwd', 'user']
print(len(res2)) # Running results :3

​ Also mentioned is a class for temporarily saving data , This is mainly used to save the data returned by the interface , Because some test data is dynamic , It might depend on an interface , Later test cases need this data , Then we can save it as a class property when the interface returns , And then when you need a test case that uses this data , Just extract this class attribute and replace it in the test data . Tips : Set properties setattr( object , Property name , Property value ), Get attribute value getattr( object , Property name ).

版权声明
本文为[miki_ peng]所创,转载请带上原文链接,感谢
https://pythonmana.com/2021/02/20210221113602384z.html

  1. Detailed usage of urllib in Python 3 (header, proxy, timeout, authentication, exception handling)
  2. python 第三方库paramiko
  3. python 第三方库paramiko
  4. Python third party library paramiko
  5. Python third party library paramiko
  6. 卸载 PyCharm!这才是 Python 小白的最理想的 IDE
  7. 卸载 PyCharm!这才是 Python 小白的最理想的 IDE
  8. Uninstall pycharm! This is the ideal IDE for Python Xiaobai
  9. django学习-27.admin管理后台里:对列表展示页面的数据展示进行相关优化
  10. Uninstall pycharm! This is the ideal IDE for Python Xiaobai
  11. Django learning - 27. Admin management background: optimize the data display of the list display page
  12. python day2
  13. python day2
  14. Python 内存泄漏问题排查
  15. Troubleshooting of Python memory leak
  16. Python 与 excel的简单应用
  17. Simple application of Python and excel
  18. Python 与 excel的简单应用
  19. Simple application of Python and excel
  20. 2.7万 Star!最全面的 Python 设计模式集合
  21. 27000 stars! The most comprehensive collection of Python design patterns
  22. python day3
  23. python day3
  24. Commonly used data operation functions of Python
  25. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)
  26. (learning notes of data science 108) Python + dash rapid web application development -- static components (I)
  27. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)
  28. (learning notes of data science 108) Python + dash rapid web application development -- static components (I)
  29. [Python] Matplotlib 图表的绘制和美化技巧
  30. Drawing and beautifying skills of [Python] Matplotlib chart
  31. [Python] Matplotlib 图表的绘制和美化技巧
  32. Drawing and beautifying skills of [Python] Matplotlib chart
  33. Virtual environment of Python project
  34. 翻译:《实用的Python编程》02_01_Datatypes
  35. Translation: practical Python Programming 02_ 01_ Datatypes
  36. 翻译:《实用的Python编程》02_01_Datatypes
  37. 翻译:《实用的Python编程》02_01_Datatypes
  38. Translation: practical Python Programming 02_ 01_ Datatypes
  39. Translation: practical Python Programming 02_ 01_ Datatypes
  40. Python 3 入门,看这篇就够了
  41. Python 3 entry, see this is enough
  42. 华为大佬打造的400集Python视频学起来,学完万物皆可爬
  43. 400 episodes of Python video created by Huawei boss
  44. django之csrf_exempt解决跨域请求的问题
  45. CSRF of Django_ Exempt solves the problem of cross domain requests
  46. 1.7 万 Star!一个简单实用的 Python 进度条库
  47. 17000 stars! A simple and practical Python progress bar library
  48. Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租
  49. Python crawler: setting cookie to solve website interception and crawling ant short rent
  50. Python-Net编程
  51. Python net programming
  52. 学习Python数学英语基础重要吗?Python教程!
  53. Is it important to learn the basics of math and English in Python!
  54. Python数据分析常用库有哪些?Python学习!
  55. What are the common libraries for Python data analysis? Learn Python!
  56. win 创建python虚拟环境
  57. Creating Python virtual environment with win
  58. In order to automatically collect B station barrage, I developed a tool in Python
  59. 用Python编程语言来实现阿姆斯特朗数的检查
  60. Using python programming language to check Armstrong number