Skip to content
Snippets Groups Projects
Commit c0d3b416 authored by Krzysztof Mochocki's avatar Krzysztof Mochocki
Browse files

Add comparsion function for REST request

parent 310b2539
No related branches found
No related tags found
1 merge request!256Add comparsion function for REST request
import os import os
import csv import csv
from difflib import SequenceMatcher from difflib import SequenceMatcher
from pathlib import Path
from time import perf_counter as perf from time import perf_counter as perf
from typing import Any
import deepdiff import deepdiff
import re import re
...@@ -15,7 +17,7 @@ class NoResultException(Exception): ...@@ -15,7 +17,7 @@ class NoResultException(Exception):
# of result json when comparing with pattern - only one per test (ignore_tags should # of result json when comparing with pattern - only one per test (ignore_tags should
# be a string denoting predefined situation), exclusive with regular (not predefined) # be a string denoting predefined situation), exclusive with regular (not predefined)
# tags (in normal case ignore_tags must be a list of tag specifiers) # tags (in normal case ignore_tags must be a list of tag specifiers)
predefined_ignore_tags = { predefined_ignore_tags: dict[str, re.Pattern] = {
'<bridge post>' : re.compile(r"root\['post_id'\]"), '<bridge post>' : re.compile(r"root\['post_id'\]"),
'<bridge posts>' : re.compile(r"root\[\d+\]\['post_id'\]"), '<bridge posts>' : re.compile(r"root\[\d+\]\['post_id'\]"),
'<bridge discussion>' : re.compile(r"root\[.+\]\['post_id'\]"), '<bridge discussion>' : re.compile(r"root\[.+\]\['post_id'\]"),
...@@ -31,12 +33,13 @@ predefined_ignore_tags = { ...@@ -31,12 +33,13 @@ predefined_ignore_tags = {
'<database votes>' : re.compile(r"root\['votes'\]\[\d+\]\['id'\]"), '<database votes>' : re.compile(r"root\['votes'\]\[\d+\]\['id'\]"),
'<follow blog>' : re.compile(r"root\[\d+\]\['comment'\]\['post_id'\]"), # follow_api.get_blog '<follow blog>' : re.compile(r"root\[\d+\]\['comment'\]\['post_id'\]"), # follow_api.get_blog
'<tags posts>' : re.compile(r"root\[\d+\]\['post_id'\]"), '<tags posts>' : re.compile(r"root\[\d+\]\['post_id'\]"),
'<tags post>' : re.compile(r"root\['post_id'\]") # tags_api.get_discussion '<tags post>' : re.compile(r"root\['post_id'\]"), # tags_api.get_discussion
'<hafbe cache_update>' : re.compile(r"root\['votes_updated_at'\]") # witness api in haf_block_explorer
} }
def get_overlap(s1, s2): def get_overlap(s1, s2):
s = SequenceMatcher(None, s1, s2) s = SequenceMatcher(None, s1, s2)
pos_a, pos_b, size = s.find_longest_match(0, len(s1), 0, len(s2)) pos_a, pos_b, size = s.find_longest_match(0, len(s1), 0, len(s2))
return s1[pos_a:pos_a+size] if pos_b == 0 else "" return s1[pos_a:pos_a+size] if pos_b == 0 else ""
def json_pretty_string(json_obj): def json_pretty_string(json_obj):
...@@ -90,15 +93,15 @@ def get_time(test_id): ...@@ -90,15 +93,15 @@ def get_time(test_id):
def compare_response_with_pattern(response, method=None, directory=None, ignore_tags=None, error_response=False, benchmark_time_threshold=None, allow_null_response=False): def compare_response_with_pattern(response, method=None, directory=None, ignore_tags=None, error_response=False, benchmark_time_threshold=None, allow_null_response=False):
""" This method will compare response with pattern file """ """ This method will compare response with pattern file """
test_fname, _ = os.getenv('PYTEST_CURRENT_TEST').split("::") test_fname, _ = os.getenv('PYTEST_CURRENT_TEST').split("::")
test_dir = os.getenv("TAVERN_DIR", "") test_dir = os.getenv("TAVERN_DIR", "")
overlap = get_overlap(test_dir, test_fname) overlap = get_overlap(test_dir, test_fname)
test_fname = test_dir + "/" + test_fname.replace(overlap, "") test_fname = test_dir + "/" + test_fname.replace(overlap, "")
test_fname = test_fname.replace(TEST_FILE_EXT, "") test_fname = test_fname.replace(TEST_FILE_EXT, "")
response_fname = test_fname + RESPONSE_FILE_EXT response_fname = test_fname + RESPONSE_FILE_EXT
pattern_fname = test_fname + PATTERN_FILE_EXT pattern_fname = test_fname + PATTERN_FILE_EXT
tavern_disable_comparator = bool(os.getenv('TAVERN_DISABLE_COMPARATOR', False)) tavern_disable_comparator = bool(os.getenv('TAVERN_DISABLE_COMPARATOR', False))
if os.path.exists(response_fname) and not tavern_disable_comparator: if os.path.exists(response_fname) and not tavern_disable_comparator:
...@@ -119,7 +122,7 @@ def compare_response_with_pattern(response, method=None, directory=None, ignore_ ...@@ -119,7 +122,7 @@ def compare_response_with_pattern(response, method=None, directory=None, ignore_
if ignore_tags is not None: if ignore_tags is not None:
assert isinstance(ignore_tags, list), "ignore_tags should be list of tags" assert isinstance(ignore_tags, list), "ignore_tags should be list of tags"
# disable comparison with pattern on demand and save # disable comparison with pattern on demand and save
if tavern_disable_comparator: if tavern_disable_comparator:
if error is not None: if error is not None:
save_json(response_fname, error) save_json(response_fname, error)
...@@ -168,16 +171,16 @@ def compare_response_with_pattern(response, method=None, directory=None, ignore_ ...@@ -168,16 +171,16 @@ def compare_response_with_pattern(response, method=None, directory=None, ignore_
def has_valid_response(response, method=None, directory=None, error_response=False, response_fname=None, benchmark_time_threshold=None): def has_valid_response(response, method=None, directory=None, error_response=False, response_fname=None, benchmark_time_threshold=None):
test_fname, _ = os.getenv('PYTEST_CURRENT_TEST').split("::") test_fname, _ = os.getenv('PYTEST_CURRENT_TEST').split("::")
test_dir = os.getenv("TAVERN_DIR", "") test_dir = os.getenv("TAVERN_DIR", "")
overlap = get_overlap(test_dir, test_fname) overlap = get_overlap(test_dir, test_fname)
test_fname = test_dir + "/" + test_fname.replace(overlap, "") test_fname = test_dir + "/" + test_fname.replace(overlap, "")
test_fname = test_fname.replace(TEST_FILE_EXT, "") test_fname = test_fname.replace(TEST_FILE_EXT, "")
response_fname = test_fname + RESPONSE_FILE_EXT response_fname = test_fname + RESPONSE_FILE_EXT
tavern_disable_comparator = bool(os.getenv('TAVERN_DISABLE_COMPARATOR', False)) tavern_disable_comparator = bool(os.getenv('TAVERN_DISABLE_COMPARATOR', False))
if os.path.exists(response_fname) and not tavern_disable_comparator: if os.path.exists(response_fname) and not tavern_disable_comparator:
os.remove(response_fname) os.remove(response_fname)
...@@ -191,7 +194,7 @@ def has_valid_response(response, method=None, directory=None, error_response=Fal ...@@ -191,7 +194,7 @@ def has_valid_response(response, method=None, directory=None, error_response=Fal
correct_response = result correct_response = result
# disable coparison with pattern on demand # disable coparison with pattern on demand
# and save # and save
if tavern_disable_comparator: if tavern_disable_comparator:
test_id = response_json.get("id", None) test_id = response_json.get("id", None)
if error is not None: if error is not None:
...@@ -207,3 +210,31 @@ def has_valid_response(response, method=None, directory=None, error_response=Fal ...@@ -207,3 +210,31 @@ def has_valid_response(response, method=None, directory=None, error_response=Fal
if correct_response is None: if correct_response is None:
msg = "Error detected in response: result is null, json object was expected" msg = "Error detected in response: result is null, json object was expected"
raise NoResultException(msg) raise NoResultException(msg)
def compare_rest_response_with_pattern(response, method=None, directory=None, error_response: bool = False, ignore_tags: str | list[str] | list[re.Pattern] | None = None):
pytest_current_test = os.getenv('PYTEST_CURRENT_TEST')
assert pytest_current_test is not None, "Environment variable not set: PYTEST_CURRENT_TEST"
test_fname, _ = pytest_current_test.split("::")
test_dir = os.getenv("TAVERN_DIR", "")
overlap = get_overlap(test_dir, test_fname)
test_fname = test_dir + "/" + test_fname.replace(overlap, "")
test_fname = test_fname.replace(TEST_FILE_EXT, "")
response_fname = test_fname + RESPONSE_FILE_EXT
json_response: dict[str, Any] = response.json()
save_json(response_fname, json_response)
if error_response:
for required_key in ["code", "details", "hint", "message"]:
assert required_key in json_response, f"Response, marked as error, does not contain {required_key} key"
if isinstance(ignore_tags, str):
ignore_tags = [predefined_ignore_tags[ignore_tags]]
pattern = load_pattern(test_fname + PATTERN_FILE_EXT)
pattern_resp_diff = deepdiff.DeepDiff(pattern, json_response, exclude_regex_paths=ignore_tags)
if pattern_resp_diff:
raise PatternDiffException("Differences detected between response and pattern.")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment