Skip to content

Commit

Permalink
Added api contract profile parameters test case (#7604)
Browse files Browse the repository at this point in the history
* added profile parameters test case

* Refactored coordinates to match updated merge in conftest.py

* Added get request for profile and parameters in conftest.py

* Update request_template.json for profileId and parameterId

* Added lastUpdated to response_template.json

* Fixed assertion test_profile_parameters.py

* Fixed indentation on line 1685 conftest.py

* removed unnecessary profile_id var conftest.py

* removed unnecessary declaration for parameter_Id conftest.py

* fixed indentation conftest.py

* Fixing inconsistent tabbing indentation conftest.py

---------

Co-authored-by: yblanc545 <Yves-Richard_Blanc@comcast.com>
  • Loading branch information
Kashatlast2 and yblanc545 committed Jul 26, 2023
1 parent 55d8070 commit 4f91711
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
9 changes: 9 additions & 0 deletions traffic_control/clients/python/trafficops/tosession.py
Original file line number Diff line number Diff line change
Expand Up @@ -1645,6 +1645,15 @@ def delete_profile_by_id(self, profile_id=None):
#
# Profile Parameters
#
@api_request('get', 'profileparameters', ('3.0', '4.0', '4.1', '5.0'))
def get_profile_parameters(self, data=None):
"""
Retrieve all Parameter/Profile assignments.
:ref:`to-api-profileparameters`
:rtype: Tuple[Union[Dict[str, Any], List[Dict[str, Any]]], requests.Response]
:raises: Union[LoginError, OperationError]
"""

@api_request('post', 'profileparameters', ('3.0', '4.0', '4.1', '5.0'))
def associate_paramater_to_profile(self, data=None):
"""
Expand Down
36 changes: 36 additions & 0 deletions traffic_ops/testing/api_contract/v4/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1643,3 +1643,39 @@ def delivery_services_regex_data_post(to_session: TOSession, request_template_da
if msg is None:
logger.error("delivery_services_regex returned by Traffic Ops is missing an 'id' property")
pytest.fail("Response from delete request is empty, Failing test_case")


@pytest.fixture(name="profile_parameters_post_data")
def profile_parameters_post_data(to_session: TOSession, request_template_data: list[JSONData],
profile_post_data:dict[str, object], parameter_post_data:dict[str, object]
) -> dict[str, object]:
"""
PyTest Fixture to create POST data for profile parameters endpoint.
:param to_session: Fixture to get Traffic Ops session.
:param request_template_data: Fixture to get profile parameters request template from a prerequisites file.
:returns: Sample POST data and the actual API response.
"""

profile_parameters = check_template_data(request_template_data["profile_parameters"], "profile_parameters")

# Return new post data and post response from profile parameters POST request
profile_get_response = to_session.get_profiles()
profile_data = profile_get_response [0][0]
profile_id = profile_data.get("id")

profile_parameters["profileId"] = profile_post_data["id"]
profile_parameters["parameterId"] = parameter_post_data["id"]

logger.info("New profile_parameter data to hit POST method %s", profile_parameters)

# Hitting profile parameters POST method
response: tuple[JSONData, requests.Response] = to_session.associate_paramater_to_profile(profile_id=profile_id, data=profile_parameters)
resp_obj = check_template_data(response, "profile_parameters")
yield resp_obj
profile_id = resp_obj.get("profileId")
parameter_id = resp_obj.get("parameterId")
msg = to_session.delete_profile_parameter_association_by_id(profile_id=profile_id, parameter_id=parameter_id)
logger.info("Deleting Profile Parameters data... %s", msg)
if msg is None:
logger.error("Profile Parameter returned by Traffic Ops is missing a 'profile_id' property")
pytest.fail("Response from delete request is empty, Failing test_case")
10 changes: 10 additions & 0 deletions traffic_ops/testing/api_contract/v4/data/request_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -395,5 +395,15 @@
"type": 33,
"setNumber": 1
}
],
"profile_parameters": [
{
"profileId": 18,
"parameterId": 2
},
{
"profileId": 18,
"parameterId": 3
}
]
}
21 changes: 21 additions & 0 deletions traffic_ops/testing/api_contract/v4/data/response_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -1680,6 +1680,27 @@
},
"pattern": {
"type": "string"

}
}
},
"profile_parameters": {
"type": "object",
"required":[
"lastUpdated",
"profile",
"parameter"
],
"properties":{
"lastUpdated":{
"type": "string"
},
"profile":{
"type": "string"

},
"parameter":{
"type": "integer"
}
}
}
Expand Down
90 changes: 90 additions & 0 deletions traffic_ops/testing/api_contract/v4/test_profile_parameters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""API Contract Test Case for Profile Parameters endpoint."""
import logging
from typing import Union

import pytest
import requests
from jsonschema import validate

from trafficops.tosession import TOSession

# Create and configure logger
logger = logging.getLogger()

Primitive = Union[bool, int, float, str, None]


def test_profile_parameters_contract(
to_session: TOSession,
response_template_data: dict[str, Union[Primitive, list[Union[Primitive, dict[str, object],
list[object]]], dict[object, object]]], profile_parameters_post_data: dict[str, object]) -> None:
"""
Test step to validate keys, values and data types from profile parameters endpoint
response.
:param to_session: Fixture to get Traffic Ops session.
:param response_template_data: Fixture to get response template data from a prerequisites file.
:param profile_parameter_post_data: Fixture to get sample profile parameter data
and actual Profile Parameter response.
"""
# validate Profile Parameter keys from profile parameters get response
logger.info(
"Accessing /profile parameters endpoint through Traffic ops session.")

profile_id = profile_parameters_post_data.get("profileId")
if not isinstance(profile_id, int):
raise TypeError(
"malformed profile parameters in prerequisite data; 'profileId' not an integer")

parameter_id = profile_parameters_post_data.get("parameterId")
if not isinstance(parameter_id, int):
raise TypeError(
"malformed profile parameters in prerequisite data; 'parameterId' not an integer")

profile_parameter_get_response: tuple[
Union[dict[str, object],
list[Union[dict[str, object], list[object], Primitive]], Primitive],
requests.Response
] = to_session.get_profile_parameters(profile_id=profile_id, query_params={"profile": profile_id})
try:
profile_parameter_data = profile_parameter_get_response[0]
if not isinstance(profile_parameter_data, list):
raise TypeError("malformed API response; 'response' property not an array")

first_profile_parameter = profile_parameter_data[0]
if not isinstance(first_profile_parameter, dict):
raise TypeError(
"malformed API response; first Profile Parameter in response is not an object")
logger.info("Profile Parameter Api get response %s", first_profile_parameter)
profile_parameter_response_template = response_template_data.get("profile_parameters")
if not isinstance(profile_parameter_response_template, dict):
raise TypeError(
f"Profile Parameter response template data must be a dict, not '{type(profile_parameter_response_template)}'")

profile_parameters_post_data["profile"] = first_profile_parameter["profile"]
profile_parameters_post_data["parameter"] = first_profile_parameter["parameter"]

# validate profile_parameter values from prereq data in profile parameters get response.
keys = ["profile", "parameter"]
prereq_values = [profile_parameters_post_data[key] for key in keys]
get_values = [first_profile_parameter[key] for key in keys]

assert validate(instance=first_profile_parameter,
schema=profile_parameter_response_template) is None
assert get_values == prereq_values
except IndexError:
logger.error("Either prerequisite data or API response was malformed")
pytest.fail("API contract test failed for profile_parameter endpoint: API response was malformed")

0 comments on commit 4f91711

Please sign in to comment.