Skip to content

Refactor TestRecord class and add interop features for test execution context - #2250

Merged
david-driscoll merged 1 commit into
mainfrom
feature/test-context-wrapping
Jun 28, 2026
Merged

Refactor TestRecord class and add interop features for test execution context#2250
david-driscoll merged 1 commit into
mainfrom
feature/test-context-wrapping

Conversation

@david-driscoll

Copy link
Copy Markdown
Member

No description provided.

@github-actions github-actions Bot added this to the v10.0.5 milestone Jun 28, 2026
@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 18 critical · 3 medium · 4 minor

Alerts:
⚠ 25 issues (≤ 0 issues of at least minor severity)

Results:
25 new issues

Category Results
Compatibility 1 medium
UnusedCode 1 minor
BestPractice 2 medium
ErrorProne 18 critical
CodeStyle 3 minor

View in Codacy

🟢 Metrics -4 complexity · 0 duplication

Metric Results
Complexity -4
Duplication 0

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@github-actions

Copy link
Copy Markdown

Test Results

0 tests  ±0   0 ✅ ±0   0s ⏱️ ±0s
0 suites ±0   0 💤 ±0 
0 files   ±0   0 ❌ ±0 

Results for commit 9af1bd7. ± Comparison against base commit 5640e0d.

@codecov

codecov Bot commented Jun 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 58.25%. Comparing base (5640e0d) to head (9af1bd7).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##           main    #2250       +/-   ##
=========================================
+ Coverage      0   58.25%   +58.25%     
=========================================
  Files         0       52       +52     
  Lines         0     3368     +3368     
  Branches      0      221      +221     
=========================================
+ Hits          0     1962     +1962     
- Misses        0     1339     +1339     
- Partials      0       67       +67     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codacy-production codacy-production Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the TestRecord class to use automatic TUnit context resolution and introduces interop delegation features for both TUnit and XUnit3. However, the Codacy analysis indicates the PR is not up to standards due to 25 new issues and a lack of required test coverage.

A critical risk exists in the Scriban template used for XUnit3 delegation: property and indexer setters are currently empty, which will lead to silent failures when writing to delegated members. Additionally, TestRecord lacks safe initialization for TestContext.Current, potentially causing NullReferenceExceptions if accessed outside a test lifecycle. There are also significant documentation copy-paste errors throughout the TUnit implementation referring to 'xUnit'.

About this PR

  • The source generation templates for XUnit3 delegation do not support writable properties or indexers. Any attempt to set values on these members will fail silently at runtime.
  • The PR description is empty. Please provide context regarding the new interop features and why the TestRecord refactoring was necessary.

Test suggestions

  • Verify TestRecord correctly proxies TUnit execution properties (Phase, Result, etc.)
  • Verify TestRecord correctly proxies TUnit output methods (WriteLine, AttachArtifact)
  • Verify TestRecord Isolation methods return correctly formatted unique names
  • Verify XUnitTestContext source-generated members correctly delegate calls to the underlying ITestContext
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Verify TestRecord correctly proxies TUnit execution properties (Phase, Result, etc.)
2. Verify TestRecord correctly proxies TUnit output methods (WriteLine, AttachArtifact)
3. Verify TestRecord Isolation methods return correctly formatted unique names
4. Verify XUnitTestContext source-generated members correctly delegate calls to the underlying ITestContext

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment on lines +49 to +50
set
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

The indexer setter implementation is empty. Any attempt to set a value via an indexer on the generated classes will be silently ignored. This should delegate to the underlying reference.

}
{{~end~}}
{{~if property.have_setter~}}
set

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

The property setter implementation is empty and ignores the 'value' parameter. It should delegate the assignment to the underlying reference to prevent silent failures when setting properties on the context.

/// This property is typically used to retrieve contextual information or perform
/// test-specific logging operations.
/// </remarks>
public TestContext TestContext { get; } = TestContext.Current!;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 HIGH RISK

The TestContext property relies on TestContext.Current, which may be null if accessed outside of a TUnit test execution. Explicitly checking for null and throwing a clear exception is recommended to avoid confusing NullReferenceExceptions.

Suggested change
public TestContext TestContext { get; } = TestContext.Current!;
public TestContext TestContext { get; } = TestContext.Current ?? throw new InvalidOperationException("TUnit TestContext is not available in the current execution context.");

/// var dotPrefix = TestContext.Current!.Isolation.GetIsolatedPrefix("."); // Returns "test.42."
/// </code>
/// </example>
public string GetIsolatedPrefix(string separator = "_") => ( (ITestIsolation)TestContext ).GetIsolatedPrefix(separator);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

Optional parameters in public APIs can cause versioning issues. Replacing 'GetIsolatedPrefix' and 'AttachArtifact' optional parameters with method overloads ensures the default values are centralized in the library.

/// </summary>
/// <param name="key">The key of the value to get or set.</param>
/// <returns>The value associated with the specified key.</returns>
public object? this[string key] => ( (ITestStateBag)TestContext )[key];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ LOW RISK

Suggestion: The indexer is missing a setter. Add a setter to maintain parity with the underlying ITestStateBag implementation, allowing users to use indexer assignment syntax.

@@ -0,0 +1,411 @@
using TUnit.Core.Enums;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ LOW RISK

Suggestion: Specify CLS compliance for the assembly to ensure interoperability with other .NET languages like F# or VB.NET.

Suggested change
using TUnit.Core.Enums;
[assembly: System.CLSCompliant(true)]
using TUnit.Core.Enums;

Comment on lines 10 to +22
/// The xunit test context
/// </remarks>
/// <param name="context"></param>
/// <param name="logEventLevel"></param>
/// <param name="outputTemplate"></param>
/// <param name="configureLogger"></param>
[PublicAPI]
public abstract class TUnitTestRecord<TContext>(
TestContext context,
LogEventLevel logEventLevel = LogEventLevel.Verbose,
string? outputTemplate = null,
Action<TContext, LoggerConfiguration>? configureLogger = null
) : RocketSurgeryTestContext<TContext>(
configureLogger,
logEventLevel,
outputTemplate
)
where TContext : RocketSurgeryTestContext<TContext>, ILoggingTestContext
public abstract partial class TestRecord<TContext>
(LogEventLevel logEventLevel = LogEventLevel.Verbose, string? outputTemplate = null, Action<TContext, LoggerConfiguration>? configureLogger = null)
: RocketSurgeryTestContext<TContext>(configureLogger, logEventLevel, outputTemplate)
where TContext : RocketSurgeryTestContext<TContext>
{
private readonly TestContext _context = context;
/// <summary>
/// Represents the current test context for xUnit tests.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ LOW RISK

Nitpick: The documentation here refers to 'xunit test context', but this class is part of the TUnit implementation. Update all XML summaries and remarks to correctly reflect TUnit.

@david-driscoll
david-driscoll merged commit ae42d6d into main Jun 28, 2026
9 of 10 checks passed
@david-driscoll
david-driscoll deleted the feature/test-context-wrapping branch June 28, 2026 23:50
@github-actions github-actions Bot added the ✨ mysterious We forgot to label this label Jun 28, 2026
@github-actions github-actions Bot modified the milestones: v10.0.5, v10.0.6, v10.0.7 Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ mysterious We forgot to label this

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant