Refactor TestRecord class and add interop features for test execution context - #2250
Conversation
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Compatibility | 1 medium |
| UnusedCode | 1 minor |
| BestPractice | 2 medium |
| ErrorProne | 18 critical |
| CodeStyle | 3 minor |
🟢 Metrics -4 complexity · 0 duplication
Metric Results Complexity -4 Duplication 0
AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.
TIP This summary will be updated as you push new changes.
Codecov Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
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
| set | ||
| { |
There was a problem hiding this comment.
🔴 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 |
There was a problem hiding this comment.
🔴 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!; |
There was a problem hiding this comment.
🔴 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.
| 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); |
There was a problem hiding this comment.
🟡 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]; |
There was a problem hiding this comment.
⚪ 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; | |||
There was a problem hiding this comment.
⚪ LOW RISK
Suggestion: Specify CLS compliance for the assembly to ensure interoperability with other .NET languages like F# or VB.NET.
| using TUnit.Core.Enums; | |
| [assembly: System.CLSCompliant(true)] | |
| using TUnit.Core.Enums; |
| /// 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. |
There was a problem hiding this comment.
⚪ 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.
No description provided.