diff --git a/.github/skills/dotnet-to-python-test-mapping/SKILL.md b/.github/skills/dotnet-to-python-test-mapping/SKILL.md new file mode 100644 index 000000000000..eea683d023df --- /dev/null +++ b/.github/skills/dotnet-to-python-test-mapping/SKILL.md @@ -0,0 +1,74 @@ +--- +name: Dotnet-to-Python test mapping +description: Map an Azure SDK for .NET test case to its equivalent Azure SDK for Python test (same service area), then implement or update the Python test under sdk/.../tests. Use when a user provides a .NET test file path/URL and asks for the corresponding Python test. +--- + +## Purpose +You help translate a single Azure SDK for .NET test scenario into the equivalent Azure SDK for Python test file under this repo. + +## When to use +Use this skill when the user: +- links to a .NET test file (GitHub URL or local path), and +- asks to find/create/update the equivalent Python test in Python SDK folder + +## Inputs you should request (only if missing) +Only ask the user for extra inputs when you truly cannot derive them from repo search. +1. **Only if** the .NET test file path does **not** contain `Scenario` or `ScenarioTests` folder, ask the user to confirm whether the test can run successfully in **live mode**. Otherwise, skip asking. +2. If user does not provide a Python SDK repo folder, otherwise infer the correct package and tests folder. + +## Workflow +1. **Identify the .NET test intent** + - Read the test class and methods. + - Summarize required resources, operations, and assertions. + +2. **Locate the Python package & tests folder** + - If the user did not provide a specific Python SDK folder under `sdk/`, do NOT ask them to provide one by default. + - Instead, infer it using the techniques in "How to map .NET -> Python package (best signal: HTTP path)". + - Find the matching Python management/data-plane package under `sdk/`. + - Verify the target tests folder exists; if it doesn’t, find the closest existing `tests` folder pattern in that package. + +3. **Find an existing Python analogue** + - Search by scenario keywords, operation names, resource types, and test naming patterns. + - Prefer updating/extending an existing scenario test over creating a new one. + +4. **Implement the Python test** + - Follow the package's existing test patterns (fixtures, recorded tests, naming conventions). + - Keep changes minimal and scoped to the scenario. + +5. **Validate** + - Run the package tests (or at minimum the new/updated test file) in the existing test harness. + +## How to map .NET -> Python package (best signal: HTTP path) +The most reliable mapping between a generated .NET SDK folder and a generated Python SDK folder is the HTTP request path, because both SDKs are generated from the same source (Swagger/TypeSpec). That means the operations typically share the same REST paths. + +### Steps +1. **Find the REST path in the .NET generated code** + - Locate the generated collection/client method for the operation used in the test. + - In Azure SDK for .NET generated code, the REST path is commonly surfaced as a `Request Path` annotation/comment (or an attribute nearby). + - Example `Request Path` annotation: + - https://github.com/Azure/azure-sdk-for-net/blob/a89fe22c07d5dd2303ff4cf45e726d3d16c57f5b/sdk/network/Azure.ResourceManager.Network/src/Generated/AdminRuleGroupCollection.cs#L58-L59 + +2. **Search for that path in this Python repo** + - Take the path string (the part after the host, e.g. `/subscriptions/{subscriptionId}/...`). + - Search the Python repo for the same path. Likely hits include: + - Generated client operation files under `sdk///azure/mgmt/.../operations/` (mgmt-plane) + - Generated REST/operation specs in the codegen output + - Test recordings referencing the URL path + - Once you find the matching Python package folder under `sdk/`, the target test folder is usually: + - `sdk///tests` (data-plane patterns vary), or + - `sdk///tests` / `sdk///tests/recordings` (mgmt-plane common) + +3. **Confirm by quick sanity checks** + - The Python package’s namespace should match the service (e.g., `azure.mgmt.network`). + - The operations/classes should mention the same resource type names used in the .NET test. + - Prefer the package that already has scenario tests and recordings for similar resources. + +### Fallbacks (if the path search is noisy) +- Search by resource type segments in the path (e.g., `Microsoft.Network`, `adminRuleGroups`, `routeTables`). +- Search by operation name used in the .NET test and map to Python operations modules. +- Use service folder heuristics (`sdk/network/` vs `sdk/resources/`), then narrow to `azure-mgmt-*` packages. + +## Example mapping +- .NET: `sdk/resources/Azure.ResourceManager.Resources/tests/Scenario/DataBoundaryOperationsTests.cs` +- Python target folder: `sdk/resources/azure-mgmt-resource/tests` +- Python analogue: `sdk/resources/azure-mgmt-resource/tests/test_data_boundary_scenario_test.py` diff --git a/.github/skills/dotnet-to-python-test-mapping/examples.md b/.github/skills/dotnet-to-python-test-mapping/examples.md new file mode 100644 index 000000000000..3ade16ea0ef8 --- /dev/null +++ b/.github/skills/dotnet-to-python-test-mapping/examples.md @@ -0,0 +1,10 @@ +## Example prompt + +"Help .NET SDK test case https://github.com/Azure/azure-sdk-for-net/blob/f77ff48fb510bd60ea8c2cfbb8d3fa301f5d4f54/sdk/resources/Azure.ResourceManager.Resources/tests/Scenario/DataBoundaryOperationsTests.cs to python test case under folder C:/dev/azure-sdk-for-python/sdk/resources/azure-mgmt-resource/tests" + +## Expected behavior + +1. Ask the user to confirm the .NET test passes in live mode. +2. Confirm the .NET folder maps to `sdk/resources/azure-mgmt-resource/tests`. +3. Locate the Python analogue (e.g., `test_data_boundary_scenario_test.py`). +4. Implement/update the Python test with minimal changes and run the relevant test command. diff --git a/sdk/compute/azure-mgmt-compute/tests/test_mgmt_compute_resource_skus.py b/sdk/compute/azure-mgmt-compute/tests/test_mgmt_compute_resource_skus.py new file mode 100644 index 000000000000..838d8df5221f --- /dev/null +++ b/sdk/compute/azure-mgmt-compute/tests/test_mgmt_compute_resource_skus.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +# ------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +# -------------------------------------------------------------------------- + +# covered ops: +# resource_skus: 1/1 + +import pytest +import azure.mgmt.compute +from devtools_testutils import AzureMgmtRecordedTestCase, RandomNameResourceGroupPreparer, recorded_by_proxy + +AZURE_LOCATION = "westus" + + +@pytest.mark.live_test_only +class TestMgmtComputeResourceSkus(AzureMgmtRecordedTestCase): + + def setup_method(self, method): + self.mgmt_client = self.create_mgmt_client(azure.mgmt.compute.ComputeManagementClient) + + @recorded_by_proxy + def test_get_resource_skus(self): + """Lists all available Resource SKUs with filter and extended locations.""" + count = 0 + for resource_sku in self.mgmt_client.resource_skus.list( + filter="location eq 'westus'", + include_extended_locations="true" + ): + count += 1 + + assert count > 0 diff --git a/sdk/resources/azure-mgmt-resource/tests/test_data_boundary_scenario_test.py b/sdk/resources/azure-mgmt-resource/tests/test_data_boundary_scenario_test.py new file mode 100644 index 000000000000..714b3d599748 --- /dev/null +++ b/sdk/resources/azure-mgmt-resource/tests/test_data_boundary_scenario_test.py @@ -0,0 +1,60 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- + +import pytest +from azure.core.exceptions import HttpResponseError +from azure.mgmt.resource.databoundaries import DataBoundaryMgmtClient +from azure.mgmt.resource.databoundaries.models import DataBoundaryDefinition, DataBoundaryProperties, DataBoundary, ProvisioningState + +from devtools_testutils import AzureMgmtRecordedTestCase, recorded_by_proxy + +@pytest.mark.live_test_only +class TestDataBoundaryScenario(AzureMgmtRecordedTestCase): + + def setup_method(self, method): + self.client = self.create_mgmt_client(DataBoundaryMgmtClient) + + @recorded_by_proxy + def test_get_data_boundary_tenant(self): + result = self.client.data_boundaries.get_tenant(default="default") + + # Based on .NET test: Assert.AreEqual(DataBoundaryRegion.EU, resourceData.Properties.DataBoundary); + # In this environment/recording, it is 'Global'. + assert result.properties.data_boundary == DataBoundary.GLOBAL + + @recorded_by_proxy + def test_get_data_boundary_scoped(self): + subscription_id = self.get_settings_value("SUBSCRIPTION_ID") + scope = "/subscriptions/{}".format(subscription_id) + + result = self.client.data_boundaries.get_scope(scope=scope, default="default") + + assert result.properties.data_boundary == DataBoundary.GLOBAL + assert result.properties.provisioning_state == ProvisioningState.SUCCEEDED + + @recorded_by_proxy + def test_get_data_boundary_scoped_collection(self): + subscription_id = self.get_settings_value("SUBSCRIPTION_ID") + scope = "/subscriptions/{}".format(subscription_id) + + result = self.client.data_boundaries.get_scope(scope=scope, default="default") + + assert result.properties.data_boundary == DataBoundary.GLOBAL + assert result.properties.provisioning_state == ProvisioningState.SUCCEEDED + + @recorded_by_proxy + def test_put_data_boundary(self): + data_boundary_definition = DataBoundaryDefinition( + properties=DataBoundaryProperties(data_boundary=DataBoundary.EU) + ) + + with pytest.raises(HttpResponseError) as excinfo: + self.client.data_boundaries.put( + default="default", + data_boundary_definition=data_boundary_definition + ) + + assert "does not have authorization" in str(excinfo.value)