目次
序文:
インターフェイス自動テストでは、インターフェイスの戻り値のすべてのフィールドを迅速に検証することが重要なタスクです。ワンクリックの迅速な検証により、インターフェイスから返されたデータが期待を満たしているかどうかを効果的に検証し、潜在的な問題を適時に検出できます。
今日はまず、既存のサードパーティ ライブラリを使用して、 API インターフェイスから返されるすべてのフィールドを迅速に検証するという問題を解決する方法について説明します。現在のインターフェイスのほとんどは Restful API に基づいているため、その後の紹介では、インターフェイスの応答本文の形式が JSON を例として挙げていると仮定します。
上記の実装要件を満たすために、多くのサードパーティ ライブラリ ソリューションがあります。たとえば、一般的なものは次のとおりです:、、、などdeepdiff
。 これらのサードパーティ ライブラリにはそれぞれ独自の焦点があります。この記事では、DeepDiff の使用方法に焦点を当てdifflib
ます。解決するライブラリ クイック チェック インターフェイスによって返されるフィールドの問題。json-diff
json_tools
1. DeepDiff について知る
Deepdiff
モジュールは、2 つのオブジェクトが同一であることを確認し、それらの違いを見つけるためによく使用されます。DeepDiff、DeepSearch、DeepHash の 3 つのクラスを提供します。公式 Web サイトのアドレス: DeepDiff OLD 4.0.7 document! — DeepDiff 4.0.7 document 、最新バージョンは次のとおりです。V5.5.0
主成分:
-
DeepDiff: 2 つのオブジェクトを比較します。オブジェクトは、フィールドや文字列などの反復可能なオブジェクトにすることができます。オブジェクトの深い違いについては、すべての変更を再帰的に検索します。
-
DeepSearch: オブジェクトから他のオブジェクトを検索します。
-
DeepHash: オブジェクトの内容に基づいたハッシュ化
JSON
DeepDiff の本来の目的は、比較、XML
テキスト型、または比較できる異なるデータ間の違いを見つけることです。图片
しばらく使用した後、実際にテスト アサーションとして直接使用できます。これは別のデータからも提供されます。視点. 新しいチェック方法。
2. DeepDiffの使用
上記の紹介を読んでも、まだ混乱していて、どのように始めればよいかわからないと思います。次に、いくつかのケースを使用して、ソフトウェアの機能と機能をさらに体験してみましょうDeepdiff
。
使用する前に、以下をインストールしてください。
pip install deepdiff
2.1 ケース 1: 2 つの JSON を比較する
Deepdiff を使用して JSON の違いを比較します。
import pytest
import requests
import pprint
from deepdiff import DeepDiff
class TestDemo(object):
def test_case_01(self):
a = {"Object": {
"code": "0",
"message": "success"
},
"code": "0",
"message": "success"
}
b = {"Object": {
"code": "0",
"message": "failure"
},
"message": "success",
"timestamp": "1614301293"
}
pprint.pprint(DeepDiff(a, b))
上記の場合、関数は a と b の差を比較することであり、結果の差の出力結果は次のようになります。
.{'dictionary_item_added': [root['timestamp']],
'dictionary_item_removed': [root['code']],
'values_changed': {"root['Object']['message']": {'new_value': 'failure',
'old_value': 'success'}}}
上記の出力結果では、実際には返された json に従ってすべての差分が取得されます。主にオブジェクト間の値、型間の変更、削除または追加されたキーを比較して結果を出力します。
主に次の 4 つの状況が含まれます。
- 1. type_changes: 型変更のキー
- 2.values_changed: 値が変更されたキー
- 3.dictionary_item_added: 辞書キーが追加されました
- 4.dictionary_item_removed: フィールドキーが削除されました
2.2 ケース 2: インターフェースの応答の比較
ケース 1 に基づいて、さらに、ローカル定義のハードコーディングされた変数値を、リクエストを開始し、応答を取得し、 Deepdiff と組み合わせてアサートします。
中心となるアイデアは、まず期待される応答構造を定義し (つまり、期待される結果が何であるかを事前に知っておく必要があります)、次に実際に返された構造に基づいて 2 つをDeepdiff
自動的に比較します。
import pytest
import requests
import pprint
from deepdiff import DeepDiff
class TestDemo(object):
def setup_class(self):
self.response = requests.get('http://www.httpbin.org/json').json()
def test_case_02(self):
expected_reps = {'slideshow': {'author': 'Yours Truly', 'date': 'date of publication',
'slides': [{'title': 'Wake up to WonderWidgets!', 'type': 'all'}, {
'items': ['Why <em>WonderWidgets</em> are great',
'Who <em>buys</em> WonderWidgets'], 'title': 'Overview',
'type': 'all'}], 'title': 'Sample Slide Show'}}
pprint.pprint(DeepDiff(expected_reps, self.response))
実際に返される構造体は検証対象の期待される構造体データとまったく同じであるため、上記のコードの出力結果は次のようになります{},即两者没有差异
。(実際の結果と期待される結果が一致していることも意味します)
これに基づいて、上記のexpected_reps
予想される構造を変更しauthor
て再度実行すると、出力結果は次のようになります。Yours Truly
Yours
{'values_changed': {"root['slideshow']['author']": {'new_value': 'Yours Truly',
'old_value': 'Yours'}}}
上記の出力結果から、明らかに 3 つのメッセージが得られます。
- インターフェイスによって返される構造体の値が変更されました。これは
values_changed
、 - どのフィールドの値が変更されたかを明確に示します (例: )
root['slideshow']['author']
。 Yours Truly
実際の戻り値や期待値などの具体的な内容を変更しますYours
。
これを読んだ後、あなたはこの時点で、インターフェイスのテストでの Deepdiff の使用について、すでに何らかの感情を抱いていると思います。しかし、検証など、一部のインターフェイスによって返される値は固定されていないという疑問が生じるでしょう。たとえば、タイムスタンプ フィールドの場合、インターフェイスが呼び出されるたびに、返されるフィールドの値は異なります。このタイプのデータの場合、データ ルールのみがわかっており、データ自体の値は最初から決定できません。 . Deepdiffと組み合わせて使うには?心配しないで、下を見てください。
2.3 ケース 3: 通常の検索マッチング
上記の問題を解決するには、 の通常の検索マッチング関数を使用できますDeepSearch
。インターフェイスが深くネストされた構造オブジェクトを返し、指定された要素 (キーと値の両方) が存在するかどうかを確認したい場合、ディープ検索は良い選択。
使用する前に、最初にインポートする必要がありますfrom deepdiff import grep
。サンプル ソース コードは次のとおりです。
def test_case_03(self):
datas = {"mikezhou": "狂师", "age":18, "city": "china", "info": {"author": {"tag": "mikezhou"}}}
reuslt = datas | grep("mike*",use_regexp=True)
print(reuslt)
たとえば、返された構造体に mike で始まるフィールドまたは値があるかどうかを確認する場合、指定された要素が存在する場合はそのパスが返され、存在しない場合は空の辞書が返されます。上記の出力は次のようになります。
.{'matched_paths': ["root['mikezhou']"], 'matched_values': ["root['info']['author']['tag']"]}
上記の例は単純ですが、十分に賢い人であれば、そこから核となるアイデアを理解できるはずです。事前に予測できない一部の動的な値については、正規表現を使用して照合および検証できます。検証方法は、正規表現の記述方法によって異なります。
3. 最後のヒント: DeepDiff ブラックリスト
実際にインターフェイス テスト アサーションを実行するとき、オブジェクトの順序が異なる場合がありますが、実際の状況では 2 つの値が同じである場合や、フィールド全体をチェックするときに、特別なフィールドの検証 (この種の問題を解決するために、Deepdiff は、比較するときにのみ追加する必要がある信頼できるパラメーターも提供します。
ignore order
(並べ替えは無視します)ignore string case
(大文字と小文字を区別しない)exclude_paths
フィールド ブラックリストにはパラメーターが含まれません。プロトタイプは次のとおりです。
result = DeepDiff(result, expected, view='tree',ignore_order=True,ignore_string_case=True)
例:
def test_case_05(self):
expected_reps = {"datas": {
"code": "200",
"message": "success"
},
"code": "201",
"message": "success"
}
actual_reps = {"datas": {
"code": "201",
"message": "failure"
},
"message": "Success",
"timestamp": "1614301293"
}
pprint.pprint(DeepDiff(expected_reps, actual_reps, ignore_order=True,ignore_string_case=True,exclude_paths={"root['timestamp']"}))
上記のサンプル コードでは、照合順序と大文字小文字の問題を無視し、除外timestamp
フィールドの検証を指定しています。具体的な出力結果は以下の通りです。
{'dictionary_item_removed': [root['code']],
'values_changed': {"root['datas']['code']": {'new_value': '201',
'old_value': '200'},
"root['datas']['message']": {'new_value': 'failure',
'old_value': 'success'},
"root['message']": {'new_value': 'Success',
'old_value': 'success'}}}
4. まとめ
上記の事例紹介を通じて、DeepDiff
の使い方について基本的な理解ができたと思います。インターフェイス自動テストにおいて、DeepDiff を使用する利点を要約すると、次のとおりです。
- インターフェイスをテストする場合、予期される構造 (またはインターフェイス コントラクト) を直接使用して、実際に返された構造 (フィールド、値) を自動的に比較してそれらが同じかどうかを判断でき、大量のコードを節約できます。
- データベースのデータを比較する場合も同様で、SQL を使用して結果を調べた後、直接 JSON に変換し、予想される JSON と比較することができます。
ここに来た者として、皆さんも寄り道は避けていただきたいと思います。
ここでは、自動テストを進める上で必要なことをいくつか共有し、お役に立てれば幸いです。
(WEB自動テスト、アプリ自動テスト、インターフェース自動テスト、継続的インテグレーション、自動テスト開発、工場面接の大きな質問、履歴書テンプレートなど)
そうすることでより良い進歩が見込めると信じています!
下の小さなカードをクリックしてください