From ecc60a29da74a1e96c5fdc0d81dba4e5715e86f4 Mon Sep 17 00:00:00 2001 From: Tomas Pavlin Date: Tue, 19 Jan 2021 15:05:24 +0100 Subject: [PATCH 1/2] Improve reporting --- .../swagger_parser/swagger_parser.py | 2 ++ .../swagger_tester/swagger_tester.py | 8 ++++-- tests/swagger_parser/test_swagger_parser.py | 3 +++ tests/swagger_parser/test_swagger_tester.py | 27 +++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/swagger_parser/test_swagger_tester.py diff --git a/swagger_unittest/swagger_parser/swagger_parser.py b/swagger_unittest/swagger_parser/swagger_parser.py index 5e19d7c..349706d 100644 --- a/swagger_unittest/swagger_parser/swagger_parser.py +++ b/swagger_unittest/swagger_parser/swagger_parser.py @@ -506,6 +506,8 @@ def validate_definition(self, definition_name: str, dict_to_test: Dict, definiti # Check all required in dict_to_test spec_def = definition or self.specification['definitions'][definition_name] + if not isinstance(dict_to_test, dict): + return False all_required_keys_present = all(req in dict_to_test.keys() for req in spec_def.get('required', {})) if 'required' in spec_def and not all_required_keys_present: return False diff --git a/swagger_unittest/swagger_tester/swagger_tester.py b/swagger_unittest/swagger_tester/swagger_tester.py index 87e637a..3b6c959 100644 --- a/swagger_unittest/swagger_tester/swagger_tester.py +++ b/swagger_unittest/swagger_tester/swagger_tester.py @@ -84,8 +84,12 @@ def validate_definition(swagger_parser, valid_response, response): # Check if there is a definition that match body and response valid_definition = swagger_parser.get_dict_definition(valid_response, get_list=True) actual_definition = swagger_parser.get_dict_definition(response, get_list=True) - assert len(set(valid_definition).intersection(actual_definition)) >= 1, \ - f'Responses {valid_response} and {response} not compatible' + assert len(set(valid_definition).intersection(actual_definition)) >= 1, ( + f'Responses are not compatible. Definition of valid response is {valid_definition} which is different ' + f'than definition of actual response which is {actual_definition}. \n' + f'Valid response: {valid_response} \n' + f'Actual response: {response}' + ) def parse_parameters(url, action, path, request_args, swagger_parser): diff --git a/tests/swagger_parser/test_swagger_parser.py b/tests/swagger_parser/test_swagger_parser.py index 630e0b3..bdcb7ab 100644 --- a/tests/swagger_parser/test_swagger_parser.py +++ b/tests/swagger_parser/test_swagger_parser.py @@ -215,6 +215,9 @@ def test_validate_definition(swagger_parser, pet_definition_example): pet_definition_example['name'] = 2 assert not swagger_parser.validate_definition('Pet', pet_definition_example) + # Check string instead of dict_to_test + assert not swagger_parser.validate_definition('Pet', 'foo') + def test_get_paths_data(swagger_parser, post_put_path_data, get_path_data): swagger_parser.get_paths_data() diff --git a/tests/swagger_parser/test_swagger_tester.py b/tests/swagger_parser/test_swagger_tester.py new file mode 100644 index 0000000..f738a82 --- /dev/null +++ b/tests/swagger_parser/test_swagger_tester.py @@ -0,0 +1,27 @@ +# -*- coding:utf-8 -*- +import pytest + +from swagger_unittest.swagger_tester import swagger_tester + + +def test_validate_definition(swagger_parser, pet_definition_example): + valid_response = swagger_parser.definitions_example['Pet'] + + # Valid Pet is valid definition + swagger_tester.validate_definition(swagger_parser, valid_response, valid_response) + + # Changing list with emtpy list is valid definition of Pet + response = valid_response.copy() + assert len(response['tags']) > 0 + response['tags'] = [] + swagger_tester.validate_definition(swagger_parser, valid_response, response) + + # Changing list with string is not valid definition of Pet + with pytest.raises(AssertionError): + response = valid_response.copy() + response['tags'] = 'foo' + swagger_tester.validate_definition(swagger_parser, valid_response, response) + + # Empty dict is not valid Pet + with pytest.raises(AssertionError, match=r".*Responses are not compatible\. Definition of valid response is.*"): + swagger_tester.validate_definition(swagger_parser, valid_response, {}) From 861efbe3bfa5679fb9b230576bb71f5b3d6c236d Mon Sep 17 00:00:00 2001 From: Tomas Pavlin Date: Sun, 7 Feb 2021 18:06:02 +0100 Subject: [PATCH 2/2] Fix checking string swagger definition --- .../swagger_parser/swagger_parser.py | 32 ++++++++++--------- tests/swagger_parser/conftest.py | 5 +++ tests/swagger_parser/data/enum.yaml | 21 ++++++++++++ tests/swagger_parser/test_swagger_parser.py | 8 +++++ 4 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 tests/swagger_parser/data/enum.yaml diff --git a/swagger_unittest/swagger_parser/swagger_parser.py b/swagger_unittest/swagger_parser/swagger_parser.py index 4b81cb2..7e6091a 100644 --- a/swagger_unittest/swagger_parser/swagger_parser.py +++ b/swagger_unittest/swagger_parser/swagger_parser.py @@ -489,12 +489,12 @@ def validate_additional_properties(self, valid_response, response): except Exception: return False - def validate_definition(self, definition_name: str, dict_to_test: Dict, definition: Dict = None): + def validate_definition(self, definition_name: str, expected_value: Dict, definition: Dict = None): """Validate the given dict according to the given definition. Args: definition_name: name of the the definition. - dict_to_test: dict to test. + expected_value: dict or scalar value to test. definition: definition Returns: @@ -507,21 +507,23 @@ def validate_definition(self, definition_name: str, dict_to_test: Dict, definiti # Check all required in dict_to_test spec_def = definition or self.specification['definitions'][definition_name] - if not isinstance(dict_to_test, dict): - return False - all_required_keys_present = all(req in dict_to_test.keys() for req in spec_def.get('required', {})) - if 'required' in spec_def and not all_required_keys_present: - return False + if isinstance(expected_value, dict): + all_required_keys_present = all(req in expected_value.keys() for req in spec_def.get('required', {})) + if 'required' in spec_def and not all_required_keys_present: + return False - # Check no extra arg & type - properties_dict = spec_def.get('properties', {}) - for key, value in dict_to_test.items(): - if value is not None: - if key not in properties_dict: # Extra arg - return False - else: # Check type - if not self._validate_type(properties_dict[key], value): + # Check no extra arg & type + properties_dict = spec_def.get('properties', {}) + for key, value in expected_value.items(): + if value is not None: + if key not in properties_dict: # Extra arg return False + else: # Check type + if not self._validate_type(properties_dict[key], value): + return False + else: + # Definition corresponds to scalar value (string for instance) + return self.check_type(expected_value, spec_def['type']) return True diff --git a/tests/swagger_parser/conftest.py b/tests/swagger_parser/conftest.py index 83b4f20..a613c02 100644 --- a/tests/swagger_parser/conftest.py +++ b/tests/swagger_parser/conftest.py @@ -25,6 +25,11 @@ def inline_parser(): return SwaggerParser('data/inline.yaml') +@pytest.fixture +def swagger_enum_parser(): + return SwaggerParser('data/enum.yaml') + + @pytest.fixture(scope='module', params=['data/no_properties.yaml', 'data/object_no_schema.yaml', diff --git a/tests/swagger_parser/data/enum.yaml b/tests/swagger_parser/data/enum.yaml new file mode 100644 index 0000000..1426e74 --- /dev/null +++ b/tests/swagger_parser/data/enum.yaml @@ -0,0 +1,21 @@ +swagger: '2.0' +info: + version: '2016-01-19T11:24:50Z' + title: authentication tests +schemes: +- http +paths: + /test: + get: + description: Get something + responses: + '200': + description: OK + schema: + $ref: '#/definitions/my_enum' +definitions: + my_enum: + type: string + enum: + - OPTION_A + - OPTION_B diff --git a/tests/swagger_parser/test_swagger_parser.py b/tests/swagger_parser/test_swagger_parser.py index b4ebfa8..792b248 100644 --- a/tests/swagger_parser/test_swagger_parser.py +++ b/tests/swagger_parser/test_swagger_parser.py @@ -222,6 +222,14 @@ def test_validate_definition(swagger_parser, pet_definition_example): assert not swagger_parser.validate_definition('Pet', 'foo') +def test_validate_enum_definition(swagger_enum_parser): + # Check string instead of dict_to_test + assert swagger_enum_parser.validate_definition('my_enum', 'OPTION_A') + + # TODO: also check for correct enum value (currently enum is treated as string) + assert swagger_enum_parser.validate_definition('my_enum', 'FOO_BAR') + + def test_get_paths_data(swagger_parser, post_put_path_data, get_path_data): swagger_parser.get_paths_data() assert len(swagger_parser.paths) == 13