From 94e1cd9a563726fbd5933a2051f71c51d4bf3ab0 Mon Sep 17 00:00:00 2001 From: David Talbot <17692467+dctalbot@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:17:10 -0500 Subject: [PATCH] [MAINTENANCE] fix REST API contract tests (#9098) --- .github/workflows/ci.yml | 17 -------- .../cloud/rest_contracts/conftest.py | 43 +++++++------------ .../cloud/rest_contracts/test_checkpoints.py | 4 +- .../test_data_context_configuration.py | 7 ++- .../cloud/rest_contracts/test_datasource.py | 4 +- .../rest_contracts/test_expectation_suites.py | 12 +++--- 6 files changed, 32 insertions(+), 55 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 777a4629d612..d97eb567fe06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -316,23 +316,6 @@ jobs: - name: Run the tests run: invoke ci-tests 'cloud' --up-services --verbose - - name: Get mercury version - run: | - curl -s ''${GX_CLOUD_BASE_URL}'/status' | \ - python3 -c "import os, sys, json; api_version=json.load(sys.stdin)['api_version']; os.system(f'echo api_version={api_version}');" \ - >> $GITHUB_OUTPUT - id: get_mercury_version - - - name: Verify endpoint contracts - run: | - pact-verifier -r --provider-base-url=${GX_CLOUD_BASE_URL} \ - --pact-url=tests/integration/cloud/rest_contracts/pacts/great_expectations-mercury.json \ - --pact-broker-url=https://greatexpectations.pactflow.io/ \ - --pact-broker-token=${PACT_BROKER_READ_WRITE_TOKEN} \ - --provider=mercury \ - --provider-version-branch=develop \ - --provider-app-version=${{ steps.get_mercury_version.outputs.api_version }} - marker-tests: needs: [unit-tests, static-analysis] diff --git a/tests/integration/cloud/rest_contracts/conftest.py b/tests/integration/cloud/rest_contracts/conftest.py index 92467646892c..09e5891712f9 100644 --- a/tests/integration/cloud/rest_contracts/conftest.py +++ b/tests/integration/cloud/rest_contracts/conftest.py @@ -103,8 +103,13 @@ def get_git_commit_hash() -> str: return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip() -@pytest.fixture +@pytest.fixture(scope="package") def pact_test(request) -> pact.Pact: + """ + pact_test can be used as a context manager and will: + 1. write a new contract to the pact dir + 2. verify the contract against the mock service + """ pact_broker_base_url = "https://greatexpectations.pactflow.io" broker_token: str @@ -126,7 +131,7 @@ def pact_test(request) -> pact.Pact: # in GH, and we run the release build process on the tagged commit. version = f"{get_git_commit_hash()}_{str(uuid.uuid4())[:5]}" - pact_test: pact.Pact = pact.Consumer( + _pact: pact.Pact = pact.Consumer( name=CONSUMER_NAME, version=version, tag_with_git_branch=True, @@ -141,9 +146,9 @@ def pact_test(request) -> pact.Pact: publish_to_broker=publish_to_broker, ) - pact_test.start_service() - yield pact_test - pact_test.stop_service() + _pact.start_service() + yield _pact + _pact.stop_service() class ContractInteraction(pydantic.BaseModel): @@ -188,7 +193,7 @@ class Config: @pytest.fixture -def run_pact_test( +def run_rest_api_pact_test( gx_cloud_session: Session, pact_test: pact.Pact, ) -> Callable: @@ -236,32 +241,16 @@ def _run_pact_test( request_url = f"http://{PACT_MOCK_HOST}:{PACT_MOCK_PORT}{contract_interaction.request_path}" with pact_test: - gx_cloud_session.request( + # act + resp = gx_cloud_session.request( method=contract_interaction.method, url=request_url, json=contract_interaction.request_body, params=contract_interaction.request_params, ) - try: - provider_base_url: Final[str] = os.environ["GX_CLOUD_BASE_URL"] - except KeyError as e: - raise OSError("GX_CLOUD_BASE_URL is not set in this environment.") from e - - verifier = pact.Verifier( - provider=PROVIDER_NAME, - provider_base_url=provider_base_url, - ) - - pacts: tuple[str, ...] = tuple( - str(file.resolve()) for file in PACT_DIR.glob("*.json") - ) - - exit_code, logs = verifier.verify_pacts( - *pacts, - verbose=False, - ) - if exit_code == 1: - raise AssertionError("Pact verifier reports failed interactions") + # assert + assert resp.status_code == contract_interaction.response_status + # TODO more unit test assertions would go here e.g. response body checks return _run_pact_test diff --git a/tests/integration/cloud/rest_contracts/test_checkpoints.py b/tests/integration/cloud/rest_contracts/test_checkpoints.py index 0bd093672493..062bc22e2a8d 100644 --- a/tests/integration/cloud/rest_contracts/test_checkpoints.py +++ b/tests/integration/cloud/rest_contracts/test_checkpoints.py @@ -94,6 +94,6 @@ ) def test_checkpoint( contract_interaction: ContractInteraction, - run_pact_test: Callable[[ContractInteraction], None], + run_rest_api_pact_test: Callable[[ContractInteraction], None], ) -> None: - run_pact_test(contract_interaction) + run_rest_api_pact_test(contract_interaction) diff --git a/tests/integration/cloud/rest_contracts/test_data_context_configuration.py b/tests/integration/cloud/rest_contracts/test_data_context_configuration.py index 811e1ec69ff8..fb1c712192d6 100644 --- a/tests/integration/cloud/rest_contracts/test_data_context_configuration.py +++ b/tests/integration/cloud/rest_contracts/test_data_context_configuration.py @@ -37,6 +37,7 @@ def test_data_context_configuration( cloud_access_token: str, pact_test: pact.Pact, ) -> None: + # arrange provider_state = "the Data Context exists" scenario = "a request for a Data Context" method = "GET" @@ -59,9 +60,13 @@ def test_data_context_configuration( ) with pact_test: - _ = gx.get_context( + # act + ctx = gx.get_context( mode="cloud", cloud_base_url=PACT_MOCK_SERVICE_URL, cloud_organization_id=EXISTING_ORGANIZATION_ID, cloud_access_token=cloud_access_token, ) + + # assert + assert ctx.datasources is not None diff --git a/tests/integration/cloud/rest_contracts/test_datasource.py b/tests/integration/cloud/rest_contracts/test_datasource.py index 385548a371e0..ace7dc8a5121 100644 --- a/tests/integration/cloud/rest_contracts/test_datasource.py +++ b/tests/integration/cloud/rest_contracts/test_datasource.py @@ -83,6 +83,6 @@ ) def test_datasource( contract_interaction: ContractInteraction, - run_pact_test: Callable[[ContractInteraction], None], + run_rest_api_pact_test: Callable[[ContractInteraction], None], ) -> None: - run_pact_test(contract_interaction) + run_rest_api_pact_test(contract_interaction) diff --git a/tests/integration/cloud/rest_contracts/test_expectation_suites.py b/tests/integration/cloud/rest_contracts/test_expectation_suites.py index e65095e77f08..a53eb3b1d76f 100644 --- a/tests/integration/cloud/rest_contracts/test_expectation_suites.py +++ b/tests/integration/cloud/rest_contracts/test_expectation_suites.py @@ -252,9 +252,9 @@ def test_get_expectation_suites( ) def test_post_expectation_suite_request( contract_interaction: ContractInteraction, - run_pact_test: Callable[[ContractInteraction], None], + run_rest_api_pact_test: Callable[[ContractInteraction], None], ) -> None: - run_pact_test(contract_interaction) + run_rest_api_pact_test(contract_interaction) @pytest.mark.cloud @@ -297,9 +297,9 @@ def test_post_expectation_suite_request( ) def test_put_expectation_suite_request( contract_interaction: ContractInteraction, - run_pact_test: Callable[[ContractInteraction], None], + run_rest_api_pact_test: Callable[[ContractInteraction], None], ) -> None: - run_pact_test(contract_interaction) + run_rest_api_pact_test(contract_interaction) @pytest.mark.cloud @@ -342,9 +342,9 @@ def test_put_expectation_suite_request( ) def test_put_non_existent_expectation_suite( contract_interaction: ContractInteraction, - run_pact_test: Callable[[ContractInteraction], None], + run_rest_api_pact_test: Callable[[ContractInteraction], None], ) -> None: - run_pact_test(contract_interaction) + run_rest_api_pact_test(contract_interaction) @pytest.mark.cloud