Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.251003001" />
<PackageVersion Include="OpenTelemetry" Version="1.15.3" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsVersion)" />
</ItemGroup>
<ItemGroup Label="Test dependencies">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ internal static class AzureDevOpsCommandLineOptions
{
public const string AzureDevOpsOptionName = "report-azdo";
public const string AzureDevOpsReportSeverity = "report-azdo-severity";
public const string PublishAzureDevOpsRunNameOptionName = "publish-azdo-run-name";
public const string PublishAzureDevOpsTestResultsOptionName = "publish-azdo-test-results";
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public IReadOnlyCollection<CommandLineOption> GetCommandLineOptions()
[
new CommandLineOption(AzureDevOpsCommandLineOptions.AzureDevOpsOptionName, AzureDevOpsResources.OptionDescription, ArgumentArity.Zero, false),
new CommandLineOption(AzureDevOpsCommandLineOptions.AzureDevOpsReportSeverity, AzureDevOpsResources.SeverityOptionDescription, ArgumentArity.ExactlyOne, false),
new CommandLineOption(AzureDevOpsCommandLineOptions.PublishAzureDevOpsRunNameOptionName, AzureDevOpsResources.PublishAzdoRunNameOptionDescription, ArgumentArity.ExactlyOne, false),
new CommandLineOption(AzureDevOpsCommandLineOptions.PublishAzureDevOpsTestResultsOptionName, AzureDevOpsResources.PublishAzdoTestResultsOptionDescription, ArgumentArity.Zero, false),
];

public Task<ValidationResult> ValidateOptionArgumentsAsync(CommandLineOption commandOption, string[] arguments)
Expand All @@ -51,6 +53,14 @@ public Task<ValidationResult> ValidateCommandLineOptionsAsync(ICommandLineOption
return ValidationResult.InvalidTask(AzureDevOpsResources.AzureDevOpsReportSeverityRequiresAzureDevOps);
}

return ValidationResult.ValidTask;
if (!commandLineOptions.IsOptionSet(AzureDevOpsCommandLineOptions.PublishAzureDevOpsRunNameOptionName))
{
return ValidationResult.ValidTask;
}

bool isPublishResultsEnabled = commandLineOptions.IsOptionSet(AzureDevOpsCommandLineOptions.PublishAzureDevOpsTestResultsOptionName);
return isPublishResultsEnabled
? ValidationResult.ValidTask
: ValidationResult.InvalidTask(AzureDevOpsResources.PublishAzdoRunNameRequiresPublishAzdoTestResults);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,37 @@ namespace Microsoft.Testing.Extensions;
public static class AzureDevOpsExtensions
{
/// <summary>
/// Adds support to the test application builder.
/// Adds support to the test application builder.
/// </summary>
/// <param name="builder">The test application builder.</param>
public static void AddAzureDevOpsProvider(this ITestApplicationBuilder builder)
{
var compositeTestSessionAzDoService =
new CompositeExtensionFactory<AzureDevOpsReporter>(serviceProvider =>
new CompositeExtensionFactory<AzureDevOpsReporter>(serviceProvider =>
new AzureDevOpsReporter(
serviceProvider.GetCommandLineOptions(),
serviceProvider.GetEnvironment(),
serviceProvider.GetFileSystem(),
serviceProvider.GetOutputDevice(),
serviceProvider.GetLoggerFactory()));

var compositeTestResultsPublisher =
new CompositeExtensionFactory<AzureDevOpsTestResultsPublisher>(serviceProvider =>
new AzureDevOpsTestResultsPublisher(
serviceProvider.GetCommandLineOptions(),
serviceProvider.GetConfiguration(),
serviceProvider.GetEnvironment(),
serviceProvider.GetFileSystem(),
serviceProvider.GetTestApplicationModuleInfo(),
serviceProvider.GetTestApplicationProcessExitCode(),
new AzureDevOpsTestResultsClient(serviceProvider.GetTask(), serviceProvider.GetClock()),
serviceProvider.GetTask(),
serviceProvider.GetClock(),
serviceProvider.GetLoggerFactory()));

builder.TestHost.AddDataConsumer(compositeTestSessionAzDoService);
builder.TestHost.AddDataConsumer(compositeTestResultsPublisher);
builder.TestHost.AddTestSessionLifetimeHandler(compositeTestResultsPublisher);

builder.CommandLine.AddProvider(() => new AzureDevOpsCommandLineProvider());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Text.Json.Serialization;

namespace Microsoft.Testing.Extensions.AzureDevOpsReport;

internal static class AzureDevOpsLivePublishingConstants
{
public const string AbortedTestOutcome = "Aborted";
public const string AbortedTestRunState = "Aborted";
public const string CompletedTestRunState = "Completed";
public const string FailedTestOutcome = "Failed";
public const string InProgressTestRunState = "InProgress";
public const int MaxRunNameLength = 256;
public const string NotExecutedTestOutcome = "NotExecuted";
public const string PassedTestOutcome = "Passed";
}

internal sealed record AzureDevOpsPublishConfiguration(
string CollectionUri,
string Project,
string AccessToken,
int BuildId,
string RunName,
string AutomatedTestStorage,
string ResultsDirectory);

internal sealed record AzureDevOpsTestCaseResult(
[property: JsonPropertyName("automatedTestName")] string AutomatedTestName,
[property: JsonPropertyName("automatedTestStorage")] string AutomatedTestStorage,
[property: JsonPropertyName("testCaseTitle")] string TestCaseTitle,
[property: JsonPropertyName("outcome")] string Outcome,
[property: JsonPropertyName("durationInMs")] long? DurationInMs,
[property: JsonPropertyName("errorMessage")] string? ErrorMessage,
[property: JsonPropertyName("stackTrace")] string? StackTrace,
[property: JsonPropertyName("startedDate")] DateTimeOffset? StartedDate,
[property: JsonPropertyName("completedDate")] DateTimeOffset? CompletedDate);

internal sealed record AzureDevOpsTestResultsPublisherOptions(
int BatchSize,
TimeSpan FlushInterval,
int CoordinationReadRetryCount,
TimeSpan CoordinationReadRetryDelay,
TimeSpan CoordinationFinalizeTimeout,
TimeSpan CoordinationFileExpiration)
{
public AzureDevOpsTestResultsPublisherOptions(int batchSize, TimeSpan flushInterval, int coordinationReadRetryCount, TimeSpan coordinationReadRetryDelay)
: this(batchSize, flushInterval, coordinationReadRetryCount, coordinationReadRetryDelay, TimeSpan.FromSeconds(30), TimeSpan.FromHours(4))
{
}

public static AzureDevOpsTestResultsPublisherOptions Default { get; } = new(100, TimeSpan.FromSeconds(5), 40, TimeSpan.FromMilliseconds(250), TimeSpan.FromSeconds(30), TimeSpan.FromHours(4));
}
Loading
Loading