diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b409664f5121..5a759c4e7d89 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -201,10 +201,20 @@ dependency already in use. Add a new dependency only at the narrowest necessary - Do not allow unused `using` directives to be committed. - Use `#if NET` blocks for .NET Core specific code, and `#if NETFRAMEWORK` for .NET Framework specific code. +### Target framework properties + +Never hardcode a TFM (`net8.0`, `net9.0`, etc.) in a `.csproj` file. Use the appropriate +property: + +| Context | Property | Defined in | +| --- | --- | --- | +| Source projects and test projects (.NET) | `$(SdkTargetFramework)` | Root `Directory.Build.props` (equals `$(NetCurrent)` from Arcade) | +| Multi-targeting with .NET Framework | Match the pattern used by peer projects in the same area. Some areas use Arcade properties (`$(NetFrameworkToolCurrent)`, `$(NetMinimum)`); others hardcode `net472`. | +| Test asset projects (`test/TestAssets/`) | `$(CurrentTargetFramework)` | Substituted at test runtime by `TestAssetsManager` via `ToolsetInfo.CurrentTargetFramework` | + ## Testing - Large changes should always include test changes. -- When creating new test projects in test/TestAssets/TestProjects, always use `$(CurrentTargetFramework)` for the `` property instead of hard-coding a specific version like `net8.0`. - The Skip parameter of the Fact attribute to point to the specific issue link. - To run tests in this repo (after a full build, invoke the repo-local bootstrap SDK directly): - For MSTest-style projects: `./.dotnet/dotnet test path/to/project.csproj --filter "FullyQualifiedName~TestName"` diff --git a/test/AGENTS.md b/test/AGENTS.md index e237a82dd06c..95d2fbcde941 100644 --- a/test/AGENTS.md +++ b/test/AGENTS.md @@ -11,6 +11,24 @@ Guidance for changes under `test/`. ## Conventions & gotchas +- **Derive from `SdkTest`** (in `Microsoft.NET.TestFramework.MSTest`). This gives you + `TestAssetsManager`, `Log` (wired to MSTest's `TestContext`), and + `BinLogArgument(...)` for binlog paths collected by Helix. +- **Use `SdkTestContext.Current` for paths** — never hardcode paths or manually discover + locations at runtime (e.g. walking up directories): + + | Need | API | + | --- | --- | + | `dotnet` executable (the built SDK) | `SdkTestContext.Current.ToolsetUnderTest.DotNetHostPath` | + | Repo root (nullable in Helix) | `SdkTestContext.Current.ToolsetUnderTest.RepoRoot` or `SdkTestContext.GetRepoRoot()` | + | Test execution directory | `SdkTestContext.Current.TestExecutionDirectory` | + | Test assets root | `SdkTestContext.Current.TestAssetsDirectory` (or `TestAssetsManager` from base class) | + + **Never** use `.dotnet/dotnet` or `Process.Start("dotnet", ...)` without going through + `DotNetHostPath` — this ensures the test exercises the built SDK, not a globally + installed one. +- **Test asset placement.** Put test inputs (projects, packages, workloads, etc.) in + `test/TestAssets/`. They are automatically deployed to Helix via `test/UnitTests.proj`. - **Don't raise parallelism.** MSTest is repo-defaulted to `None` in `test/Directory.Build.props` because of concurrency flakiness; a few projects opt into `ClassLevel`. Cranking it up causes Helix over-subscription/timeouts. @@ -21,3 +39,31 @@ Guidance for changes under `test/`. them). (See `src/Cli/AGENTS.md` for the CLI-specific detail.) - Helix work-item partitioning is driven by `test/UnitTests.proj` (per-project method limits/multipliers) — relevant if a project's tests are unusually slow or numerous. + +## Helix deployment + +CI runs SDK tests on Helix machines where the repo layout differs from a local dev box. +The conventions above (SdkTest, SdkTestContext, test asset placement) handle most cases. +This section covers the additional Helix-specific concerns. + +### Deploying extra files to the test execution directory + +If a test needs files at runtime beyond the test assembly and test assets (scripts, +`.props`/`.targets` files, etc.), add them to `TestExecutionDirectoryFiles` in +`test/UnitTests.proj`: + +```xml + + relative/subfolder/ + +``` + +Files listed here are copied to `TestExecutionDirectoryFiles\` inside the Helix payload +and become available under `SdkTestContext.Current.TestExecutionDirectory`. + +### Validate locally in a simulated Helix layout + +Consider validating in a simulated Helix layout when your tests reference paths, use +test assets, or add new Helix payload (`TestExecutionDirectoryFiles`). See +[Repro Helix Failure](../documentation/project-docs/repro-helix-failure.md) for the +steps to create a local Helix test layout and run tests against it.