From 377b8de947f6316ca319bb94cf8aa30436a77d19 Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Tue, 25 Aug 2026 14:28:05 -0700 Subject: [PATCH 01/31] Update image (#55648) --- .../modern-web-apps-azure/media/image5-8.png | Bin 33455 -> 36062 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/architecture/modern-web-apps-azure/media/image5-8.png b/docs/architecture/modern-web-apps-azure/media/image5-8.png index 8f01b369b564e953acac2fdf17d97ce4721ae8ab..6723c1be30d938f559ff5397e7bdd4554c9fd4a7 100644 GIT binary patch literal 36062 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 literal 33455 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

TJ@+;b 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 ZbR;S4catR_H6WQvN5eq90{r;p{{X`S#WMf^ From d0fa3a5ffa063ea5934322f743c2894f0b959bb4 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:26:33 -0700 Subject: [PATCH 02/31] Annotate changed files with build warnings (#55650) --- .github/workflows/generate-preview-links.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/generate-preview-links.yml b/.github/workflows/generate-preview-links.yml index 6deb553ebd2f3..f29384314db28 100644 --- a/.github/workflows/generate-preview-links.yml +++ b/.github/workflows/generate-preview-links.yml @@ -13,6 +13,7 @@ jobs: runs-on: ubuntu-latest permissions: statuses: read + checks: write pull-requests: write steps: - name: Harden Runner @@ -23,3 +24,4 @@ jobs: - uses: dotnet/docs-tools/actions/preview-link-generator@main with: repo_token: ${{ secrets.GITHUB_TOKEN }} + annotate_file_warnings: true From 04d0c5ababe375cff2a7775f55bc3f6e51f27e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Wed, 26 Aug 2026 00:34:45 +0200 Subject: [PATCH 03/31] Clarify MTP message bus UID filtering (#55646) * Document MTP message bus UID filtering Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Clarify MTP producer and consumer UID match Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../microsoft-testing-platform-architecture-extensions.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/core/testing/microsoft-testing-platform-architecture-extensions.md b/docs/core/testing/microsoft-testing-platform-architecture-extensions.md index 98ed287d3863b..ca5483b2bd349 100644 --- a/docs/core/testing/microsoft-testing-platform-architecture-extensions.md +++ b/docs/core/testing/microsoft-testing-platform-architecture-extensions.md @@ -3,7 +3,7 @@ title: Build extensions for Microsoft.Testing.Platform (MTP) description: Learn how to create in-process and out-of-process extensions for Microsoft.Testing.Platform (MTP). author: MarcoRossignoli ms.author: mrossignoli -ms.date: 07/17/2026 +ms.date: 08/25/2026 ai-usage: ai-assisted --- @@ -312,6 +312,9 @@ The `IDataConsumer` inherits from [IExtension](./microsoft-testing-platform-arch `ConsumeAsync`: This method is triggered whenever data of a type to which the current consumer is subscribed is published to the [`IMessageBus`](./microsoft-testing-platform-architecture-services.md#the-imessagebus-service). It receives the `IDataProducer` to provide details about the data payload's producer, as well as the `IData` payload itself. As you can see, `IData` is a generic placeholder interface that contains general informative data. The ability to publish different types of `IData` implies that the consumer needs to *switch* on the type itself to cast it to the correct type and access the specific information. +> [!IMPORTANT] +> The message bus doesn't invoke an `IDataConsumer` for data from an `IDataProducer` whose `IExtension.Uid` matches the consumer's `IExtension.Uid`. If an extension both publishes and subscribes to message bus data, assign distinct UIDs to its producer and consumer registrations. To process data that the extension produces itself, call the processing logic directly instead of routing the data through the message bus. + A sample implementation of a consumer that wants to elaborate the [`TestNodeUpdateMessage`](./microsoft-testing-platform-architecture-test-framework.md#the-testnodeupdatemessage-data) produced by a [testing framework](./microsoft-testing-platform-architecture-test-framework.md#test-framework-extension) could be: ```csharp From f597daadd4f69b5caf24b708937bb2546952ae85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 12:37:54 +0000 Subject: [PATCH 04/31] Bump the dotnet group with 1 update (#55718) Bumps Microsoft.Extensions.AsyncState from 10.8.0 to 10.9.0 --- updated-dependencies: - dependency-name: Microsoft.Extensions.AsyncState dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../csharp/AspNetCoreIntegration/AspNetCoreIntegration.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/extensions/snippets/async-state/csharp/AspNetCoreIntegration/AspNetCoreIntegration.csproj b/docs/core/extensions/snippets/async-state/csharp/AspNetCoreIntegration/AspNetCoreIntegration.csproj index 9638bdf09798a..1a62c4db19894 100644 --- a/docs/core/extensions/snippets/async-state/csharp/AspNetCoreIntegration/AspNetCoreIntegration.csproj +++ b/docs/core/extensions/snippets/async-state/csharp/AspNetCoreIntegration/AspNetCoreIntegration.csproj @@ -6,7 +6,7 @@ - + From 4330fbf452d71d94515b9d9d665e6ec0e837bf20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 12:41:35 +0000 Subject: [PATCH 05/31] Bump the dotnet group with 4 updates (#55734) Bumps CommunityToolkit.VectorData.InMemory from 1.0.0 to 1.0.1 Bumps Microsoft.Extensions.AI.OpenAI from 10.8.3 to 10.9.0 Bumps Microsoft.Extensions.Configuration from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Configuration.UserSecrets from 10.0.10 to 10.0.11 --- updated-dependencies: - dependency-name: CommunityToolkit.VectorData.InMemory dependency-version: 1.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.OpenAI dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration.UserSecrets dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../snippets/chat-with-data/openai/VectorDataAI.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ai/vector-stores/snippets/chat-with-data/openai/VectorDataAI.csproj b/docs/ai/vector-stores/snippets/chat-with-data/openai/VectorDataAI.csproj index f555b7d1c423b..69be09d4afce2 100644 --- a/docs/ai/vector-stores/snippets/chat-with-data/openai/VectorDataAI.csproj +++ b/docs/ai/vector-stores/snippets/chat-with-data/openai/VectorDataAI.csproj @@ -9,10 +9,10 @@ - - - - + + + + From df40d2f7e232235057ef94177cf2f4d705ffd2f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 14:45:21 +0200 Subject: [PATCH 06/31] Bump the dotnet group with 2 updates (#55720) --- .../csharp/MSTest.Project/MSTest.Project.csproj | 2 +- .../csharp/NUnit.TestProject/NUnit.Project.csproj | 2 +- .../csharp/XUnit.TestProject/XUnit.Project.csproj | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/core/testing/snippets/order-unit-tests/csharp/MSTest.Project/MSTest.Project.csproj b/docs/core/testing/snippets/order-unit-tests/csharp/MSTest.Project/MSTest.Project.csproj index de67a89c56f7e..0c41737a1e24d 100644 --- a/docs/core/testing/snippets/order-unit-tests/csharp/MSTest.Project/MSTest.Project.csproj +++ b/docs/core/testing/snippets/order-unit-tests/csharp/MSTest.Project/MSTest.Project.csproj @@ -8,7 +8,7 @@ - + diff --git a/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj b/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj index 52c129fc5ff8a..372f386f510f0 100644 --- a/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj +++ b/docs/core/testing/snippets/order-unit-tests/csharp/NUnit.TestProject/NUnit.Project.csproj @@ -10,7 +10,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/docs/core/testing/snippets/order-unit-tests/csharp/XUnit.TestProject/XUnit.Project.csproj b/docs/core/testing/snippets/order-unit-tests/csharp/XUnit.TestProject/XUnit.Project.csproj index 767ca5e1f7b41..ac785d6263b1b 100644 --- a/docs/core/testing/snippets/order-unit-tests/csharp/XUnit.TestProject/XUnit.Project.csproj +++ b/docs/core/testing/snippets/order-unit-tests/csharp/XUnit.TestProject/XUnit.Project.csproj @@ -8,9 +8,9 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 9c15423aaebe0818a8d03d96f7cb408af2feeae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Wed, 26 Aug 2026 15:48:38 +0200 Subject: [PATCH 07/31] Document Azure DevOps group limitations (#55325) * Document Azure DevOps group limitations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Refine Azure DevOps group guidance Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 75f9a66e-631b-4d19-9800-892cf968eefd * Align Azure DevOps group option guidance Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 75f9a66e-631b-4d19-9800-892cf968eefd --- .../core/testing/microsoft-testing-platform-test-reports.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/core/testing/microsoft-testing-platform-test-reports.md b/docs/core/testing/microsoft-testing-platform-test-reports.md index eb3a9ff1345ce..836d366e3593f 100644 --- a/docs/core/testing/microsoft-testing-platform-test-reports.md +++ b/docs/core/testing/microsoft-testing-platform-test-reports.md @@ -151,6 +151,7 @@ builder.TestHost.AddAzureDevOpsProvider(); |---|---|---| | `--report-azdo` | 1.9.0 | Enables the Azure DevOps report generator. Errors and warnings are written to the output in a format that Azure DevOps understands. | | `--report-azdo-severity` | 1.9.0 | Severity to use for reported events. Valid values are `error` (default) and `warning`. | +| `--report-azdo-groups` | 2.4.0 | Enables or disables per-assembly log groups. When enabled, each test assembly's output appears in a collapsible section of the Azure Pipelines log. Valid values are `on` and `off` (default). Requires `--report-azdo`. | | `--report-azdo-flaky-history` | 2.3.0 | Queries Azure DevOps test result history for the past N days (1-90) and annotates reported failures with flakiness context. Requires `--report-azdo`. | | `--report-azdo-demote-known-flaky` | 2.3.0 | Demotes failures that are flaky enough in the Azure DevOps history window (default threshold is 25%) from errors to warnings. Requires `--report-azdo` and `--report-azdo-flaky-history`. | | `--report-azdo-quarantine-file` | 2.3.0 | Path to a text file that lists quarantined test fully qualified names or glob patterns. Matching failures are reported as warnings. Requires `--report-azdo`. | @@ -163,8 +164,11 @@ builder.TestHost.AddAzureDevOpsProvider(); | `--publish-azdo-test-results` | 2.3.0 | Publishes test results live to the Azure DevOps **Tests** tab. | | `--publish-azdo-run-name` | 2.3.0 | Sets a custom Azure DevOps test run name for live test-result publishing. Requires `--publish-azdo-test-results`. | +> [!WARNING] +> Groups are disabled by default and aren't recommended when multiple test assemblies run in parallel. Azure DevOps `##[group]` and `##[endgroup]` formatting commands are sequential and anonymous. Concurrent assembly output can interleave, cause incorrect group nesting, and put lines under the wrong assembly. Set `--report-azdo-groups on` only for a single assembly or serialized assembly execution. + > [!NOTE] -> The **MTP version** column lists the MTP release in which each option first became available in a stable build. The Azure DevOps extension itself became stable in MTP 1.9.0 with `--report-azdo` and `--report-azdo-severity`; the remaining options were added in MTP 2.3.0. +> The **MTP version** column lists the first MTP version that contains each option. The Azure DevOps extension itself became stable in MTP 1.9.0 with `--report-azdo` and `--report-azdo-severity`; the remaining options were added in MTP 2.3.0 or 2.4.0. The extension automatically detects that it is running in continuous integration (CI) environment by checking the `TF_BUILD` environment variable. From 71ec8a72261bc9c4afe88a010f7628bcdf976e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Wed, 26 Aug 2026 15:56:23 +0200 Subject: [PATCH 08/31] Document current MSTest and MTP features (#55742) * Document latest MSTest and MTP features Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4b5507dd-30fe-4080-9f4b-a0abc234cd97 * Address MSTest documentation review Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4b5507dd-30fe-4080-9f4b-a0abc234cd97 * Correct MTP 2.4 documentation details Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4b5507dd-30fe-4080-9f4b-a0abc234cd97 --------- Copilot-Session: 4b5507dd-30fe-4080-9f4b-a0abc234cd97 --- .../testing/microsoft-testing-platform-ai.md | 77 ++++++++++++++++ ...ting-platform-architecture-capabilities.md | 9 +- ...esting-platform-architecture-extensions.md | 21 ++++- ...-testing-platform-architecture-services.md | 30 ++++-- .../microsoft-testing-platform-cli-options.md | 23 ++++- .../microsoft-testing-platform-config.md | 8 +- .../microsoft-testing-platform-features.md | 19 +++- .../microsoft-testing-platform-intro.md | 3 +- ...crosoft-testing-platform-open-telemetry.md | 51 ++++++++++- .../microsoft-testing-platform-server-mode.md | 50 ++++++++++ .../microsoft-testing-platform-telemetry.md | 4 +- ...rosoft-testing-platform-terminal-output.md | 3 +- ...microsoft-testing-platform-test-reports.md | 22 ++++- .../testing/mstest-analyzers/mstest0082.md | 89 ++++++++++++++++++ .../testing/mstest-analyzers/mstest0083.md | 91 +++++++++++++++++++ .../core/testing/mstest-analyzers/overview.md | 7 +- .../testing/mstest-analyzers/usage-rules.md | 8 +- docs/core/testing/unit-testing-mstest-sdk.md | 17 +++- docs/navigate/devops-testing/toc.yml | 10 ++ 19 files changed, 508 insertions(+), 34 deletions(-) create mode 100644 docs/core/testing/microsoft-testing-platform-ai.md create mode 100644 docs/core/testing/microsoft-testing-platform-server-mode.md create mode 100644 docs/core/testing/mstest-analyzers/mstest0082.md create mode 100644 docs/core/testing/mstest-analyzers/mstest0083.md diff --git a/docs/core/testing/microsoft-testing-platform-ai.md b/docs/core/testing/microsoft-testing-platform-ai.md new file mode 100644 index 0000000000000..91feccf7581b5 --- /dev/null +++ b/docs/core/testing/microsoft-testing-platform-ai.md @@ -0,0 +1,77 @@ +--- +title: Microsoft.Testing.Platform (MTP) AI integrations +description: Learn how MTP extensions access AI chat clients and configure the Azure AI Foundry provider. +author: Evangelink +ms.author: amauryleve +ms.date: 08/26/2026 +ai-usage: ai-assisted +--- + +# AI integrations + +The experimental [Microsoft.Testing.Platform.AI](https://www.nuget.org/packages/Microsoft.Testing.Platform.AI) package defines provider-neutral AI abstractions for test frameworks and MTP extensions. The package integrates with `Microsoft.Extensions.AI`, so an extension can request an without depending on a specific model provider. + +> [!IMPORTANT] +> The AI APIs use the `TPEXP` diagnostic ID and can change in a future release. The packages supply infrastructure to extensions; they don't add AI behavior to a test suite by themselves. + +## Choose the packages + +Add the abstractions package when you author an extension that consumes a chat client. Add a provider package to the test application that hosts the extension: + +```dotnetcli +dotnet add package Microsoft.Testing.Platform.AI +dotnet add package Microsoft.Testing.Extensions.AzureFoundry +``` + +`Microsoft.Testing.Extensions.AzureFoundry` is the Microsoft-provided reference provider. It creates an Azure OpenAI chat client through Azure AI Foundry. + +## Configure Azure AI Foundry + +Set the following environment variables: + +| Variable | Required | Description | +|---|---|---| +| `AZURE_OPENAI_ENDPOINT` | Yes | The Azure OpenAI resource endpoint, such as `https://my-resource.openai.azure.com`. | +| `AZURE_OPENAI_DEPLOYMENT_NAME` | Yes | The model deployment name. | +| `AZURE_OPENAI_API_KEY` | Conditional | The resource API key. Set this value unless you register a `TokenCredential` in code. | + +To keep credentials out of source control, supply these values through your local environment or a protected CI secret store. + +## Register the provider + +Disable the generated MTP entry point and register the provider in your custom `Main` method. For API-key authentication, call: + +```csharp +#pragma warning disable TPEXP +builder.AddAzureOpenAIChatClientProvider(); +#pragma warning restore TPEXP +``` + +For Microsoft Entra ID or managed identity, reference the `Azure.Identity` package and pass a credential: + +```csharp +using Azure.Identity; + +#pragma warning disable TPEXP +builder.AddAzureOpenAIChatClientProvider(new DefaultAzureCredential()); +#pragma warning restore TPEXP +``` + +When `AZURE_OPENAI_API_KEY` is set, the provider uses the API key before the supplied credential. Credential resolution and authentication occur when the first chat request runs, so configuration errors might not appear during provider registration. + +## Consume a chat client + +Implement `IChatClientProvider` to integrate another AI provider. An MTP extension can retrieve the registered chat client from its `IServiceProvider`: + +```csharp +IChatClient? client = + await serviceProvider.GetChatClientAsync(cancellationToken); +``` + +The call returns `null` when no available provider is registered. Before an extension sends test data to a model, document what data it sends and apply the privacy, security, and retention requirements for that data. + +## See also + +- [MTP features](microsoft-testing-platform-features.md) +- [Build extensions for MTP](microsoft-testing-platform-architecture-extensions.md) +- [Microsoft.Extensions.AI libraries](/dotnet/ai/microsoft-extensions-ai) diff --git a/docs/core/testing/microsoft-testing-platform-architecture-capabilities.md b/docs/core/testing/microsoft-testing-platform-architecture-capabilities.md index 0140788ba4e6b..46b245395fb44 100644 --- a/docs/core/testing/microsoft-testing-platform-architecture-capabilities.md +++ b/docs/core/testing/microsoft-testing-platform-architecture-capabilities.md @@ -3,7 +3,8 @@ title: Microsoft.Testing.Platform (MTP) capabilities overview description: Learn about MTP capabilities concept. author: MarcoRossignoli ms.author: mrossignoli -ms.date: 07/11/2024 +ms.date: 08/26/2026 +ai-usage: ai-assisted --- # Microsoft.Testing.Platform (MTP) capabilities @@ -76,7 +77,7 @@ If the testing framework implements this interface, at runtime, the following ca The hypothetical code fragment inside the extension could be something like: ```csharp -IServiceProvider provider = null; // TODO: Get IServiceProvider. +IServiceProvider serviceProvider = null; // TODO: Get IServiceProvider. var capabilities = serviceProvider.GetRequiredService(); // Utilize the `GetCapability` API to search for the specific capability to query. @@ -104,7 +105,7 @@ The preceding example illustrates how the capability infrastructure enables a po It's evident that not all details can be communicated through an interface. Considering the previous example, what should the extension expect if the `CanProvidePerTestCpuConsumption` is supported? What kind of custom information is expected to be transmitted via the [IMessageBus](./microsoft-testing-platform-architecture-services.md#the-imessagebus-service) by the testing framework? The solution is **documentation of the capability**. It's the responsibility of the capability *owner* to design, ship, and document it as clearly as possible to assist implementors who want to effectively *collaborate* with the extension that requires the specific capability. -For instance, the TRX report extension enables the testing framework to implement the necessary capability to accurately generate a TRX report. The extension to register is included in the NuGet package, but the capability to implement is found in the *contract only* NuGet package. +For instance, the TRX report extension enables the testing framework to implement the necessary capability to accurately generate a TRX report. The extension to register is included in the NuGet package, but the capability to implement is found in the [contract-only package](https://www.nuget.org/packages/Microsoft.Testing.Extensions.TrxReport.Abstractions). In conclusion, let's summarize the primary aspects of the capability system: @@ -119,7 +120,7 @@ The platform exposes a specialized interface named `ITestFrameworkCapability` th ### `IBannerMessageOwnerCapability` -An optional [test framework capability](#framework-capabilities) that allows the test framework to provide the banner message to the platform. If the message is `null` or if the capability is n't present, the platform will use its default banner message. +An optional [test framework capability](#framework-capabilities) allows the test framework to provide the banner message to the platform. If the message is `null` or the capability isn't present, the platform uses its default banner message. This capability implementation allows you to abstract away the various conditions that the test framework may need to consider when deciding whether or not the banner message should be displayed. diff --git a/docs/core/testing/microsoft-testing-platform-architecture-extensions.md b/docs/core/testing/microsoft-testing-platform-architecture-extensions.md index ca5483b2bd349..c7ec6e6f3d8c3 100644 --- a/docs/core/testing/microsoft-testing-platform-architecture-extensions.md +++ b/docs/core/testing/microsoft-testing-platform-architecture-extensions.md @@ -3,7 +3,7 @@ title: Build extensions for Microsoft.Testing.Platform (MTP) description: Learn how to create in-process and out-of-process extensions for Microsoft.Testing.Platform (MTP). author: MarcoRossignoli ms.author: mrossignoli -ms.date: 08/25/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -450,7 +450,7 @@ await messageBus.PublishAsync( > `TestNodeFileArtifact` is obsolete and was removed in MTP 2.0.0. To attach test-level files, use `FileArtifactProperty` on the `TestNode`. For more information, see [Migrate from Microsoft.Testing.Platform (MTP) v1 to v2](microsoft-testing-platform-migration-from-v1-to-v2.md#removed-obsolete-types). > [!NOTE] -> MTP 2.4.0 (unreleased as of July 2026) adds an experimental `kind` constructor overload and `Kind` property to `FileArtifact` and `SessionFileArtifact` (requires the `TPEXP` diagnostic to be suppressed). `Kind` is a producer-asserted, reverse-DNS identifier of the artifact *format* (for example, `microsoft.testing.trx`, `microsoft.testing.junit`, `microsoft.testing.ctrf`, or `microsoft.testing.html`) that post-processing can use to group artifacts of the same format for consolidation. Leave it `null` or omit it when the producer doesn't declare a known kind. At this time, `Kind` is only a metadata contract; don't assume broad merge orchestration beyond that. +> MTP 2.4.0 (unreleased as of August 2026) adds an experimental `kind` constructor overload and `Kind` property to `FileArtifact` and `SessionFileArtifact` (requires the `TPEXP` diagnostic to be suppressed). `Kind` is a producer-asserted, reverse-DNS identifier of the artifact *format* (for example, `microsoft.testing.trx`, `microsoft.testing.junit`, `microsoft.testing.ctrf`, or `microsoft.testing.html`) that post-processing uses to group artifacts of the same format. Leave it `null` or omit it when the producer doesn't declare a known kind. > > ```csharp > #pragma warning disable TPEXP // Experimental API. @@ -463,6 +463,12 @@ await messageBus.PublishAsync( > #pragma warning restore TPEXP > ``` +### The `IArtifactPostProcessor` extensions + +Starting with MTP 2.4.0, the experimental `IArtifactPostProcessor` extension point processes artifacts after a `dotnet test` invocation runs multiple test modules or after a retry runs multiple attempts. The `ArtifactPostProcessingMode` value identifies whether the processor handles `TestModules` or `RetryAttempts`. + +The built-in TRX, JUnit, CTRF, and HTML report extensions use this extension point to consolidate related report artifacts in a `merged` directory. HTML consolidation creates a merged summary and preserves the original per-process reports. To learn how report consolidation affects test output, see [Report consolidation](microsoft-testing-platform-test-reports.md#report-consolidation). + ### The `ITestHostEnvironmentVariableProvider` extensions The `ITestHostEnvironmentVariableProvider` is an *out-of-process* extension that enables you to establish custom environment variables for the test host. Utilizing this extension point ensures that the testing platform will initiate a new host with the appropriate environment variables, as detailed in the [architecture](./microsoft-testing-platform-architecture.md) section. @@ -695,6 +701,17 @@ public static void AddSelfRegisteredExtensions(this global::Microsoft.Testing.Pl If the call is missing, double-check that the props file is packaged under `buildMultiTargeting/` (not `build/`) inside the `.nupkg`, that `DisplayName` and `TypeFullName` metadata are present, and that the consumer hasn't set `false`. +## Load extensions dynamically + +Starting with MTP 2.4.0, pass `--enable-dynamic-extensions` to load extensions declared by `*.testingplatformextensions.json` manifest files next to the test application. MTP doesn't scan for arbitrary assemblies, and dynamic loading stays disabled unless each run explicitly enables it. + +Each manifest entry identifies an assembly and a `TestingPlatformBuilderHook` type to invoke. MTP reports every loaded extension in terminal output and fails the run if a manifest, assembly, type, or hook is invalid. Set an entry's `enabled` property to `false` to disable it without deleting the manifest. + +> [!WARNING] +> Dynamically loaded extensions run with full trust inside the test process. Use manifests and assemblies only from directories and sources you trust. + +For the complete manifest contract, see the [extension manifest JSON schema](https://github.com/microsoft/testfx/blob/main/docs/testingplatformextensions.schema.json) and [dynamic extension loading design](https://github.com/microsoft/testfx/blob/main/docs/RFCs/023-Dynamic-Extension-Loading.md). + ## Extensions execution order The testing platform consists of a [testing framework](./microsoft-testing-platform-architecture-test-framework.md#test-framework-extension) and any number of extensions that can operate [*in-process*](./microsoft-testing-platform-architecture.md#in-process-vs-out-of-process-extensions) or [*out-of-process*](./microsoft-testing-platform-architecture.md#in-process-vs-out-of-process-extensions). This document outlines the **sequence of calls** to all potential extensibility points to provide clarity on when a feature is anticipated to be invoked: diff --git a/docs/core/testing/microsoft-testing-platform-architecture-services.md b/docs/core/testing/microsoft-testing-platform-architecture-services.md index cd6814f0d6972..82db9a3c0d089 100644 --- a/docs/core/testing/microsoft-testing-platform-architecture-services.md +++ b/docs/core/testing/microsoft-testing-platform-architecture-services.md @@ -3,7 +3,8 @@ title: Microsoft.Testing.Platform services overview description: Learn about the available Microsoft.Testing.Platform (MTP) services. author: MarcoRossignoli ms.author: mrossignoli -ms.date: 07/11/2024 +ms.date: 08/26/2026 +ai-usage: ai-assisted --- # Microsoft.Testing.Platform services @@ -66,10 +67,11 @@ In the preceding code, both the `capabilitiesFactory` and the `adapterFactory` s The `IConfiguration` interface can be retrieved using the [`IServiceProvider`](#microsofttestingplatform-services) and provides access to the configuration settings for the testing framework and any extension points. By default, these configurations are loaded from: -* Environment variables -* A JSON file named `[assemblyName].testingplatformconfig.json` located near the entry point assembly. +* Command-line options, exposed under the `commandLineOptions:` section. +* Environment variables. +* A JSON file named *[appname].testconfig.json* located next to the test application executable. -**The order of precedence is maintained, which means that if a configuration is found in the environment variables, the JSON file will not be processed.** +Command-line options take precedence over environment variables, which take precedence over values from *[appname].testconfig.json*. MTP loads every source and selects the first source that supplies each key. For `commandLineOptions:` values, MTP selects a source for the complete option so indexed arguments don't combine across sources. For details about configuration-file discovery and precedence, see [MTP configuration settings](./microsoft-testing-platform-config.md). The interface is a straightforward key-value pair of strings: @@ -80,6 +82,8 @@ public interface IConfiguration } ``` +Starting with MTP 2.4.0, the configuration service also implements the `IConfigurationRoot` interface. Use `GetSection` to retrieve an `IConfigurationSection`, and use `GetChildren` to enumerate immediate child sections. A section exposes its `Key`, full `Path`, optional scalar `Value`, and `HasValue` state. Providers must implement `IHierarchicalConfigurationProvider` before their keys appear through enumeration, but you can retrieve a known path from any provider. + ### JSON configuration file The JSON file follows a hierarchical structure. To access child properties, you need to use the `:` separator. For example, consider a configuration for a potential testing framework like: @@ -172,6 +176,12 @@ The `ICommandLineOptions` can be obtained through certain APIs, such as the [ICo `ICommandLineOptions.TryGetOptionArgumentList(string optionName, out string[]? arguments)`: This method enables you to check whether a specific option has been set and, if so, retrieve the corresponding value or values (if the arity is more than one). Similar to the previous case, the `optionName` should be provided without the `--` prefix. +## The `IArtifactNamingService` service + +Starting with MTP 2.4.0, `IArtifactNamingService` gives extensions the same cross-platform file-name templating that MTP report extensions use. Retrieve it with `serviceProvider.GetArtifactNamingService()`, then call `ResolveFileName` with a template. + +The service expands `{pname}`, `{pid}`, `{asm}`, `{tfm}`, `{arch}`, and `{time}`. It preserves directory segments and sanitizes the leaf file name for the current operating system. Unknown placeholders remain unchanged. For placeholder descriptions, see [Report file names](microsoft-testing-platform-test-reports.md#report-file-names). + ## The `ILoggerFactory` service The testing platform comes with an integrated logging system that generates a log file. You can view the logging options by running the `--help` command. @@ -347,8 +357,9 @@ The API consists of: public interface IOutputDevice { Task DisplayAsync( - IOutputDeviceDataProducer producer, - IOutputDeviceData data); + IOutputDeviceDataProducer producer, + IOutputDeviceData data, + CancellationToken cancellationToken); } public interface IOutputDeviceDataProducer : IExtension @@ -394,18 +405,19 @@ IServiceProvider provider = null; // Get the service provider... var outputDevice = provider.GetOutputDevice(); await outputDevice.DisplayAsync( - this, + this, new FormattedTextOutputDeviceData($"TestingFramework version '{Version}' running tests with parallelism of {_dopValue}") { ForegroundColor = new SystemConsoleColor { ConsoleColor = ConsoleColor.Green } - }); + }, + CancellationToken.None); ``` Beyond the standard use of colored text, the main advantage of `IOutputDevice` and `IOutputDeviceData` is that the *output device* is entirely independent and unknown to the user. This allows for the development of complex user interfaces. For example, it's entirely feasible to implement a *real-time* web application that displays the progress of tests. ## The `IPlatformInformation` service -Provides information about the platform such as: name, version, commit hash and build date. +The experimental `IPlatformInformation` service provides the platform `Name`, optional `Version`, optional `CommitHash`, and optional `BuildDate`. diff --git a/docs/core/testing/microsoft-testing-platform-cli-options.md b/docs/core/testing/microsoft-testing-platform-cli-options.md index 6d01498c010e6..f10dbcdf8a015 100644 --- a/docs/core/testing/microsoft-testing-platform-cli-options.md +++ b/docs/core/testing/microsoft-testing-platform-cli-options.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform (MTP) CLI options reference description: Find platform and extension command-line options for MTP in one place. author: Evangelink ms.author: amauryleve -ms.date: 07/09/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -86,6 +86,13 @@ This article gives a central entry point for MTP command-line options. Defines the verbosity level when the `--diagnostic` switch is used. The available values are `Trace`, `Debug`, `Information`, `Warning`, `Error`, or `Critical`. +- **`--enable-dynamic-extensions`** + + Enables loading extensions declared by `*.testingplatformextensions.json` manifest files next to the test application. Dynamic extensions are disabled by default. For security requirements and the manifest schema, see [Load extensions dynamically](./microsoft-testing-platform-architecture-extensions.md#load-extensions-dynamically). + + > [!NOTE] + > This option is available in MTP starting with version 2.4.0. + - **`--exit-on-process-exit`** Exit the test process if dependent process exits. PID must be provided. @@ -142,6 +149,20 @@ This article gives a central entry point for MTP command-line options. The directory where the test results are going to be placed. If the specified directory doesn't exist, it's created. The default is `TestResults` in the directory that contains the test application. +- **`--server`** + + Starts the test application in JSON-RPC server mode for editor, IDE, or tool integration. Omit the value or use `jsonrpc`. For a supported source-only client, see [MTP server mode](./microsoft-testing-platform-server-mode.md). + + > [!IMPORTANT] + > The `dotnettestcli` value and its transport arguments are internal to the .NET SDK integration. Don't pass them manually. + +- **`--show-slowest-tests`** + + Shows the requested number of slowest tests in the terminal summary. When a run contains multiple test modules, MTP reports the slowest tests for each module. + + > [!NOTE] + > This option is available in MTP starting with version 2.4.0. + - **`--timeout`** A global test execution timeout. Takes one argument as string in the format `[h|m|s]` where `` is float. diff --git a/docs/core/testing/microsoft-testing-platform-config.md b/docs/core/testing/microsoft-testing-platform-config.md index a83e147ffb9cb..e0248bef36aa9 100644 --- a/docs/core/testing/microsoft-testing-platform-config.md +++ b/docs/core/testing/microsoft-testing-platform-config.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform (MTP) config options description: Learn how to configure MTP using testconfig.json configuration settings and environment variables. author: Evangelink ms.author: amauryleve -ms.date: 06/16/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -215,6 +215,12 @@ When set to any non-empty value, suppresses all ANSI color output. MTP honors th When set to `1` or `true`, suppresses the startup banner, the copyright message, and the telemetry banner. This is the standard .NET CLI environment variable and is honored by MTP. See also `TESTINGPLATFORM_NOBANNER`. +### `TESTINGPLATFORM_PIPE_DIRECTORY` environment variable + +Starting with MTP 2.4.0, this variable overrides the directory where MTP creates Unix domain-socket files for named-pipe communication. Use it when a sandbox or container doesn't allow socket creation in the default temporary directory. MTP creates and checks the directory, and fails with an error when the directory isn't writable or the resulting socket path is too long. + +The variable has no effect on Windows, where named pipes don't use file-system paths. It also doesn't relocate a pipe that another process, such as the .NET SDK, creates. + ### `TESTINGPLATFORM_WAIT_ATTACH_DEBUGGER` environment variable When set to `1`, the test process pauses at startup and waits for a debugger to attach before proceeding. Equivalent to the `--debug` command-line option. Not supported on browser platforms. diff --git a/docs/core/testing/microsoft-testing-platform-features.md b/docs/core/testing/microsoft-testing-platform-features.md index 8aeab51c02d70..0dd297e6ef6c8 100644 --- a/docs/core/testing/microsoft-testing-platform-features.md +++ b/docs/core/testing/microsoft-testing-platform-features.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform features description: Learn about the various Microsoft.Testing.Platform features, both built-in and available as extensions. author: nohwnd ms.author: jajares -ms.date: 07/03/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -31,16 +31,19 @@ Use the following path based on your goal: - Need to customize terminal output: [Terminal output](./microsoft-testing-platform-terminal-output.md) (built-in) - Need TRX or Azure DevOps reports: [Test reports](./microsoft-testing-platform-test-reports.md) (extension) -- Need GitHub Actions-native output (log groups, annotations, and job summary): [GitHub Actions report](./microsoft-testing-platform-test-reports.md#github-actions-reports) (extension, experimental) +- Need GitHub Actions-native output (log groups, annotations, and job summary): [GitHub Actions report](./microsoft-testing-platform-test-reports.md#github-actions-reports) (extension) - Need coverage data: [Code coverage](./microsoft-testing-platform-code-coverage.md) (extension) - Need crash or hang diagnostics: [Crash and hang dumps](./microsoft-testing-platform-crash-hang-dumps.md) (extension) - Need to record the screen during a run: [Diagnostics](./microsoft-testing-platform-diagnostics.md) (extension, experimental) - Need to deploy and launch a packaged-app test host: [Test host deployment](./microsoft-testing-platform-test-host-deployment.md) (extension, experimental) - Need to route platform logs through `Microsoft.Extensions.Logging`: [Microsoft.Extensions integration](./microsoft-testing-platform-extensions-integration.md) (extension, experimental) +- Need to build editor or IDE integration: [Server mode](./microsoft-testing-platform-server-mode.md) (built-in) +- Need to load extensions that aren't compile-time references: [Dynamic extension loading](./microsoft-testing-platform-architecture-extensions.md#load-extensions-dynamically) (built-in, opt-in) - Need to retry failed tests: [Retry](./microsoft-testing-platform-retry.md#retry) (extension) - Need hot reload support: [Hot Reload](./microsoft-testing-platform-hot-reload.md) (extension) - Need Microsoft Fakes support: [Microsoft Fakes](./microsoft-testing-platform-fakes.md) (extension) - Need OpenTelemetry traces and metrics: [OpenTelemetry](./microsoft-testing-platform-open-telemetry.md) (extension) +- Need to supply AI chat clients to a test framework or extension: [AI integrations](./microsoft-testing-platform-ai.md) (extension, experimental) - Telemetry data collection and opt-out: [Telemetry](./microsoft-testing-platform-telemetry.md) (extension) ## Built-in features @@ -51,6 +54,14 @@ These features are part of the core platform and don't require additional NuGet Status and progress reporting to the terminal: output modes, ANSI support, and progress indicators. +**[Server mode](./microsoft-testing-platform-server-mode.md)** + +Drive test discovery and execution from an editor, IDE, or other tool through JSON-RPC. + +**[Dynamic extension loading](./microsoft-testing-platform-architecture-extensions.md#load-extensions-dynamically)** + +Load explicitly declared extension assemblies from JSON manifests when a run opts in. + ## Extension features These features require installing NuGet packages. @@ -71,6 +82,10 @@ Collect process dump files when the test host crashes or hangs. Emit traces and metrics through OpenTelemetry during test runs. +**[AI integrations](./microsoft-testing-platform-ai.md)** (experimental) + +Supply provider-neutral AI chat clients to test frameworks and extensions, including through Azure AI Foundry. + **[Retry](./microsoft-testing-platform-retry.md)** Retry failed tests with configurable policies. diff --git a/docs/core/testing/microsoft-testing-platform-intro.md b/docs/core/testing/microsoft-testing-platform-intro.md index 8f723de2fd7b2..38e4508c74742 100644 --- a/docs/core/testing/microsoft-testing-platform-intro.md +++ b/docs/core/testing/microsoft-testing-platform-intro.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform overview - .NET test runner description: Learn about Microsoft.Testing.Platform (MTP), a lightweight and portable .NET test runner and VSTest alternative for running unit tests in CI pipelines, CLI, and IDEs. author: Evangelink ms.author: amauryleve -ms.date: 08/06/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -30,6 +30,7 @@ Use the following path, based on what you need next: - Migrate an existing VSTest setup: [Migrate from VSTest to MTP](./migrating-vstest-microsoft-testing-platform.md) - Add diagnostics, coverage, and reporting: [MTP features](./microsoft-testing-platform-features.md) - Build your own extension: [MTP architecture](./microsoft-testing-platform-architecture.md), [Extension points](./microsoft-testing-platform-architecture-extensions.md), and [Services](./microsoft-testing-platform-architecture-services.md) +- Build editor or IDE integration: [MTP server mode](./microsoft-testing-platform-server-mode.md) ## MTP pillars diff --git a/docs/core/testing/microsoft-testing-platform-open-telemetry.md b/docs/core/testing/microsoft-testing-platform-open-telemetry.md index 97781093d81a9..266a26e130910 100644 --- a/docs/core/testing/microsoft-testing-platform-open-telemetry.md +++ b/docs/core/testing/microsoft-testing-platform-open-telemetry.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform (MTP) OpenTelemetry description: Learn how to use the OpenTelemetry extension to emit traces and metrics from MTP. author: Evangelink ms.author: amauryleve -ms.date: 06/16/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -17,7 +17,7 @@ This extension integrates [OpenTelemetry](https://opentelemetry.io/) with Micros > This extension is available in MTP starting with version 2.1.0. > [!IMPORTANT] -> This extension is currently experimental. All public APIs are gated behind the `TPEXP` diagnostic ID. +> Starting with MTP 2.4.0, the OpenTelemetry extension follows the MTP release version and its public entry points are no longer experimental. ## Registration @@ -40,6 +40,14 @@ using var app = await builder.BuildAsync(); return await app.RunAsync(); ``` +To configure instrumentation, resource attributes, and an OTLP exporter from standard `OTEL_*` environment variables, call: + +```csharp +builder.AddOpenTelemetryProviderFromEnvironment(); +``` + +The method adds instrumentation only when you configure an exporter or pass a configuration callback, so you can leave the registration in the application when some environments don't export telemetry. + ## API ### `AddOpenTelemetryProvider` @@ -53,9 +61,48 @@ Registers the OpenTelemetry provider on `ITestApplicationBuilder`. Accepts two o Call on `TracerProviderBuilder` or `MeterProviderBuilder` to subscribe to the built-in `Microsoft.Testing.Platform` activity source and meter. +### `AddTestingPlatformResource` + +Call on `ResourceBuilder` to add test assembly, host, operating system, and runtime attributes. The detector also identifies CI provider, pipeline, branch, and commit information for GitHub Actions, Azure Pipelines, GitLab CI, and Jenkins. + +### `AddOpenTelemetryProviderFromEnvironment` + +Registers tracing, metrics, resource detection, and an OTLP exporter from standard OpenTelemetry environment variables. `OTEL_SDK_DISABLED=true` disables the integration. Configure `OTEL_TRACES_EXPORTER`, `OTEL_METRICS_EXPORTER`, or `OTEL_EXPORTER_OTLP_ENDPOINT` to activate export. + ## Activity source and meter The extension emits telemetry under: - Activity source: `Microsoft.Testing.Platform` - Meter: `Microsoft.Testing.Platform` + +## Semantic conventions + +MTP emits standard OpenTelemetry testing and code attributes where a convention exists, including `test.case.name`, `test.case.result.status`, `test.suite.name`, `code.function.name`, `code.file.path`, `code.line.number`, `code.stacktrace`, and `error.type`. Failed tests set the span status to `Error` and add an `exception` event. + +MTP extends the conventions with additional result states (`skipped`, `error`, `timeout`, `cancelled`, and `unknown`) and test attributes for concepts that OpenTelemetry doesn't define. To preserve existing dashboards, legacy attribute and instrument names remain enabled by default. + +When the launching process supplies `TRACEPARENT` and `TRACESTATE`, MTP places the test run under that trace instead of starting an unrelated root trace. + +## Emitted metrics + +| Instrument | Type | Unit | Description | +|---|---|---|---| +| `test.case.duration` | Histogram | `s` | Test duration, grouped by result status and suite. | +| `test.case.result.count` | Counter | `{test}` | Completed tests, grouped by result status and suite. | +| `test.case.active` | UpDownCounter | `{test}` | Tests that are currently running. | +| `test.run.duration` | Histogram | `s` | Run duration, grouped by result status and exit code. | +| `test.case.retry.count` | Counter | `{test}` | Tests scheduled for another attempt by the retry extension. | + +## Environment configuration + +| Environment variable | Default | Description | +|---|---|---| +| `TRACEPARENT`, `TRACESTATE` | Unset | W3C trace context for the parent run. | +| `TESTINGPLATFORM_OTEL_CAPTURE_TEST_OUTPUT` | `1` | Attaches captured standard output and error to test spans. Set to `0` when output might contain secrets. | +| `TESTINGPLATFORM_OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT` | `8192` | Sets the maximum characters retained for a string attribute. | +| `TESTINGPLATFORM_OTEL_EMIT_LEGACY_ATTRIBUTES` | `1` | Emits legacy attribute and instrument names alongside semantic-convention names. | +| `OTEL_SDK_DISABLED` | Unset | Set to `true` to disable the OpenTelemetry SDK. | +| `OTEL_SERVICE_NAME` | Unset | Overrides the service name. | +| `OTEL_EXPORTER_OTLP_ENDPOINT` | Unset | Sets the OTLP endpoint. | +| `OTEL_TRACES_EXPORTER`, `OTEL_METRICS_EXPORTER` | Unset | Selects trace and metric exporters. | diff --git a/docs/core/testing/microsoft-testing-platform-server-mode.md b/docs/core/testing/microsoft-testing-platform-server-mode.md new file mode 100644 index 0000000000000..a6c7bb88680da --- /dev/null +++ b/docs/core/testing/microsoft-testing-platform-server-mode.md @@ -0,0 +1,50 @@ +--- +title: Microsoft.Testing.Platform (MTP) server mode +description: Learn how tools and IDEs drive MTP test applications through JSON-RPC server mode. +author: Evangelink +ms.author: amauryleve +ms.date: 08/26/2026 +ai-usage: ai-assisted +--- + +# Server mode + +MTP server mode lets an editor, IDE, or other test tool launch a test application and drive discovery and execution through JSON-RPC. Use server mode when you build tooling around MTP. For normal command-line and CI runs, run the test application directly or use `dotnet test`. + +Start the public JSON-RPC server with `--server` or `--server jsonrpc`. + +> [!IMPORTANT] +> The .NET SDK uses a separate internal binary protocol through `--server dotnettestcli`. Don't pass that value yourself. `dotnet test` configures the transport and protocol arguments. + +## Use the source-only client + +Starting with MTP 2.4.0, the [Microsoft.Testing.Platform.ServerMode.Client.Sources](https://www.nuget.org/packages/Microsoft.Testing.Platform.ServerMode.Client.Sources) package supplies a canonical client for the JSON-RPC protocol. The package injects C# source into your project instead of adding a runtime assembly. + +The source-only design provides: + +- No runtime DLL or additional deployment dependency. +- Native AOT-compatible, reflection-free serialization. +- Protocol types and serialization code from the same repository as the MTP server. + +The injected `MtpServerClient` and `IMtpServerClient` types can initialize a connection, discover tests, run tests, request server exit, and report test-node updates. The types remain `internal` to your assembly. + +## Meet client requirements + +Use C# 12 or later. The package sets `LangVersion` to `12.0` when your project doesn't specify a language version. It also supplies internal compatibility types for .NET Framework 4.6.2 and `netstandard2.0`. + +Remove any hand-written copy of the MTP client before you add the package to avoid duplicate internal types. + +## Choose connection behavior + +Set `MtpServerClientOptions.IsStateful` to tell the server whether the client preserves state across requests: + +- Leave the value `false` for a single discovery or execution request followed by exit. +- Set the value to `true` for an editor or IDE session that sends multiple requests over the same connection. + +The client sends this setting through the experimental `capabilities.testing.isStateful` protocol capability. + +## See also + +- [Run and debug tests with MTP](microsoft-testing-platform-run-and-debug.md) +- [Build a test framework for MTP](microsoft-testing-platform-architecture-test-framework.md) +- [MTP JSON-RPC protocol](https://github.com/microsoft/testfx/blob/main/docs/mstest-runner-protocol/001-protocol-intro.md) diff --git a/docs/core/testing/microsoft-testing-platform-telemetry.md b/docs/core/testing/microsoft-testing-platform-telemetry.md index e4ea91187bc0a..056d67161bec1 100644 --- a/docs/core/testing/microsoft-testing-platform-telemetry.md +++ b/docs/core/testing/microsoft-testing-platform-telemetry.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform (MTP) telemetry description: Learn about the telemetry data collected by MTP and how to disable it. author: nohwnd ms.author: jajares -ms.date: 02/25/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -74,7 +74,7 @@ The telemetry feature collects the following data points: | All | If Hot reload is enabled. | | All | If the application crashed. | | All | If the application is running as NativeAOT. | -| All | If the repository is our own repository. Based on the `telemetry:isDevelopmentRepository` setting in _testingplatformconfig.json_. | +| All | Whether the repository is the MTP development repository, based on the `platformOptions:telemetry:isDevelopmentRepository` setting in *[appname].testconfig.json*. | | All | Name of the test framework you're using, as a hashed value. | | All | Name of your executable (which is usually the same as the name of the project), as a hashed value. | | All | Operating system, version and architecture. | diff --git a/docs/core/testing/microsoft-testing-platform-terminal-output.md b/docs/core/testing/microsoft-testing-platform-terminal-output.md index 8171110826548..c47670f8cbe17 100644 --- a/docs/core/testing/microsoft-testing-platform-terminal-output.md +++ b/docs/core/testing/microsoft-testing-platform-terminal-output.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform (MTP) terminal output description: Learn about the built-in terminal test reporter in MTP, including output modes, ANSI support, and progress indicators. author: evangelink ms.author: amauryleve -ms.date: 08/06/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -61,6 +61,7 @@ If your code must write directly to the console and you need that output to rema | `--show-stdout` | 2.2.1 | Determines when to show captured standard output of a test. Valid values are `All`, `Failed`, and `None`. Default is `All`. | | `--show-stderr` | 2.2.1 | Determines when to show captured error output of a test. Valid values are `All`, `Failed`, and `None`. Default is `All`. | | `--show-flaky-tests` | 2.4.0 | Controls the `flaky:` summary and the **Flaky tests** list for tests that pass after a retry. Use `on` or `off`; the default is `on`. Applies to MSTest `[Retry]` and the [retry extension](microsoft-testing-platform-retry.md). | +| `--show-slowest-tests` | 2.4.0 | Shows the requested number of slowest tests in the summary. For a multi-module run, MTP reports the slowest tests for each module. | > [!NOTE] > A dash (—) in the **MTP version** column marks core options that aren't tied to a specific version because they've been available since the platform's initial releases. diff --git a/docs/core/testing/microsoft-testing-platform-test-reports.md b/docs/core/testing/microsoft-testing-platform-test-reports.md index 836d366e3593f..4d2c3946b4712 100644 --- a/docs/core/testing/microsoft-testing-platform-test-reports.md +++ b/docs/core/testing/microsoft-testing-platform-test-reports.md @@ -3,7 +3,7 @@ title: Microsoft.Testing.Platform (MTP) test reports description: Learn about the MTP extensions that create test report files (TRX, HTML, JUnit, CTRF, Azure DevOps, GitHub Actions). author: evangelink ms.author: amauryleve -ms.date: 08/06/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -34,6 +34,14 @@ For example, `--report-trx-filename "{asm}_{tfm}_{arch}.trx"` reproduces the def > [!NOTE] > Placeholder names are case-sensitive and use lowercase. Placeholder support for report file names is available in MTP starting with version 2.3.0. +## Report consolidation + +Starting with MTP 2.4.0, MTP automatically post-processes report artifacts after a `dotnet test` invocation runs multiple test modules or after retry support runs multiple attempts. The feature is experimental in MTP 2.4.0. + +The TRX, JUnit, CTRF, and HTML extensions group compatible artifacts by report kind and write a consolidated report under the test results directory's `merged` subdirectory. CTRF consolidation combines module results and collapses retry attempts into the final test result with retry history. HTML consolidation creates a merged summary and preserves the original per-process reports. + +For custom report extensions, the experimental `IArtifactPostProcessor` API exposes separate `TestModules` and `RetryAttempts` processing modes. For more information, see [The `IArtifactPostProcessor` extensions](microsoft-testing-platform-architecture-extensions.md#the-iartifactpostprocessor-extensions). + ## Visual Studio test reports (TRX) The Visual Studio test result file (or TRX) is the default format for publishing test results. This extension requires the [Microsoft.Testing.Extensions.TrxReport](https://nuget.org/packages/Microsoft.Testing.Extensions.TrxReport) NuGet package. @@ -152,6 +160,7 @@ builder.TestHost.AddAzureDevOpsProvider(); | `--report-azdo` | 1.9.0 | Enables the Azure DevOps report generator. Errors and warnings are written to the output in a format that Azure DevOps understands. | | `--report-azdo-severity` | 1.9.0 | Severity to use for reported events. Valid values are `error` (default) and `warning`. | | `--report-azdo-groups` | 2.4.0 | Enables or disables per-assembly log groups. When enabled, each test assembly's output appears in a collapsible section of the Azure Pipelines log. Valid values are `on` and `off` (default). Requires `--report-azdo`. | +| `--report-azdo-annotations` | 2.4.0 | Enables or disables annotations for failed and skipped tests. Valid values are `on` (default) and `off`. Requires `--report-azdo`. | | `--report-azdo-flaky-history` | 2.3.0 | Queries Azure DevOps test result history for the past N days (1-90) and annotates reported failures with flakiness context. Requires `--report-azdo`. | | `--report-azdo-demote-known-flaky` | 2.3.0 | Demotes failures that are flaky enough in the Azure DevOps history window (default threshold is 25%) from errors to warnings. Requires `--report-azdo` and `--report-azdo-flaky-history`. | | `--report-azdo-quarantine-file` | 2.3.0 | Path to a text file that lists quarantined test fully qualified names or glob patterns. Matching failures are reported as warnings. Requires `--report-azdo`. | @@ -168,10 +177,12 @@ builder.TestHost.AddAzureDevOpsProvider(); > Groups are disabled by default and aren't recommended when multiple test assemblies run in parallel. Azure DevOps `##[group]` and `##[endgroup]` formatting commands are sequential and anonymous. Concurrent assembly output can interleave, cause incorrect group nesting, and put lines under the wrong assembly. Set `--report-azdo-groups on` only for a single assembly or serialized assembly execution. > [!NOTE] -> The **MTP version** column lists the first MTP version that contains each option. The Azure DevOps extension itself became stable in MTP 1.9.0 with `--report-azdo` and `--report-azdo-severity`; the remaining options were added in MTP 2.3.0 or 2.4.0. +> The **MTP version** column lists the first MTP version that contains each option. The Azure DevOps extension itself became stable in MTP 1.9.0 with `--report-azdo` and `--report-azdo-severity`; the remaining options were added in MTP 2.3.0 or the unreleased MTP 2.4.0. The extension automatically detects that it is running in continuous integration (CI) environment by checking the `TF_BUILD` environment variable. +Starting with MTP 2.4.0, Azure DevOps Markdown summaries aggregate results across every test module in a `dotnet test` invocation. When you also enable code coverage, the summary includes covered and total counts, percentages, threshold results, and an indicator when coverage data is partial. + ## GitHub Actions reports The GitHub Actions report emits GitHub Actions-native workflow commands so test runs produce a first-class experience on the runner: per-assembly log groups, failed and skipped test annotations (surfaced in the workflow **Annotations** tab and, when the source location resolves, on the pull request's **Files changed** diff), a Markdown job summary appended to the file referenced by `GITHUB_STEP_SUMMARY`, and slow-test notices. @@ -179,7 +190,7 @@ The GitHub Actions report emits GitHub Actions-native workflow commands so test The extension activates only when the run is on GitHub Actions (the `GITHUB_ACTIONS` environment variable is `true`) and the `--report-gh` switch is set; otherwise it does nothing. When active, each feature is enabled by default and can be turned off individually with its `--report-gh-*` option. > [!NOTE] -> Available in MTP starting with version 2.3.0. This extension is experimental, and its options and output format might change in a future version. +> The extension is available starting with MTP 2.3.0. Starting with MTP 2.4.0, its public entry points are no longer experimental. ### Manual registration @@ -195,6 +206,9 @@ builder.AddGitHubActionsProvider(); | `--report-gh` | 2.3.0 | Enables the GitHub Actions report generator so test runs emit workflow commands. Requires the run to be on GitHub Actions. | | `--report-gh-groups` | 2.3.0 | Enables or disables per-assembly log groups. Valid values are `on` (default) and `off`. Requires `--report-gh`. | | `--report-gh-annotations` | 2.3.0 | Enables or disables annotations for failed and skipped tests. Valid values are `on` (default) and `off`. Requires `--report-gh`. | -| `--report-gh-step-summary` | 2.3.0 | Enables or disables writing a Markdown job summary to the file referenced by `GITHUB_STEP_SUMMARY`. Valid values are `on` (default) and `off`. Requires `--report-gh`. | +| `--report-gh-step-summary` | 2.3.0 | Controls whether the extension writes a Markdown job summary to the file referenced by `GITHUB_STEP_SUMMARY`. Valid values are `on` (default), `off`, and, starting with MTP 2.4.0, `on-failure`. Requires `--report-gh`. | +| `--report-gh-step-summary-sections` | 2.4.0 | Selects summary content. Valid values are `test-results`, `slow-tests`, `coverage`, and `all` (default). Requires `--report-gh` and a summary mode other than `off`. | | `--report-gh-slow-test-notices` | 2.3.0 | Enables or disables slow-test notices. Valid values are `on` (default) and `off`. Requires `--report-gh`. | | `--report-gh-slow-test-threshold` | 2.3.0 | The duration a test can run before a slow-test notice is emitted. Accepts a bare number of seconds or a value with a unit suffix such as `90s`, `2m`, or `1.5h`. The default is `60s`. Requires `--report-gh`. | + +Starting with MTP 2.4.0, GitHub Actions Markdown summaries aggregate results across every test module in a `dotnet test` invocation. When you also enable code coverage, select `coverage` or `all` to include covered and total counts, percentages, threshold results, and an indicator when coverage data is partial. diff --git a/docs/core/testing/mstest-analyzers/mstest0082.md b/docs/core/testing/mstest-analyzers/mstest0082.md new file mode 100644 index 0000000000000..188e61fbc2b19 --- /dev/null +++ b/docs/core/testing/mstest-analyzers/mstest0082.md @@ -0,0 +1,89 @@ +--- +title: "MSTEST0082: A test class inherits a lifecycle or test method from a different MSTest version" +description: "Learn about code analysis rule MSTEST0082: A test class inherits a lifecycle or test method from a different MSTest version" +ms.date: 08/26/2026 +f1_keywords: +- MSTEST0082 +- InheritedMemberFromDifferentMSTestVersionAnalyzer +helpviewer_keywords: +- InheritedMemberFromDifferentMSTestVersionAnalyzer +- MSTEST0082 +author: evangelink +ms.author: amauryleve +ai-usage: ai-assisted +dev_langs: +- CSharp +--- +# MSTEST0082: A test class inherits a lifecycle or test method from a different MSTest version + +| Property | Value | +|-------------------------------------|----------------------------------------------------| +| **Rule ID** | MSTEST0082 | +| **Title** | A test class inherits a lifecycle or test method from a different MSTest version | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Warning | +| **Introduced in version** | 4.4.0 (preview) | +| **Is there a code fix** | No | + +> [!IMPORTANT] +> This analyzer is planned for MSTest 4.4 and is available only in preview builds until MSTest 4.4.0 is released. + +## Cause + +A discoverable test class inherits a public test method or lifecycle method from an assembly that references a different major version of MSTest. + +## Rule description + +MSTest matches test and lifecycle attributes by exact runtime type identity. MSTest v3 defines these attributes in `Microsoft.VisualStudio.TestPlatform.TestFramework`, while MSTest v4 defines them in `MSTest.TestFramework`. If a base library and a derived test project use different major versions, the adapter silently ignores inherited attributes from the other framework assembly. As a result, inherited tests aren't discovered, and inherited initialization or cleanup methods don't run. + +For example, a shared test library built with MSTest v3 might declare: + +```csharp +public abstract class SharedTests +{ + [TestMethod] public void InheritedTest() { } +} +``` + +An MSTest v4 project that derives from the base class triggers the diagnostic: + +```csharp +[TestClass] +public sealed class ProductTests : SharedTests { } // Violation +``` + +The analyzer checks inherited test methods, test initialization and cleanup methods, and class initialization and cleanup methods that are configured to run for derived classes. + +## How to fix violations + +Reference the same MSTest major version from the base library and the derived test project. Recompile the assembly that declares the base class and, for a custom attribute derived from an MSTest attribute, recompile the assembly that declares the custom attribute. + +## When to suppress warnings + +Don't suppress warnings from this rule. A violation means that MSTest silently skips inherited tests or lifecycle methods. + +## Suppress a warning + +If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule. + +```csharp +#pragma warning disable MSTEST0082 +// The code that's violating the rule is on this line. +#pragma warning restore MSTEST0082 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.MSTEST0082.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md). + +## See also + +- [Migrate from MSTest v3 to v4](../unit-testing-mstest-migration-v3-v4.md) +- [Test lifecycle](../unit-testing-mstest-writing-tests-lifecycle.md) diff --git a/docs/core/testing/mstest-analyzers/mstest0083.md b/docs/core/testing/mstest-analyzers/mstest0083.md new file mode 100644 index 0000000000000..f184e1a012ebe --- /dev/null +++ b/docs/core/testing/mstest-analyzers/mstest0083.md @@ -0,0 +1,91 @@ +--- +title: "MSTEST0083: Use '[ExecutableCondition]' instead of 'File.Exists' checks before 'Process.Start'" +description: "Learn about code analysis rule MSTEST0083: Use '[ExecutableCondition]' instead of 'File.Exists' checks before 'Process.Start'" +ms.date: 08/26/2026 +f1_keywords: +- MSTEST0083 +- UseExecutableConditionAttributeInsteadOfProcessCheckAnalyzer +helpviewer_keywords: +- UseExecutableConditionAttributeInsteadOfProcessCheckAnalyzer +- MSTEST0083 +author: evangelink +ms.author: amauryleve +ai-usage: ai-assisted +dev_langs: +- CSharp +--- +# MSTEST0083: Use '\[ExecutableCondition]' instead of 'File.Exists' checks before 'Process.Start' + +| Property | Value | +|-------------------------------------|----------------------------------------------------| +| **Rule ID** | MSTEST0083 | +| **Title** | Use '\[ExecutableCondition]' instead of 'File.Exists' checks before 'Process.Start' | +| **Category** | Usage | +| **Fix is breaking or non-breaking** | Non-breaking | +| **Enabled by default** | Yes | +| **Default severity** | Info | +| **Introduced in version** | 4.4.0 (preview) | +| **Is there a code fix** | Yes, for C# only | + +> [!IMPORTANT] +> This analyzer is planned for MSTest 4.4 and is available only in preview builds until MSTest 4.4.0 is released. + +## Cause + +A test method first checks whether an executable exists and returns or calls `Assert.Inconclusive` when it doesn't, then calls `Process.Start` with the same executable path. + +## Rule description + +Use `[ExecutableCondition]` to declare that a test requires an executable. The attribute reports the test as skipped when MSTest can't resolve the executable. An early return incorrectly reports the test as passed, and an imperative check hides the requirement from discovery and reporting tools. + +```csharp +[TestMethod] +public void RunsTool() +{ + if (!File.Exists("tool.exe")) return; // Violation + Process.Start("tool.exe"); +} +``` + +The analyzer recognizes a first-statement guard without a meaningful `else` branch when both `File.Exists` and the later `Process.Start` use the same constant executable path. + +## How to fix violations + +Replace the guard with `[ExecutableCondition]`. + +```csharp +[TestMethod] +[ExecutableCondition("tool.exe")] +public void RunsTool() => Process.Start("tool.exe"); +``` + +A C# code fix replaces the guard with the attribute. Visual Basic reports the diagnostic but doesn't provide an automatic fix. + +## When to suppress warnings + +Suppress the rule when the file check validates data rather than an executable prerequisite, or when the test needs behavior that `ExecutableConditionAttribute` can't express. + +## Suppress a warning + +If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule. + +```csharp +#pragma warning disable MSTEST0083 +// The code that's violating the rule is on this line. +#pragma warning restore MSTEST0083 +``` + +To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../../../fundamentals/code-analysis/configuration-files.md). + +```ini +[*.{cs,vb}] +dotnet_diagnostic.MSTEST0083.severity = none +``` + +For more information, see [How to suppress code analysis warnings](../../../fundamentals/code-analysis/suppress-warnings.md). + +## See also + +- [ExecutableConditionAttribute](../unit-testing-mstest-writing-tests-controlling-execution.md#executableconditionattribute) +- [MSTEST0061: Use OSCondition attribute instead of runtime check](mstest0061.md) +- [MSTEST0079: Use ArchitectureCondition attribute instead of runtime checks](mstest0079.md) diff --git a/docs/core/testing/mstest-analyzers/overview.md b/docs/core/testing/mstest-analyzers/overview.md index ade647d04055b..486ca0559e82a 100644 --- a/docs/core/testing/mstest-analyzers/overview.md +++ b/docs/core/testing/mstest-analyzers/overview.md @@ -3,7 +3,7 @@ title: MSTest code analysis description: Learn about the MSTest code analysis. author: evangelink ms.author: amauryleve -ms.date: 08/06/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -118,6 +118,7 @@ Rules that help ensure your test classes and methods are properly structured and - [MSTEST0072](mstest0072.md) - `[AssemblyFixtureProvider]` isn't supported with ahead-of-time compilation - [MSTEST0078](mstest0078.md) - `[DependsOn]` arguments should be valid - [MSTEST0081](mstest0081.md) - `[TestFilterProvider]` should reference a valid test filter type +- [MSTEST0082](mstest0082.md) - A test class inherits a lifecycle or test method from a different MSTest version Related documentation: [Write tests with MSTest](../unit-testing-mstest-writing-tests.md) @@ -241,6 +242,8 @@ Rules for configuring test execution, parallelization, and other test settings: - [MSTEST0079](mstest0079.md) - Use ArchitectureCondition attribute instead of runtime checks - [MSTEST0080](mstest0080.md) - Use CICondition attribute instead of environment checks - [MSTEST0081](mstest0081.md) - `[TestFilterProvider]` should reference a valid test filter type +- [MSTEST0082](mstest0082.md) - A test class inherits a lifecycle or test method from a different MSTest version +- [MSTEST0083](mstest0083.md) - Use `[ExecutableCondition]` instead of `File.Exists` checks before `Process.Start` Related documentation: [Configure MSTest](../unit-testing-mstest-configure.md), [Running tests](../unit-testing-mstest-running-tests.md) @@ -329,6 +332,8 @@ Related documentation: [Configure MSTest](../unit-testing-mstest-configure.md), | [MSTEST0079](mstest0079.md) | Usage | Use ArchitectureCondition attribute instead of runtime checks | Info | | [MSTEST0080](mstest0080.md) | Usage | Use CICondition attribute instead of environment checks | Info | | [MSTEST0081](mstest0081.md) | Usage | `[TestFilterProvider]` should reference a valid test filter type | Warning | +| [MSTEST0082](mstest0082.md) | Usage | A test class inherits a lifecycle or test method from a different MSTest version | Warning | +| [MSTEST0083](mstest0083.md) | Usage | Use `[ExecutableCondition]` instead of `File.Exists` checks before `Process.Start` | Info | \* Escalated to Error in `Recommended` and `All` modes. diff --git a/docs/core/testing/mstest-analyzers/usage-rules.md b/docs/core/testing/mstest-analyzers/usage-rules.md index 04154cef03af1..e3a24d0dbc481 100644 --- a/docs/core/testing/mstest-analyzers/usage-rules.md +++ b/docs/core/testing/mstest-analyzers/usage-rules.md @@ -3,7 +3,7 @@ title: MSTest Usage rules (code analysis) description: Learn about MSTest code analysis usage rules. author: evangelink ms.author: amauryleve -ms.date: 08/06/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -77,6 +77,8 @@ Usage rules support proper usage of MSTest attributes, methods, and patterns. Th | [MSTEST0079](mstest0079.md) | Use ArchitectureCondition attribute instead of runtime checks. | Info | Yes | | [MSTEST0080](mstest0080.md) | Use CICondition attribute instead of environment checks. | Info | Yes | | [MSTEST0081](mstest0081.md) | `[TestFilterProvider]` should reference a valid test filter type. | Warning | No | +| [MSTEST0082](mstest0082.md) | A test class inherits a lifecycle or test method from a different MSTest version. | Warning | No | +| [MSTEST0083](mstest0083.md) | Use `[ExecutableCondition]` instead of `File.Exists` checks before `Process.Start`. | Info | Yes | \* Escalated to Error in `Recommended` and `All` modes. @@ -91,6 +93,7 @@ Ensure your test classes, methods, and fixtures follow MSTest requirements: - **[MSTEST0030](mstest0030.md)**: Methods with [TestMethod] must be in a [TestClass]. - **[MSTEST0063](mstest0063.md)**: Test class constructor validation. - **[MSTEST0069](mstest0069.md)**: Apply [TestClass] directly so source-generated discovery finds the class. +- **[MSTEST0082](mstest0082.md)**: Keep base and derived test classes on the same MSTest major version. ### Lifecycle methods @@ -105,6 +108,7 @@ Validate initialization and cleanup methods: - **[MSTEST0034](mstest0034.md)**: Set ClassCleanupBehavior.EndOfClass. - **[MSTEST0050](mstest0050.md)**: Global test fixture validation. - **[MSTEST0072](mstest0072.md)**: Don't use shared assembly fixture providers with ahead-of-time compilation. +- **[MSTEST0082](mstest0082.md)**: Recompile inherited lifecycle methods against the test project's MSTest version. ### Data-driven testing @@ -181,6 +185,8 @@ Rules for tests that run in parallel: - **[MSTEST0079](mstest0079.md)**: Use `ArchitectureCondition` instead of runtime architecture checks. - **[MSTEST0080](mstest0080.md)**: Use `CICondition` instead of environment checks. - **[MSTEST0081](mstest0081.md)**: Validate test filter provider registrations. +- **[MSTEST0082](mstest0082.md)**: Detect inherited tests and lifecycle methods compiled against another MSTest major version. +- **[MSTEST0083](mstest0083.md)**: Use `ExecutableCondition` instead of an imperative executable check. ## Related documentation diff --git a/docs/core/testing/unit-testing-mstest-sdk.md b/docs/core/testing/unit-testing-mstest-sdk.md index 4de82c2381838..6c232f7fb31f2 100644 --- a/docs/core/testing/unit-testing-mstest-sdk.md +++ b/docs/core/testing/unit-testing-mstest-sdk.md @@ -3,7 +3,7 @@ title: MSTest SDK configuration author: MarcoRossignoli description: Learn how to configure MSTest.Sdk profiles, extensions, and advanced features. ms.author: mrossignoli -ms.date: 08/06/2026 +ms.date: 08/26/2026 ai-usage: ai-assisted --- @@ -46,7 +46,7 @@ You can set the profile using the property `TestingExtensionsProfile` with one o * [Code Coverage](./microsoft-testing-platform-code-coverage.md#microsoft-code-coverage) * [Trx Report](./microsoft-testing-platform-test-reports.md#visual-studio-test-reports-trx) -* `AllMicrosoft` - Enable all extensions shipped by Microsoft (including extensions with a restrictive license). +* `AllMicrosoft` - Enables the Microsoft extensions selected for broad out-of-the-box use, including extensions with a restrictive license. Experimental and API-only extensions can still require explicit opt-in. Enables the following extensions: @@ -55,6 +55,8 @@ You can set the profile using the property `TestingExtensionsProfile` with one o * [Fakes](./microsoft-testing-platform-fakes.md) (MSTest.Sdk 3.7.0+) * [Hang Dump](./microsoft-testing-platform-crash-hang-dumps.md#hang-dump) * [Hot Reload](./microsoft-testing-platform-hot-reload.md#hot-reload) + * [HTML Report](./microsoft-testing-platform-test-reports.md#html-reports) + * [GitHub Actions Report](./microsoft-testing-platform-test-reports.md#github-actions-reports) (MSTest.Sdk 4.3.0+) * [Retry](./microsoft-testing-platform-retry.md#retry) * [Trx Report](./microsoft-testing-platform-test-reports.md#visual-studio-test-reports-trx) * [AzureDevOpsReport](./microsoft-testing-platform-test-reports.md#azure-devops-reports) @@ -79,12 +81,15 @@ Here's a full example, using the `None` profile: | [Fakes](https://www.nuget.org/packages/Microsoft.Testing.Extensions.Fakes) | | | :heavy_check_mark:¹ | | [Hang Dump](https://www.nuget.org/packages/Microsoft.Testing.Extensions.HangDump) | | | :heavy_check_mark: | | [Hot Reload](https://www.nuget.org/packages/Microsoft.Testing.Extensions.HotReload) | | | :heavy_check_mark: | +| [HTML Report](https://www.nuget.org/packages/Microsoft.Testing.Extensions.HtmlReport) | | | :heavy_check_mark: | +| [GitHub Actions Report](https://www.nuget.org/packages/Microsoft.Testing.Extensions.GitHubActionsReport) | | | :heavy_check_mark:³ | | [Retry](https://www.nuget.org/packages/Microsoft.Testing.Extensions.Retry) | | | :heavy_check_mark: | | [Trx](https://www.nuget.org/packages/Microsoft.Testing.Extensions.TrxReport) | | :heavy_check_mark: | :heavy_check_mark: | | [AzureDevOpsReport](./microsoft-testing-platform-test-reports.md#azure-devops-reports) | | | :heavy_check_mark:² | ¹ MSTest.Sdk 3.7.0+ ² MSTest.Sdk 3.11.0+ +³ MSTest.Sdk 4.3.0+ ### Enable or disable extensions @@ -105,7 +110,13 @@ For example, to enable the crash dump extension (NuGet package [Microsoft.Testin For a list of all available extensions, see [MTP features](./microsoft-testing-platform-features.md). -Starting with MSTest.Sdk 4.3, enable the experimental JUnit report extension with `true`, then pass `--report-junit` when you run the test application. The extension is available only with Microsoft.Testing.Platform and isn't included in the `Default` or `AllMicrosoft` profiles. +Some MTP extensions remain opt-in and aren't included in the `Default` or `AllMicrosoft` profiles: + +- Starting with MSTest.Sdk 4.3, set `true`, then pass `--report-junit`. +- Starting with the MSTest.Sdk 4.4 preview, set `true`, then pass `--report-ctrf`. +- To reference the OpenTelemetry extension, set `true`. Because the extension requires API configuration, register it in your custom entry point as described in [OpenTelemetry](microsoft-testing-platform-open-telemetry.md). + +These extensions are available only with MTP. > [!WARNING] > It's important to review the licensing terms for each extension as they might vary. diff --git a/docs/navigate/devops-testing/toc.yml b/docs/navigate/devops-testing/toc.yml index eb7b83755c05d..a1f3ae47b9ba7 100644 --- a/docs/navigate/devops-testing/toc.yml +++ b/docs/navigate/devops-testing/toc.yml @@ -266,6 +266,10 @@ items: href: ../../core/testing/mstest-analyzers/mstest0080.md - name: MSTEST0081 href: ../../core/testing/mstest-analyzers/mstest0081.md + - name: MSTEST0082 + href: ../../core/testing/mstest-analyzers/mstest0082.md + - name: MSTEST0083 + href: ../../core/testing/mstest-analyzers/mstest0083.md - name: Migration items: - name: Migrate from MSTest v1 to v3 @@ -350,6 +354,9 @@ items: - name: OpenTelemetry href: ../../core/testing/microsoft-testing-platform-open-telemetry.md displayName: MTP,OpenTelemetry,traces,metrics + - name: AI integrations + href: ../../core/testing/microsoft-testing-platform-ai.md + displayName: MTP,AI,Azure AI Foundry,Azure OpenAI,IChatClient - name: Retry href: ../../core/testing/microsoft-testing-platform-retry.md displayName: MTP,retry,flaky tests @@ -392,6 +399,9 @@ items: - name: Services href: ../../core/testing/microsoft-testing-platform-architecture-services.md displayName: MTP,services,IServiceProvider + - name: Server mode + href: ../../core/testing/microsoft-testing-platform-server-mode.md + displayName: MTP,server mode,JSON-RPC,IDE integration,test client - name: VSTest href: https://github.com/microsoft/vstest - name: Testing with 'dotnet test' From e3da7baf9459ad74df0e686a0447ee3770a8eb78 Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Wed, 26 Aug 2026 18:49:38 +0200 Subject: [PATCH 09/31] Document Schannel handshake message limits for SslStream (#55739) * Document Schannel handshake message limits Explain how to diagnose oversized TLS handshake messages and configure the supported Schannel limits on Windows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d2be9392-507d-4112-8367-a273ce3668b1 * Reword Schannel section in second-person active voice Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d2be9392-507d-4112-8367-a273ce3668b1 --- .../extensions/sslstream-troubleshooting.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/core/extensions/sslstream-troubleshooting.md b/docs/core/extensions/sslstream-troubleshooting.md index 7ea96387312a9..af81aeff48554 100644 --- a/docs/core/extensions/sslstream-troubleshooting.md +++ b/docs/core/extensions/sslstream-troubleshooting.md @@ -3,7 +3,8 @@ title: Troubleshoot SslStream authentication issues description: Learn how to troubleshoot and investigate issues when performing authentication with SslStream in .NET. author: rzikm ms.author: radekzikmund -ms.date: 03/13/2023 +ms.date: 08/24/2026 +ai-usage: ai-assisted --- # Troubleshoot `SslStream` authentication issues @@ -28,6 +29,22 @@ Unfortunately, for client application the only solution is to add the certificat On Windows, you may encounter the `(0x8009030E): No credentials are available in the security package` error message when attempting to use certificates with ephemeral keys. This behavior is due to a bug in the underlying OS API (Schannel). More relevant info and workarounds can be found on the associated [GitHub issue](https://github.com/dotnet/runtime/issues/23749). +## Handshake message exceeds the Schannel limit + +On Windows, you might hit a handshake failure when a fragmented TLS handshake message exceeds the size limit that Schannel enforces. In this case, `SslStream` surfaces an whose inner reports error `0x80090326` (`SEC_E_ILLEGAL_MESSAGE`) and the message `The message received was unexpected or badly formatted`. You're most likely to produce large handshake messages when you use large certificate chains or when a peer sends a long list of acceptable certificate issuers during mutual TLS authentication. + +Because this error isn't specific to message size, confirm the cause before you change any Schannel configuration. Use a packet-capture tool to inspect the handshake messages and their sizes. + +If the capture confirms that a handshake message exceeds the limit, ask an administrator to create one of the following `DWORD` values under `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Messaging`: + +| Value | Applies to | Default | +| --- | --- | --- | +| `MessageLimitClient` | Messages that a TLS client accepts. | `0x8000` bytes | +| `MessageLimitServer` | Messages that a TLS server accepts when it doesn't use client authentication. | `0x4000` bytes | +| `MessageLimitServerClientAuth` | Messages that a TLS server accepts when it uses client authentication. | `0x8000` bytes | + +Set the smallest value that accepts the expected handshake message. Schannel supports values up to `0x10000` bytes. Don't change these settings unless you've confirmed the cause, because they affect the entire machine and larger limits increase memory use for each security context. For more information and registry-editing precautions, see [Messaging - fragment parsing](/windows-server/security/tls/tls-registry-settings#messaging--fragment-parsing). + ## Client and server do not possess a common algorithm When inspecting the `ClientHello` and `ServerHello` messages, you may find out that there is no cipher suite offered by both client and server or even that some ciphers are not offered even if explicitly configured via (available on Linux only). The underlying TLS library may disable TLS versions and cipher suites which are considered insecure. From 321718d5a0405d9b0ce0fafbae28e93c6c7052bb Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Wed, 26 Aug 2026 18:51:33 +0200 Subject: [PATCH 10/31] Make SslStream certificate guidance peer-agnostic (client + server) (#55745) * Make SslStream certificate guidance peer-agnostic Rework the 'Specify a server certificate' section into 'Specify a local certificate' so it covers both server and client authentication, since recent .NET versions handle the two sides symmetrically. Add a subsection on sending intermediate certificates to the peer via SslStreamCertificateContext, which is the recommended client-side alternative to modifying the machine or user certificate store. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: aebd17be-0e7d-42d7-a1fc-c1a86ed34610 * Clarify client certificate is passed via a collection AuthenticateAsClientAsync overloads take an X509CertificateCollection, not a single certificate. Reword the client bullet to reflect that. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: aebd17be-0e7d-42d7-a1fc-c1a86ed34610 --------- Copilot-Session: aebd17be-0e7d-42d7-a1fc-c1a86ed34610 --- .../extensions/sslstream-best-practices.md | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/docs/core/extensions/sslstream-best-practices.md b/docs/core/extensions/sslstream-best-practices.md index c05b588040c68..6e56b7ab76637 100644 --- a/docs/core/extensions/sslstream-best-practices.md +++ b/docs/core/extensions/sslstream-best-practices.md @@ -3,7 +3,8 @@ title: TLS/SSL best practices description: Learn the best practices when using SslStream in .NET. author: rzikm ms.author: radekzikmund -ms.date: 03/13/2023 +ms.date: 08/26/2026 +ai-usage: ai-assisted --- # TLS/SSL best practices @@ -25,19 +26,52 @@ Deferring the decision to the OS automatically uses the most recent version of T > [!NOTE] > is not supported on Windows and attempts to instantiate it will cause to be thrown. -## Specify a server certificate +## Specify a local certificate -When authenticating as a server, requires an instance. It is recommended to always use an instance which also contains the private key. +When authenticating as a server, always requires a certificate. When authenticating as a client, you also provide a certificate if the server requests one for mutual TLS (mTLS). In both roles, the certificate must be an instance that contains the private key. -There are multiple ways that a server certificate can be passed to : +Recent .NET versions handle the server and client sides symmetrically, so the following guidance applies whether the application authenticates as a server, a client, or both. -- Directly as a parameter to or via property -- From a selection callback in property -- By passing a in the property +You can provide the certificate to in several ways. -The recommended approach is to use the property. When the certificate is obtained by one of the other two ways, a instance is created internally by the implementation. Creating a involves building an which is a CPU intensive operation. It is more efficient to create a once and reuse it for multiple instances. +When you authenticate as a server: -Reusing instances also enables additional features such us [TLS session resumption](https://datatracker.ietf.org/doc/html/rfc5077) on Linux servers. +- Set the property, or pass the certificate to . +- Return the certificate from the callback. +- Set a on the property. + +When you authenticate as a client: + +- Add the certificate to the collection, or pass a collection that contains it to . +- Return the certificate from the callback. +- Set a on the property. + +> [!NOTE] +> The property is available starting in .NET 8. + +For better performance, use the certificate context property ( or ). When you provide the certificate in one of the other ways, creates a internally. Creating the context builds an , which is a CPU-intensive operation, so it's more efficient to create the context once and reuse it across multiple instances. + +Reusing a instance also enables extra features such as [TLS session resumption](https://datatracker.ietf.org/doc/html/rfc5077) on Linux servers. + +### Send intermediate certificates to the peer + +When an intermediate certificate authority issues the local certificate, the peer might not be able to build the full certificate chain unless the handshake includes the intermediate certificates. To send these intermediates, create a with the method and pass the intermediate certificates in the `additionalCertificates` parameter: + +```csharp +X509Certificate2 leafCertificate = GetLeafCertificate(); +X509Certificate2Collection intermediates = GetIntermediateCertificates(); + +SslStreamCertificateContext certificateContext = + SslStreamCertificateContext.Create(leafCertificate, intermediates); + +// When you authenticate as a server. +serverOptions.ServerCertificateContext = certificateContext; + +// When you authenticate as a client for mutual TLS. +clientOptions.ClientCertificateContext = certificateContext; +``` + +The context works the same way for both roles. On the client side, the certificate context is the recommended way to send intermediates, because the alternative—adding the intermediates to the machine or user certificate store—affects every application on the system. ## Custom `X509Certificate` validation From bd51fd966ccd908bbd35f95f6f10f39801a9560c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 12:30:29 -0700 Subject: [PATCH 11/31] Bump the dotnet group with 1 update (#55671) Bumps OpenAI from 2.12.0 to 2.13.0 --- updated-dependencies: - dependency-name: OpenAI dependency-version: 2.13.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/ai/quickstarts/snippets/assistants/AIAssistants.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/snippets/assistants/AIAssistants.csproj b/docs/ai/quickstarts/snippets/assistants/AIAssistants.csproj index b2e4de73baa1a..5fa861af45d89 100644 --- a/docs/ai/quickstarts/snippets/assistants/AIAssistants.csproj +++ b/docs/ai/quickstarts/snippets/assistants/AIAssistants.csproj @@ -10,7 +10,7 @@ - + From c4077a0fba8022e79c5193c9e213e3af1f1533f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Wed, 26 Aug 2026 22:27:44 +0200 Subject: [PATCH 12/31] Clarify architecture migration from VSTest to MTP (#55748) * Clarify MTP architecture migration Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Preserve failures in MTP matrix example Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9217a-7e79-45e0-b9df-334d627940fe --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2dd9217a-7e79-45e0-b9df-334d627940fe --- ...microsoft-testing-platform-test-reports.md | 5 ++ ...ating-vstest-microsoft-testing-platform.md | 74 ++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/docs/core/testing/microsoft-testing-platform-test-reports.md b/docs/core/testing/microsoft-testing-platform-test-reports.md index 4d2c3946b4712..74cfb5c40717a 100644 --- a/docs/core/testing/microsoft-testing-platform-test-reports.md +++ b/docs/core/testing/microsoft-testing-platform-test-reports.md @@ -187,8 +187,13 @@ Starting with MTP 2.4.0, Azure DevOps Markdown summaries aggregate results acros The GitHub Actions report emits GitHub Actions-native workflow commands so test runs produce a first-class experience on the runner: per-assembly log groups, failed and skipped test annotations (surfaced in the workflow **Annotations** tab and, when the source location resolves, on the pull request's **Files changed** diff), a Markdown job summary appended to the file referenced by `GITHUB_STEP_SUMMARY`, and slow-test notices. +This extension requires the [Microsoft.Testing.Extensions.GitHubActionsReport](https://www.nuget.org/packages/Microsoft.Testing.Extensions.GitHubActionsReport) NuGet package. + The extension activates only when the run is on GitHub Actions (the `GITHUB_ACTIONS` environment variable is `true`) and the `--report-gh` switch is set; otherwise it does nothing. When active, each feature is enabled by default and can be turned off individually with its `--report-gh-*` option. +> [!IMPORTANT] +> The `--report-gh` option belongs to `Microsoft.Testing.Extensions.GitHubActionsReport`. The [GitHubActionsTestLogger](https://www.nuget.org/packages/GitHubActionsTestLogger) package provides a different option, `--report-github`. The options aren't aliases and work only when the test project registers the package that owns the option. + > [!NOTE] > The extension is available starting with MTP 2.3.0. Starting with MTP 2.4.0, its public entry points are no longer experimental. diff --git a/docs/core/testing/migrating-vstest-microsoft-testing-platform.md b/docs/core/testing/migrating-vstest-microsoft-testing-platform.md index 6ec31331068e1..11ec53c1026c5 100644 --- a/docs/core/testing/migrating-vstest-microsoft-testing-platform.md +++ b/docs/core/testing/migrating-vstest-microsoft-testing-platform.md @@ -3,7 +3,8 @@ title: Migration guide from VSTest to Microsoft.Testing.Platform (MTP) description: Step-by-step guide to migrate from VSTest to Microsoft.Testing.Platform (MTP), including argument mapping, project configuration, and CI pipeline updates. author: Youssef1313 ms.author: ygerges -ms.date: 09/15/2025 +ms.date: 08/26/2026 +ai-usage: ai-assisted --- # Migrate from VSTest to Microsoft.Testing.Platform (MTP) @@ -89,6 +90,54 @@ The build-related arguments are irrelevant to the test platform and as such don' - `-r|--runtime ` - `-v|--verbosity ` +Although `--arch` remains a build-related option, it replaces the architecture that VSTest selects through `RunConfiguration.TargetPlatform`. Pass `--arch` to `dotnet test` itself, before any `--` separator. + +For example, migrate this VSTest project command: + +```dotnetcli +dotnet test MyTests.csproj -c Debug -- RunConfiguration.TargetPlatform=x86 /Parallel +``` + +For .NET 10 SDK and later versions, use this MTP command: + +```dotnetcli +dotnet test --project MyTests.csproj -c Debug --arch x86 +``` + +Replace `x86` with `x64` to target x64. MTP runs test modules in parallel by default, so `/Parallel` doesn't need a replacement. To limit module-level parallelism, use `--max-parallel-test-modules `. + +> [!IMPORTANT] +> You can't combine `--solution` with `--arch`, `--os`, or `--runtime`. These options set `RuntimeIdentifier` as a global MSBuild property, and solution builds don't support a global `RuntimeIdentifier`. To test a solution across architectures, invoke each test project separately or set `RuntimeIdentifier` in the individual test projects. + +For example, replace these four solution-level VSTest commands: + +```dotnetcli +dotnet test MySolution.sln -c Debug -- RunConfiguration.TargetPlatform=x86 /Parallel +dotnet test MySolution.sln -c Release -- RunConfiguration.TargetPlatform=x86 /Parallel +dotnet test MySolution.sln -c Debug -- RunConfiguration.TargetPlatform=x64 /Parallel +dotnet test MySolution.sln -c Release -- RunConfiguration.TargetPlatform=x64 /Parallel +``` + +For .NET 10 SDK and later versions, use a project-level matrix: + +```powershell +$testProjects = @("tests/A.Tests/A.Tests.csproj", "tests/B.Tests/B.Tests.csproj") +$testRunFailed = $false +foreach ($configuration in "Debug", "Release") { + foreach ($architecture in "x86", "x64") { + foreach ($testProject in $testProjects) { + dotnet test --project $testProject -c $configuration --arch $architecture + if ($LASTEXITCODE -ne 0) { + $testRunFailed = $true + } + } + } +} +if ($testRunFailed) { + throw "One or more test runs failed." +} +``` + The test-related arguments are VSTest specific and so need to be transformed to match the new platform. The following table shows the mapping between the VSTest arguments and the new platform: | VSTest argument | New platform argument | @@ -108,6 +157,8 @@ The test-related arguments are VSTest specific and so need to be transformed to | `--results-directory ` | `--results-directory ` | | `-s\|--settings ` | Depends upon the selected test framework | | `-t\|--list-tests` | `--list-tests` | +| `-- RunConfiguration.TargetPlatform=` | `--arch ` for a project invocation | +| `/Parallel` | No option required. MTP runs test modules in parallel by default. | | `-- ` | `--test-parameter` (provided by [VSTestBridge](microsoft-testing-platform-extensions-vstest-bridge.md)) | #### `--collect` @@ -178,6 +229,27 @@ dotnet test --report-trx > As explained earlier, when using MTP with the VSTest-based `dotnet test`, extra `--` is needed before the arguments intended to be passed to the platform. > So, this becomes `dotnet test -- --report-trx`. +GitHub Actions reporter options are package-specific and aren't interchangeable: + +| Reporter package | MTP option | +|---|---| +| [Microsoft.Testing.Extensions.GitHubActionsReport](microsoft-testing-platform-test-reports.md#github-actions-reports) | `--report-gh` | +| [GitHubActionsTestLogger](https://www.nuget.org/packages/GitHubActionsTestLogger) | `--report-github` | + +The test application recognizes an option only when the package that owns it is installed and registered. For example, if you migrate `--logger GitHubActions` and keep the `GitHubActionsTestLogger` package, replace the VSTest command: + +```dotnetcli +dotnet test --logger GitHubActions +``` + +With .NET 10 SDK and later versions, use: + +```dotnetcli +dotnet test --report-github +``` + +For .NET 9 SDK and earlier versions, use `dotnet test -- --report-github` instead. + #### `--settings` VSTest's `--settings` is used to specify a RunSettings file for the test run. RunSettings isn't supported by the core MTP and was replaced by a more modern [`testconfig.json`](./microsoft-testing-platform-config.md) configuration file. However, MSTest and NUnit still support the old RunSettings when running MTP and `--settings` is still supported. From 0e8aae764c6f43f6f64d5f1e146c7f24e51ea009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Wed, 26 Aug 2026 22:28:43 +0200 Subject: [PATCH 13/31] Clarify Azure DevOps group defaults by MTP release (#55746) * Clarify Azure DevOps group defaults Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38a4cc51-af9e-4ff9-9005-f429f2341f1f * Address Azure DevOps group review feedback Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 38a4cc51-af9e-4ff9-9005-f429f2341f1f --------- Copilot-Session: 38a4cc51-af9e-4ff9-9005-f429f2341f1f --- .../core/testing/microsoft-testing-platform-test-reports.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/core/testing/microsoft-testing-platform-test-reports.md b/docs/core/testing/microsoft-testing-platform-test-reports.md index 74cfb5c40717a..3c5aa9b8f4a5d 100644 --- a/docs/core/testing/microsoft-testing-platform-test-reports.md +++ b/docs/core/testing/microsoft-testing-platform-test-reports.md @@ -159,7 +159,7 @@ builder.TestHost.AddAzureDevOpsProvider(); |---|---|---| | `--report-azdo` | 1.9.0 | Enables the Azure DevOps report generator. Errors and warnings are written to the output in a format that Azure DevOps understands. | | `--report-azdo-severity` | 1.9.0 | Severity to use for reported events. Valid values are `error` (default) and `warning`. | -| `--report-azdo-groups` | 2.4.0 | Enables or disables per-assembly log groups. When enabled, each test assembly's output appears in a collapsible section of the Azure Pipelines log. Valid values are `on` and `off` (default). Requires `--report-azdo`. | +| `--report-azdo-groups` | 2.4.0 | Enables or disables per-assembly log groups. When enabled, each test assembly's output appears in a collapsible section of the Azure Pipelines log. Valid values are `on` and `off`. MTP 2.4.0 preview builds default to `on`; the stable MTP 2.4.0 release defaults to `off`. Requires `--report-azdo`. | | `--report-azdo-annotations` | 2.4.0 | Enables or disables annotations for failed and skipped tests. Valid values are `on` (default) and `off`. Requires `--report-azdo`. | | `--report-azdo-flaky-history` | 2.3.0 | Queries Azure DevOps test result history for the past N days (1-90) and annotates reported failures with flakiness context. Requires `--report-azdo`. | | `--report-azdo-demote-known-flaky` | 2.3.0 | Demotes failures that are flaky enough in the Azure DevOps history window (default threshold is 25%) from errors to warnings. Requires `--report-azdo` and `--report-azdo-flaky-history`. | @@ -174,10 +174,10 @@ builder.TestHost.AddAzureDevOpsProvider(); | `--publish-azdo-run-name` | 2.3.0 | Sets a custom Azure DevOps test run name for live test-result publishing. Requires `--publish-azdo-test-results`. | > [!WARNING] -> Groups are disabled by default and aren't recommended when multiple test assemblies run in parallel. Azure DevOps `##[group]` and `##[endgroup]` formatting commands are sequential and anonymous. Concurrent assembly output can interleave, cause incorrect group nesting, and put lines under the wrong assembly. Set `--report-azdo-groups on` only for a single assembly or serialized assembly execution. +> Don't enable groups when multiple test assemblies run in parallel. Azure DevOps `##[group]` and `##[endgroup]` formatting commands are sequential and anonymous. Concurrent assembly output can interleave, cause incorrect group nesting, and put lines under the wrong assembly. If you use an MTP 2.4.0 preview build, pass `--report-azdo-groups off` to disable groups. The stable MTP 2.4.0 release disables groups by default. Pass `--report-azdo-groups on` only for a single assembly or serialized assembly execution. > [!NOTE] -> The **MTP version** column lists the first MTP version that contains each option. The Azure DevOps extension itself became stable in MTP 1.9.0 with `--report-azdo` and `--report-azdo-severity`; the remaining options were added in MTP 2.3.0 or the unreleased MTP 2.4.0. +> The **MTP version** column lists the first MTP version that contains each option. The Azure DevOps extension itself became stable in MTP 1.9.0 with `--report-azdo` and `--report-azdo-severity`; the remaining options were added in MTP 2.3.0 or 2.4.0. The extension automatically detects that it is running in continuous integration (CI) environment by checking the `TF_BUILD` environment variable. From 2e9ccad4f01728e011b3f69cb1b43e7da355e403 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:29:06 -0700 Subject: [PATCH 14/31] Bump the dotnet group with 5 updates (#55738) Bumps Aspire.Azure.Data.Tables from 13.4.6 to 13.5.0 Bumps Aspire.StackExchange.Redis from 13.4.6 to 13.5.0 Bumps Microsoft.Extensions.Hosting from 10.0.8 to 10.0.11 Bumps Microsoft.Extensions.Logging.Abstractions from 10.0.8 to 10.0.11 Bumps Microsoft.Extensions.Logging.Console from 10.0.8 to 10.0.11 --- updated-dependencies: - dependency-name: Aspire.Azure.Data.Tables dependency-version: 13.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Aspire.StackExchange.Redis dependency-version: 13.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Aspire.StackExchange.Redis dependency-version: 13.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Hosting dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Logging.Console dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Hosting dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Logging.Console dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/orleans/host/snippets/aspire/Client/Client.csproj | 4 ++-- .../snippets/aspire/ServiceDefaults/ServiceDefaults.csproj | 2 +- docs/orleans/host/snippets/aspire/Silo/Silo.csproj | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/orleans/host/snippets/aspire/Client/Client.csproj b/docs/orleans/host/snippets/aspire/Client/Client.csproj index 2be5e5bc85dc5..9c0308f6c49c6 100644 --- a/docs/orleans/host/snippets/aspire/Client/Client.csproj +++ b/docs/orleans/host/snippets/aspire/Client/Client.csproj @@ -8,12 +8,12 @@ - + - + diff --git a/docs/orleans/host/snippets/aspire/ServiceDefaults/ServiceDefaults.csproj b/docs/orleans/host/snippets/aspire/ServiceDefaults/ServiceDefaults.csproj index 3a46347aefe7c..a229877443b73 100644 --- a/docs/orleans/host/snippets/aspire/ServiceDefaults/ServiceDefaults.csproj +++ b/docs/orleans/host/snippets/aspire/ServiceDefaults/ServiceDefaults.csproj @@ -11,7 +11,7 @@ - + diff --git a/docs/orleans/host/snippets/aspire/Silo/Silo.csproj b/docs/orleans/host/snippets/aspire/Silo/Silo.csproj index a9d1304b3565a..37512d869aa1d 100644 --- a/docs/orleans/host/snippets/aspire/Silo/Silo.csproj +++ b/docs/orleans/host/snippets/aspire/Silo/Silo.csproj @@ -8,14 +8,14 @@ - + - + - + From 76da820b07f843a5c2c8bebf038d3e7128b209b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:35:03 -0700 Subject: [PATCH 15/31] Bump the dotnet group with 7 updates (#55735) Bumps Microsoft.Extensions.AI.Abstractions from 10.8.3 to 10.9.0 Bumps Microsoft.Extensions.AI.Evaluation from 10.8.0 to 10.9.0 Bumps Microsoft.Extensions.AI.Evaluation.Quality from 10.8.0 to 10.9.0 Bumps Microsoft.Extensions.AI.OpenAI from 10.8.3 to 10.9.0 Bumps Microsoft.Extensions.Configuration from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Configuration.UserSecrets from 10.0.10 to 10.0.11 Bumps Microsoft.NET.Test.Sdk from 18.8.1 to 18.9.0 --- updated-dependencies: - dependency-name: Microsoft.Extensions.AI.Abstractions dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.Evaluation dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.Evaluation.Quality dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.OpenAI dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration.UserSecrets dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.NET.Test.Sdk dependency-version: 18.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../snippets/evaluate-ai-responses/TestAI.csproj | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/ai/evaluation/snippets/evaluate-ai-responses/TestAI.csproj b/docs/ai/evaluation/snippets/evaluate-ai-responses/TestAI.csproj index e0bc3e7de0354..26ba83c069668 100644 --- a/docs/ai/evaluation/snippets/evaluate-ai-responses/TestAI.csproj +++ b/docs/ai/evaluation/snippets/evaluate-ai-responses/TestAI.csproj @@ -11,13 +11,13 @@ - - - - - - - + + + + + + + From df7e399687dae94a31d9ee4d8a623a00a290ff9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:42:15 -0700 Subject: [PATCH 16/31] Bump the dotnet group with 7 updates (#55733) Bumps Microsoft.Extensions.AI.Abstractions from 10.8.3 to 10.9.0 Bumps Microsoft.Extensions.AI.Evaluation from 10.8.0 to 10.9.0 Bumps Microsoft.Extensions.AI.Evaluation.Reporting from 10.8.0 to 10.9.0 Bumps Microsoft.Extensions.AI.OpenAI from 10.8.3 to 10.9.0 Bumps Microsoft.Extensions.Configuration from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Configuration.UserSecrets from 10.0.10 to 10.0.11 Bumps Microsoft.NET.Test.Sdk from 18.8.1 to 18.9.0 --- updated-dependencies: - dependency-name: Microsoft.Extensions.AI.Abstractions dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.Evaluation dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.Evaluation.Reporting dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.OpenAI dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration.UserSecrets dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.NET.Test.Sdk dependency-version: 18.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../evaluate-safety/EvaluateResponseSafety.csproj | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/ai/evaluation/snippets/evaluate-safety/EvaluateResponseSafety.csproj b/docs/ai/evaluation/snippets/evaluate-safety/EvaluateResponseSafety.csproj index 8c917a2c6cc4d..3ce3438fac17a 100644 --- a/docs/ai/evaluation/snippets/evaluate-safety/EvaluateResponseSafety.csproj +++ b/docs/ai/evaluation/snippets/evaluate-safety/EvaluateResponseSafety.csproj @@ -11,14 +11,14 @@ - - - + + + - - - - + + + + From 3e535ae9ab784cc2a8e924e6f0565b0038192348 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:54:38 -0700 Subject: [PATCH 17/31] Bump the dotnet group with 4 updates (#55732) Bumps Microsoft.Extensions.AI from 10.8.1 to 10.9.0 Bumps Microsoft.Extensions.AI.OpenAI from 10.8.1 to 10.9.0 Bumps Microsoft.Extensions.Configuration from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Configuration.UserSecrets from 10.0.10 to 10.0.11 --- updated-dependencies: - dependency-name: Microsoft.Extensions.AI dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.AI.OpenAI dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration.UserSecrets dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../csharp/HandleInvalidToolInput.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ai/how-to/snippets/handle-invalid-tool-input/csharp/HandleInvalidToolInput.csproj b/docs/ai/how-to/snippets/handle-invalid-tool-input/csharp/HandleInvalidToolInput.csproj index 9cc03596550af..a17b8ae9fe95b 100644 --- a/docs/ai/how-to/snippets/handle-invalid-tool-input/csharp/HandleInvalidToolInput.csproj +++ b/docs/ai/how-to/snippets/handle-invalid-tool-input/csharp/HandleInvalidToolInput.csproj @@ -8,10 +8,10 @@ - - - - + + + + From 6f2929899960a376c58521d3fdcd439914672705 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:56:58 -0700 Subject: [PATCH 18/31] Bump the dotnet group with 2 updates (#55731) Bumps Microsoft.Extensions.Configuration.Binder from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Hosting from 10.0.10 to 10.0.11 --- updated-dependencies: - dependency-name: Microsoft.Extensions.Configuration.Binder dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Hosting dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../dependency-injection/snippets/console/console-di.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core/extensions/dependency-injection/snippets/console/console-di.csproj b/docs/core/extensions/dependency-injection/snippets/console/console-di.csproj index 5e326936e111a..ee874bc639c74 100644 --- a/docs/core/extensions/dependency-injection/snippets/console/console-di.csproj +++ b/docs/core/extensions/dependency-injection/snippets/console/console-di.csproj @@ -9,8 +9,8 @@ - - + + From e1c0d6ffa598f0686d61c40ba609fc97bea5601d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:57:56 -0700 Subject: [PATCH 19/31] Bump the dotnet group with 4 updates (#55730) Bumps Microsoft.CodeAnalysis from 5.6.0 to 5.9.0 Bumps Microsoft.CodeAnalysis.Analyzers from 5.6.0 to 5.9.0 Bumps Microsoft.CodeAnalysis.CSharp from 5.6.0 to 5.9.0 Bumps Microsoft.CodeAnalysis.CSharp.Workspaces from 5.6.0 to 5.9.0 --- updated-dependencies: - dependency-name: Microsoft.CodeAnalysis dependency-version: 5.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.CodeAnalysis.Analyzers dependency-version: 5.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.CodeAnalysis.CSharp dependency-version: 5.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.CodeAnalysis.CSharp dependency-version: 5.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.CodeAnalysis.CSharp.Workspaces dependency-version: 5.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj | 4 ++-- .../MakeConst/MakeConst.Test/MakeConst.Test.csproj | 2 +- .../MakeConst/MakeConst/MakeConst.csproj | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj index a48924612fd42..4ad3dd306d3be 100644 --- a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj +++ b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.CodeFixes/MakeConst.CodeFixes.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj index 930e832c01091..dd920bf8a436b 100644 --- a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj +++ b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst.Test/MakeConst.Test.csproj @@ -11,7 +11,7 @@ - + diff --git a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst/MakeConst.csproj b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst/MakeConst.csproj index 12bc57d45d344..0ceff617a9adf 100644 --- a/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst/MakeConst.csproj +++ b/docs/csharp/roslyn-sdk/tutorials/snippets/how-to-write-csharp-analyzer-code-fix/MakeConst/MakeConst/MakeConst.csproj @@ -9,8 +9,8 @@ - - + + From 493b3fb566f6116629b990a8b6bf3f44958eaf08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:58:58 -0700 Subject: [PATCH 20/31] Bump the dotnet group with 2 updates (#55729) Bumps Microsoft.Extensions.AmbientMetadata.Build from 10.8.0 to 10.9.0 Bumps Microsoft.Extensions.Hosting from 10.0.10 to 10.0.11 --- updated-dependencies: - dependency-name: Microsoft.Extensions.AmbientMetadata.Build dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet - dependency-name: Microsoft.Extensions.Hosting dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../buildmetadata-msbuild-azure.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core/diagnostics/ambient-metadata/snippets/buildmetadata-msbuild-azure/buildmetadata-msbuild-azure.csproj b/docs/core/diagnostics/ambient-metadata/snippets/buildmetadata-msbuild-azure/buildmetadata-msbuild-azure.csproj index cc602d1338e92..3647d7f0a3547 100644 --- a/docs/core/diagnostics/ambient-metadata/snippets/buildmetadata-msbuild-azure/buildmetadata-msbuild-azure.csproj +++ b/docs/core/diagnostics/ambient-metadata/snippets/buildmetadata-msbuild-azure/buildmetadata-msbuild-azure.csproj @@ -13,8 +13,8 @@ - - + + From 4f564d7f630471dc5aea387fc2fb2363e95802f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 14:01:53 -0700 Subject: [PATCH 21/31] Bump the dotnet group with 2 updates (#55728) Bumps Microsoft.Extensions.Configuration from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Configuration.Binder from 10.0.10 to 10.0.11 --- updated-dependencies: - dependency-name: Microsoft.Extensions.Configuration dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Configuration.Binder dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../DictionaryBinding/DictionaryBinding.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/core/extensions/snippets/configuration/binding-scenarios/DictionaryBinding/DictionaryBinding.csproj b/docs/core/extensions/snippets/configuration/binding-scenarios/DictionaryBinding/DictionaryBinding.csproj index 58b4b914be8a5..6966fba4701d7 100644 --- a/docs/core/extensions/snippets/configuration/binding-scenarios/DictionaryBinding/DictionaryBinding.csproj +++ b/docs/core/extensions/snippets/configuration/binding-scenarios/DictionaryBinding/DictionaryBinding.csproj @@ -8,8 +8,8 @@ - - + + From 2b6e14edfe82b511b684344beca764276e30e782 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 14:09:12 -0700 Subject: [PATCH 22/31] Bump the dotnet group with 2 updates (#55726) Bumps Microsoft.Extensions.Hosting from 10.0.10 to 10.0.11 Bumps ModelContextProtocol from 2.1.0 to 2.2.0 --- updated-dependencies: - dependency-name: Microsoft.Extensions.Hosting dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: ModelContextProtocol dependency-version: 2.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../ai/quickstarts/snippets/mcp-server/SampleMcpServer.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ai/quickstarts/snippets/mcp-server/SampleMcpServer.csproj b/docs/ai/quickstarts/snippets/mcp-server/SampleMcpServer.csproj index 1084fdd5c4e62..5dd028f3c2256 100644 --- a/docs/ai/quickstarts/snippets/mcp-server/SampleMcpServer.csproj +++ b/docs/ai/quickstarts/snippets/mcp-server/SampleMcpServer.csproj @@ -33,8 +33,8 @@ - - + + From 34ad4d39918218213e9c815c19eaf1a0afacaa57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 14:09:53 -0700 Subject: [PATCH 23/31] Bump the dotnet group with 4 updates (#55713) Bumps Microsoft.Extensions.Hosting from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Logging from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Logging.Console from 10.0.10 to 10.0.11 Bumps Microsoft.Extensions.Telemetry from 10.8.0 to 10.9.0 --- updated-dependencies: - dependency-name: Microsoft.Extensions.Hosting dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Logging dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Logging.Console dependency-version: 10.0.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dotnet - dependency-name: Microsoft.Extensions.Telemetry dependency-version: 10.9.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../core/enrichment/snippets/enrichment/Enrichment.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/core/enrichment/snippets/enrichment/Enrichment.csproj b/docs/core/enrichment/snippets/enrichment/Enrichment.csproj index c70733ef6ea9c..d8281734d4269 100644 --- a/docs/core/enrichment/snippets/enrichment/Enrichment.csproj +++ b/docs/core/enrichment/snippets/enrichment/Enrichment.csproj @@ -8,10 +8,10 @@ - - - - + + + + From 7d294fc1104aa8f8bad498f212f5a0ae3a77bfa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 14:10:34 -0700 Subject: [PATCH 24/31] Bump the dotnet group with 1 update (#55716) Bumps Microsoft.Agents.AI.OpenAI from 1.17.0 to 1.18.0 --- updated-dependencies: - dependency-name: Microsoft.Agents.AI.OpenAI dependency-version: 1.18.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dotnet ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/ai/snippets/prompt-engineering/multi-turn-chat.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/snippets/prompt-engineering/multi-turn-chat.csproj b/docs/ai/snippets/prompt-engineering/multi-turn-chat.csproj index 6a813ad952e16..c56e69ebabd11 100644 --- a/docs/ai/snippets/prompt-engineering/multi-turn-chat.csproj +++ b/docs/ai/snippets/prompt-engineering/multi-turn-chat.csproj @@ -10,7 +10,7 @@ - +