diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index c0bbc25457..b0b7a88dde 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -150,6 +150,24 @@ When a new issue is created, follow these steps: - Do not modify the `CODEOWNERS` file directly. - Do not modify `CHANGELOG.md` unless executing a release workflow (see `release-notes` prompt). - Do not close issues without a fix or without providing a clear reason. +- **Check `.github/instructions/` for matching `applyTo` patterns BEFORE starting any file creation or modification task.** Apply all conventions from those files from the start—do not refactor later. + +## Instruction File Lookup (Required Workflow) + +Before creating or modifying any file, check if matching instruction files exist: + +1. Scan `.github/instructions/` for files with `applyTo` patterns that match your file path +2. Read **all** matching instruction files completely before writing code +3. Apply **all** conventions, patterns, and requirements from the start +4. Do not skip instructions or plan to refactor later + +**Example:** Creating `src/Microsoft.Data.SqlClient/tests/UnitTests/ConnectionPool/NewTest.cs` +- File matches `applyTo: "**/tests/**,**/*Test*.cs"` from `testing.instructions.md` +- Must read `testing.instructions.md` before writing the first test method +- Must apply AAA pattern, XML doc comments, and all testing conventions from the start +- Do not create tests first and add documentation later + +This ensures consistency across the codebase and prevents rework. ## Terminal Execution Safety - Treat any non-zero shell exit code as a failed step that requires correction before proceeding. diff --git a/.github/instructions/testing.instructions.md b/.github/instructions/testing.instructions.md index df6b909f8a..025d0fe5f1 100644 --- a/.github/instructions/testing.instructions.md +++ b/.github/instructions/testing.instructions.md @@ -189,10 +189,15 @@ class and method level. #### What the Comments Must Explain - The behavior/contract being tested (not just restating the method name). - Why the scenario matters (for example: regression guard, parsing contract, sync/async parity, - isolation requirement). + isolation requirement, thread-safety validation, edge case handling). - For helper methods, what side effects occur (for example console redirection, file system copying, process execution) and why they are needed. +#### Implementation Guidance +- Always use the **Arrange-Act-Assert (AAA)** pattern with explicit section comments (see [Test Structure](#test-structure-arrange-act-assert-aaa-pattern)). +- Keep the test body focused on a single logical assertion; avoid testing multiple unrelated behaviors. +- Extract complex setup into helper methods or fixtures rather than embedding it in the test. + #### Style Guidance - Keep comments concise and factual. - Prefer behavior-focused wording over implementation trivia. @@ -212,25 +217,41 @@ public void AppRunWithMalformedConnectionStringReturnsOneAndWritesParseError() } ``` -### Test Structure +### Test Structure: Arrange-Act-Assert (AAA) Pattern + +All test methods **must** follow the **Arrange-Act-Assert (AAA)** pattern with explicit section comments. +This pattern improves readability and maintainability by clearly delineating setup, execution, and validation. + +**Pattern:** ```csharp -public class FeatureNameTests +[Fact] +public void MethodName_Scenario_ExpectedResult() { - [Fact] - public void MethodName_Scenario_ExpectedResult() - { - // Arrange - var sut = new SystemUnderTest(); - - // Act - var result = sut.PerformAction(); - - // Assert - Assert.Equal(expected, result); - } + // Arrange + // Set up test fixtures, initial state, dependencies, and test data + var sut = new SystemUnderTest(); + var input = new TestData(); + + // Act + // Execute the code under test + var result = sut.PerformAction(input); + + // Assert + // Validate outcomes and expectations + Assert.Equal(expected, result); } ``` +**Benefits:** +- Clear visual separation of setup, execution, and validation +- Easier to identify test logic flow +- Simpler to debug failing tests (know which section failed) +- Consistent convention across codebase +- Improves AI agent comprehension and test generation + +**Guideline:** Each section should be visually distinct. If AAA sections become too large (e.g., Arrange > 20 lines), +consider extracting helper methods or fixtures rather than embedding complexity in the test method itself. + ### Naming Conventions - Test class: `{ClassName}Tests` - Test method: `{Method}_{Scenario}_{ExpectedBehavior}`