内容:ガイド
序文
インターフェイスの自動化を行う場合、インターフェイスが依存する関連データを処理する場合、通常は正規表現を使用して関連データを抽出します。
正規表現。正規表現、正規表現、正規表現、正規表現、正規表現とも呼ばれます (正規表現。コードでは regex、regexp、または RE と略されることがよくあります)。
これは、文字列が特定のパターンに一致するかどうかを簡単に確認するのに役立つ特別な文字シーケンスです。多くのテキスト エディタでは、特定のパターンに一致するテキストを取得および置換するために正規表現がよく使用されます。
正規表現構文
単一文字を示します。
単一文字: 単一文字を意味します。たとえば、\d は数値の一致に使用され、\D は数字以外の一致に使用されます。
次の構文に加えて、1 つ以上の指定された特定の文字と一致することもできます。
キャラクター | 機能の説明 |
---|---|
。 | 任意の 1 文字と一致します (\n を除く) |
[2a] | [] 角括弧内にリストされている文字と一致します。たとえば、2 文字または a のいずれかと一致します。 |
\d | 数字、つまり 0 ~ 9 を照合します |
\D | 数字以外の一致 |
\s | 空白、つまりスペース、タブ キーと一致します (タブ キーは 2 つのスペースです) |
\S | 空白以外の一致 |
\w | 単語の文字に一致します。つまり、az、AZ、0-9、_ (数字、文字、アンダースコア) |
\W | 単語以外の文字に一致します |
例は次のとおりです。ここでは、findall (一致ルール、一致する文字列) の説明を示します。このメソッドは、一致するすべてのデータを検索し、リストの形式で返します。これについては、re モジュールで後ほど説明します。 :
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 回一致します |
例は次のとおりです。
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']
マッチグループ
キャラクター | 機能の説明 |
---|---|
私 | 左または右の任意の式に一致します |
(アブ) | 括弧内の文字をグループとして扱います |
例は次のとおりです。
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 | 単語以外の境界に一致する |
例は次のとおりです。
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 の数量指定子はデフォルトで貪欲です。常に可能な限り多くの文字と一致しようとします。非貪欲モードでは、できるだけ少ない文字と一致しようとします。数量を示す式に疑問符 (?) を追加すると、量をオフにできます。貪欲モード。
次の例は、3 つ以上の数値と一致します。条件を満たしている場合は、一致しなくなるまで一致します。たとえば、34656fya、34656 は 2 つ以上の数値と一致し、その後は 6 まで一致します。貪欲モードがオフになっている場合は、 , その後、2 つの数字に一致すると停止し、最終的には 34 と 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']
再モジュール
Python で正規表現を使用する場合、操作には re モジュールが使用されます。提供されるメソッドには通常、次の 2 つのパラメータを渡す必要があります。
パラメータ 1: 一致ルール
パラメータ 2: 一致する文字列
re.findall()
仕様に一致するすべての文字列を検索し、リストとして返します。
import re
test = 'aa123aaaa34656fyaa12a123d'
res = re.findall(r'\d{2,}', test)
print(res) # 运行结果:['123', '34656', '12', '123']
re.search()
仕様を満たす最初の文字列を検索し、一致するオブジェクトを返します。一致したデータは、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
返された一致オブジェクトでは、span は一致したデータの添え字範囲、match は一致した値です。
group() パラメータの説明:
パラメータは渡されません: 一致したすべてのコンテンツが取得されます
受信値: 最初のグループの内容を取得するためにパラメーターで指定できます (最初のグループを取得し、パラメーター 1 を渡し、2 番目のグループを取得し、パラメーター 2 を渡します。など)。
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))
再戦()
文字列の開始位置から照合し、照合に成功した場合は一致したオブジェクトを返します。開始位置が照合ルールを満たしていない場合は、照合は続行されず、直接 None が返されます。re.match() と re.search() は両方とも 1 つのみに一致しますが、前者は文字列の先頭のみに一致するのに対し、後者は文字列全体に一致しますが、最初に一致したデータのみを取得するという違いがあります。
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: 指定可能置換の最大数、必須ではありません (デフォルトでは、仕様を満たすすべての文字列が置換されます)
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 モジュールを使用できます。例を直接見てみましょう:
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 つ以上のデータをパラメータ化する必要がある場合があるため、グリーディ モードがオフになっていない場合は、1 つのデータのみを照合および照合できます。次に例を示します。
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 (オブジェクト、属性名) を取得します。
以下は、私がまとめた 2023 年の最も完全なソフトウェア テスト エンジニア学習知識アーキテクチャ システム図です。 |
1. Pythonプログラミングの入門から習得まで
2.インターフェース自動化プロジェクトの実戦
3. Web自動化プロジェクトの実戦
4. アプリ自動化プロジェクトの実戦
5. 一流メーカーの再開
6. DevOps システムのテストと開発
7. 一般的に使用される自動テストツール
8、JMeterのパフォーマンステスト
9. まとめ(最後にちょっとしたサプライズ)
浮き沈みを受け入れ、栄光に向かって行進し、闘争は夢を実現するリズムです。困難を恐れず勇敢に前進し、汗を胸に花に水を注ぎましょう。自分の力を信じ、無限の可能性を開花させ、自分だけの素晴らしい人生を創造し、忘れられない輝きを生み出しましょう。
平凡を拒否し、卓越性を追求し、闘争は心を奮い立たせる火です。出航し、前進し、努力して成功への道を切り開きます。粘り強さを信じて課題に立ち向かいましょう。
決意は火のようなもので、夢を追い、闘争は燃えるような粘り強さの原動力です。情熱を手放し、限界を超え、ハードワークで人生の素晴らしい章を書きましょう。奇跡を信じ、挑戦し、あらゆる努力を運命を変えるチャンスにして、自分だけの輝きを咲かせましょう!