diff --git a/changelog.d/+ignore_new_keys_in_tests.infrastructure.md b/changelog.d/+ignore_new_keys_in_tests.infrastructure.md new file mode 100644 index 00000000..90e3cc85 --- /dev/null +++ b/changelog.d/+ignore_new_keys_in_tests.infrastructure.md @@ -0,0 +1 @@ +Fix event notification tests when introducing new keys in API outputs. \ No newline at end of file diff --git a/test/helpers.py b/test/helpers.py index 8ba0fee2..17c5d26e 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -57,3 +57,22 @@ def type_validator_factory(type_): if pydantic: return pydantic.TypeAdapter(type_).validate_python return lambda *args, **kwargs: None + + +def deep_cast_dict(actual, expected): + """ + For composite objects `actual` and `expected`, return a copy of `actual` (with all dicts and lists deeply copied) + with all keys of dicts not appearing in `expected` (comparing dicts on any level) removed. Useful for assertions + in tests ignoring extra keys. + """ + if isinstance(expected, dict) and isinstance(actual, dict): + return {k: deep_cast_dict(actual[k], expected[k]) for k in expected if k in actual} + + elif isinstance(expected, list) and isinstance(actual, list): + return [deep_cast_dict(a, e) for a, e in zip(actual, expected)] + + return actual + + +def assert_dict_equal_ignore_extra(actual, expected): + assert deep_cast_dict(actual, expected) == expected diff --git a/test/integration/test_bucket.py b/test/integration/test_bucket.py index 60a632cd..e9b46d3c 100644 --- a/test/integration/test_bucket.py +++ b/test/integration/test_bucket.py @@ -7,6 +7,8 @@ # License https://www.backblaze.com/using_b2_code.html # ###################################################################### +from test.helpers import assert_dict_equal_ignore_extra + import pytest @@ -33,12 +35,13 @@ def test_bucket_notification_rules(bucket, b2_api): set_notification_rules = bucket.set_notification_rules([notification_rule]) assert set_notification_rules == bucket.get_notification_rules() - assert set_notification_rules == [ - { + assert_dict_equal_ignore_extra( + set_notification_rules, + [{ **notification_rule, "isSuspended": False, "suspensionReason": "" - } - ] + }], + ) assert bucket.set_notification_rules([]) == [] diff --git a/test/integration/test_raw_api.py b/test/integration/test_raw_api.py index 07d36d8b..12b48f1e 100644 --- a/test/integration/test_raw_api.py +++ b/test/integration/test_raw_api.py @@ -16,7 +16,7 @@ import sys import time import traceback -from test.helpers import type_validator_factory +from test.helpers import assert_dict_equal_ignore_extra, type_validator_factory from typing import List import pytest @@ -634,7 +634,9 @@ def _subtest_bucket_notification_rules(raw_api, auth_dict, api_url, account_auth } } ] - assert notification_rules_response_list == expected_notification_rule_response_list + assert_dict_equal_ignore_extra( + notification_rules_response_list, expected_notification_rule_response_list + ) assert raw_api.set_bucket_notification_rules(api_url, account_auth_token, bucket_id, []) == [] assert raw_api.get_bucket_notification_rules(api_url, account_auth_token, bucket_id) == [] diff --git a/test/unit/bucket/test_bucket.py b/test/unit/bucket/test_bucket.py index eae64467..92639e5c 100644 --- a/test/unit/bucket/test_bucket.py +++ b/test/unit/bucket/test_bucket.py @@ -21,7 +21,7 @@ import unittest.mock as mock from contextlib import suppress from io import BytesIO -from test.helpers import NonSeekableIO +from test.helpers import NonSeekableIO, assert_dict_equal_ignore_extra import apiver_deps import pytest @@ -3329,22 +3329,24 @@ def test_bucket_notification_rules(bucket, b2api_simulator): set_notification_rules = bucket.set_notification_rules([notification_rule]) assert set_notification_rules == bucket.get_notification_rules() - assert set_notification_rules == [ - { + assert_dict_equal_ignore_extra( + set_notification_rules, + [{ **notification_rule, "isSuspended": False, "suspensionReason": "" - } - ] + }], + ) b2api_simulator.bucket_id_to_bucket[bucket.id_].simulate_notification_rule_suspension( notification_rule["name"], "simulated suspension" ) - assert bucket.get_notification_rules() == [ - { + assert_dict_equal_ignore_extra( + bucket.get_notification_rules(), + [{ **notification_rule, "isSuspended": True, "suspensionReason": "simulated suspension" - } - ] + }], + ) assert bucket.set_notification_rules([]) == [] assert bucket.get_notification_rules() == []