Skip to main content

policy-testing

Conventions and patterns for writing policy compilation tests in the Azure API Management policy toolkit. Use this skill when creating or modifying test files in test/Test.Core/Compiling/.

소스 정보

저장소
Azure/azure-api-management-policy-toolkit
최근 소스 활동
2026년 3월 8일 18:53
감지된 SKILL.md 언어
영어
스타
96
포크
37

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
policy-testing
description
Conventions and patterns for writing policy compilation tests in the Azure API Management policy toolkit. Use this skill when creating or modifying test files in test/Test.Core/Compiling/.
# Policy Testing Patterns This skill describes how to write tests for policy compilation in the Azure API Management policy toolkit. ## Test File — `test/Test.Core/Compiling/{PolicyName}Tests.cs` ### File Template ```csharp // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. namespace Microsoft.Azure.ApiManagement.PolicyToolkit.Compiling; [TestClass] public class {PolicyName}Tests { [TestMethod] [DataRow( """ [Document] public class PolicyDocument : IDocument { public void Inbound(IInboundContext context) { context.{MethodName}(new {PolicyName}Config() { // required properties only }); } } """, """ <policies> <inbound> <{xml-element-name} {attributes} /> </inbound> </policies> """, DisplayName = "Should compile {policy-name} policy" )] // ... more [DataRow] entries for each test case public void ShouldCompile{PolicyName}Policy(string code, string expectedXml) { code.CompileDocument().Should().BeSuccessful().And.DocumentEquivalentTo(expectedXml); } } ``` ### Key Conventions - **Namespace**: `Microsoft.Azure.ApiManagement.PolicyToolkit.Compiling` (not the test namespace — this matches the existing convention) - **Class name**: `{PolicyName}Tests` - **Test method name**: `ShouldCompile{PolicyName}Policy` - **Framework**: MSTest (`[TestClass]`, `[TestMethod]`, `[DataRow]`) - **Assertions**: FluentAssertions via `code.CompileDocument().Should().BeSuccessful().And.DocumentEquivalentTo(expectedXml)` - **Each test scenario** is a separate `[DataRow]` attribute on a single test method, with a `DisplayName` - **C# code strings** use raw string literals (`"""..."""`) for readability - **Test code does not need `using` statements** — `CompilerTestInitialize.CompileDocument()` wraps them automatically (adds `using Microsoft.Azure.ApiManagement.PolicyToolkit.Authoring;` and `using Microsoft.Azure.ApiManagement.PolicyToolkit.Authoring.Expressions;`) ## Required Test Coverage Each of the following must be a separate `[DataRow]`: ### 1. Required Fields Only (Constant Values) The baseline test — all required properties set, no optional properties: ```csharp [DataRow( """ [Document] public class PolicyDocument : IDocument { public void Inbound(IInboundContext context) { context.RateLimit(new RateLimitConfig() { Calls = 100, RenewalPeriod = 10 }); } } """, """ <policies> <inbound> <rate-limit calls="100" renewal-period="10" /> </inbound> </policies> """, DisplayName = "Should compile rate limit policy" )] ``` ### 2. Each Optional Field Individually One `[DataRow]` per optional field, added on top of required fields: ```csharp DisplayName = "Should compile rate limit policy with retry after header name" ``` ### 3. Expression Values For every property marked with `[ExpressionAllowed]`, add a test using the expression pattern: ```csharp [DataRow( """ [Document] public class PolicyDocument : IDocument { public void Inbound(IInboundContext context) { context.RateLimitByKey(new RateLimitByKeyConfig() { Calls = CallsExp(context.ExpressionContext), RenewalPeriod = RenewalPeriodExp(context.ExpressionContext), CounterKey = CounterKeyExp(context.ExpressionContext) }); } int CallsExp(IExpressionContext context) => 100; int RenewalPeriodExp(IExpressionContext context) => 10; string CounterKeyExp(IExpressionContext context) => context.Product.Name; } """, """ <policies> <inbound> <rate-limit-by-key calls="@(100)" renewal-period="@(10)" counter-key="@(context.Product.Name)" /> </inbound> </policies> """, DisplayName = "Should compile rate limit by key policy with expressions" )] ``` **Expression pattern rules:** - **Expression method naming**: Name expression helper methods as `{PropertyName}Exp` (e.g., `CallsExp`, `CounterKeyExp`). Method must take `IExpressionContext` and return the appropriate type. - Call it as `PropertyName = MethodName(context.ExpressionContext)` in the config initializer. - The expected XML wraps the method's return expression in `@(...)`. - Expression methods are defined as members of the `PolicyDocument` class. ### 4. Child Elements If the policy has child element arrays: ```csharp DisplayName = "Should compile rate limit policy with apis" DisplayName = "Should compile rate limit policy with operations in api" ``` ### 5. Multi-Section Tests If the policy is available in multiple sections (e.g., inbound, outbound, backend), **add one test per section**: ```csharp """ [Document] public class PolicyDocument : IDocument { public void Outbound(IOutboundContext context) { context.{MethodName}(new {PolicyName}Config() { /* ... */ }); } } """, """ <policies> <outbound> <{xml-element-name} {attributes} /> </outbound> </policies> """, DisplayName = "Should compile {policy-name} policy in outbound section" ``` Repeat for each additional section (backend, on-error, etc.). ### 6. All Optional Fields Together (if combinatorially important) When interactions between optional fields matter, add a combined test. ### 7. Error Cases (Skipped for Now) Error case testing patterns are not yet fully defined. For now: - **Do NOT implement error test cases** during Phase 5. - If you add error cases, mark them with `[Ignore]` attribute and document why they are skipped: ```csharp [DataRow( """ [Document] public class PolicyDocument : IDocument { public void Inbound(IInboundContext context) { context.RateLimit(new RateLimitConfig() { RenewalPeriod = 60 // Missing 'Calls' — required }); } } """, null, // No valid XML expected; compilation produces diagnostic errors DisplayName = "Should report error when required 'Calls' field is missing" )] [Ignore("Error case testing patterns not yet defined. Awaiting framework guidance.")] ``` When error case patterns are formalized, these tests will be re-enabled and assertion logic will be added to validate diagnostic errors. **Future reference (when enabled):** - When `expectedXml` is `null`, the test expects compilation to fail with diagnostic errors. - Use `DisplayName` values like "Should report error when {field} is missing" or "Should report error when {value} exceeds maximum." ## Test Infrastructure Tests rely on shared infrastructure that you do not need to modify: - **`CompilerTestInitialize`** (`test/Test.Core/CompilerTestInitialize.cs`) — Assembly-level setup that creates the Roslyn compilation environment and `DocumentCompiler` instance. Provides the `CompileDocument()` extension method. - **`CompilationResultAssertion`** (`test/Test.Core/Assertions/CompilationResultAssertion.cs`) — FluentAssertions extensions for `BeSuccessful()` and `DocumentEquivalentTo()`. - **`Usings.cs`** (`test/Test.Core/Usings.cs`) — Global usings for `FluentAssertions`, `Microsoft.VisualStudio.TestTools.UnitTesting`, and assertion helpers.
GitHub에서 보기