Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace TUnit.Core;

// Constants-only partial, source-linked into TUnit.Reporting.Tool (the linked
// HtmlReportGenerator reads the property key back out of report sidecars). Keeping the
// key here — away from the attribute's behaviour and its base types — lets the tool
// compile just this file, so the engine and the tool can never disagree on the value.
public sealed partial class ClassTimelineAttribute
{
/// <summary>
/// Custom-property key used to round-trip the chosen <see cref="TUnit.Core.Enums.TimelineMode"/> into
/// <c>TestDetails.CustomProperties</c> so the HTML reporter can read it back per class.
/// </summary>
internal const string ClassTimelinePropertyKey = "tunit.report.timeline";
}
7 changes: 1 addition & 6 deletions TUnit.Core/Attributes/TestMetadata/ClassTimelineAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace TUnit.Core;
/// </code>
/// </example>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly)]
public sealed class ClassTimelineAttribute(TimelineMode mode) : TUnitAttribute, ITestDiscoveryEventReceiver, IScopedAttribute
public sealed partial class ClassTimelineAttribute(TimelineMode mode) : TUnitAttribute, ITestDiscoveryEventReceiver, IScopedAttribute
{
/// <summary>The timeline rendering mode to apply.</summary>
public TimelineMode Mode { get; } = mode;
Expand All @@ -47,9 +47,4 @@ public ValueTask OnTestDiscovered(DiscoveredTestContext context)
return default;
}

/// <summary>
/// Custom-property key used to round-trip the chosen <see cref="TimelineMode"/> into
/// <c>TestDetails.CustomProperties</c> so the HTML reporter can read it back per class.
/// </summary>
internal const string ClassTimelinePropertyKey = "tunit.report.timeline";
}
4 changes: 3 additions & 1 deletion TUnit.Core/SpanData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace TUnit.Core;

internal sealed class SpanData
// A record so report merging can rewrite single properties via `with` without a
// hand-maintained copy that silently drops newly added members.
internal sealed record SpanData
{
[JsonPropertyName("traceId")]
public required string TraceId { get; init; }
Expand Down
22 changes: 22 additions & 0 deletions TUnit.Core/TUnitActivitySource.ReportConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#if NET

namespace TUnit.Core;

// Span/tag constants consumed by the HTML report pipeline (HtmlReportGenerator). They live
// in this constants-only partial so TUnit.Reporting.Tool can source-link exactly these
// values without dragging in the ActivitySource statics — which also makes value drift
// between the engine and the tool impossible. Keep this file free of anything but consts.
public static partial class TUnitActivitySource
{
// Span names used across the engine and HTML report.
internal const string SpanTestSession = "test session";
internal const string SpanTestAssembly = "test assembly";
internal const string SpanTestSuite = "test suite";
internal const string SpanTestCase = "test case";
internal const string SpanTestBody = "test body";

internal const string TagTestClass = "tunit.test.class";
internal const string TagTraceScope = "tunit.trace.scope";
}

#endif
12 changes: 3 additions & 9 deletions TUnit.Core/TUnitActivitySource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace TUnit.Core;

public static class TUnitActivitySource
public static partial class TUnitActivitySource
{
private static readonly string Version =
typeof(TUnitActivitySource).Assembly.GetName().Version?.ToString() ?? "0.0.0";
Expand All @@ -28,12 +28,8 @@ public static class TUnitActivitySource
internal static readonly ActivitySource Source = new(SourceName, Version);
internal static readonly ActivitySource LifecycleSource = new(LifecycleSourceName, Version);

// Span names used across the engine and HTML report.
internal const string SpanTestSession = "test session";
internal const string SpanTestAssembly = "test assembly";
internal const string SpanTestSuite = "test suite";
internal const string SpanTestCase = "test case";
internal const string SpanTestBody = "test body";
// Span names live in TUnitActivitySource.ReportConstants.cs — a constants-only partial
// that TUnit.Reporting.Tool source-links (see that file's header before moving members).

// Tag and baggage keys used across init/dispose spans, HTML report, and cross-boundary correlation.

Expand All @@ -45,7 +41,6 @@ public static class TUnitActivitySource
public const string TagTestId = "tunit.test.id";
internal const string TagSessionId = "tunit.session.id";
internal const string TagTestFilter = "tunit.filter";
internal const string TagTestClass = "tunit.test.class";
internal const string TagTestMethod = "tunit.test.method";
internal const string TagTestNodeUid = "tunit.test.node_uid";
internal const string TagTestCategories = "tunit.test.categories";
Expand All @@ -57,7 +52,6 @@ public static class TUnitActivitySource
internal const string TagTestCaseResultStatus = "test.case.result.status";
internal const string TagTestRetryAttempt = "tunit.test.retry_attempt";
internal const string TagTestSkipReason = "tunit.test.skip_reason";
internal const string TagTraceScope = "tunit.trace.scope";

/// <summary>
/// Returns a human-readable type name suitable for span labels.
Expand Down
16 changes: 16 additions & 0 deletions TUnit.Engine/Configuration/EnvironmentConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ internal static class EnvironmentConstants
// TUnit-specific: how long (in days) the auto-uploaded HTML report artifact is kept
public const string ArtifactRetentionDays = "TUNIT_ARTIFACT_RETENTION_DAYS";

// TUnit-specific: cross-process report aggregation (issue #4522).
// ON by default wherever a shared directory is resolvable (GitHub Actions, or explicit
// TUNIT_AGGREGATE_DIR). Values: off/false/0/no/disabled/none = disable;
// defer = persist sidecars + merged HTML only (final summary via `tunit-report merge`);
// anything else (or unset) = cooperative merge.
public const string AggregateReports = "TUNIT_AGGREGATE_REPORTS";
// Shared directory for sidecars/merged outputs; auto-derived on GitHub Actions when unset.
public const string AggregateDirectory = "TUNIT_AGGREGATE_DIR";
// Opts out of the machine-readable JSON sidecar written next to the HTML report.
public const string DisableJsonReport = "TUNIT_DISABLE_JSON_REPORT";

// TUnit-specific: Execution
public const string ExecutionMode = "TUNIT_EXECUTION_MODE";
public const string MaxParallelTests = "TUNIT_MAX_PARALLEL_TESTS";
Expand Down Expand Up @@ -44,6 +55,11 @@ internal static class EnvironmentConstants
// Used to clamp TUNIT_ARTIFACT_RETENTION_DAYS so the API does not reject the request.
public const string GitHubRetentionDays = "GITHUB_RETENTION_DAYS";

// GitHub Actions context (for report aggregation scoping)
public const string RunnerTemp = "RUNNER_TEMP";
public const string GitHubRunAttempt = "GITHUB_RUN_ATTEMPT";
public const string GitHubJob = "GITHUB_JOB";

// GitHub Actions context (for CI metadata in reports)
public const string GitHubSha = "GITHUB_SHA";
public const string GitHubRef = "GITHUB_REF";
Expand Down
Loading
Loading