Skip to content

Commit dcfb54a

Browse files
Copilotthomhurst
andcommitted
Implement @thomhurst's simpler exception-based approach for dependency handling
Co-authored-by: thomhurst <[email protected]>
1 parent c906c28 commit dcfb54a

File tree

2 files changed

+44
-16
lines changed

2 files changed

+44
-16
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace TUnit.Core.Exceptions;
2+
3+
/// <summary>
4+
/// Exception thrown when a test dependency has failed and the test cannot proceed
5+
/// </summary>
6+
public class TestDependencyException : TUnitException
7+
{
8+
/// <summary>
9+
/// Name of the dependency that failed
10+
/// </summary>
11+
public string DependencyName { get; }
12+
13+
/// <summary>
14+
/// Whether the test should proceed despite the dependency failure
15+
/// </summary>
16+
public bool ProceedOnFailure { get; }
17+
18+
public TestDependencyException(string dependencyName, bool proceedOnFailure)
19+
: base($"Dependency failed: {dependencyName}")
20+
{
21+
DependencyName = dependencyName;
22+
ProceedOnFailure = proceedOnFailure;
23+
}
24+
}

TUnit.Engine/Services/SingleTestExecutor.cs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Microsoft.Testing.Platform.TestHost;
33
using TUnit.Core;
44
using TUnit.Core.Data;
5+
using TUnit.Core.Exceptions;
56
using TUnit.Core.Logging;
67
using TUnit.Core.ReferenceTracking;
78
using TUnit.Core.Tracking;
@@ -84,12 +85,8 @@ await PropertyInjector.InjectPropertiesAsync(
8485
return await HandleSkippedTestAsync(test, cancellationToken);
8586
}
8687

87-
// Check for failed dependencies and skip test if needed
88-
await CheckDependenciesAndSetSkipReasonIfNeeded(test);
89-
if (!string.IsNullOrEmpty(test.Context.SkipReason))
90-
{
91-
return await HandleSkippedTestAsync(test, cancellationToken);
92-
}
88+
// Check for failed dependencies and throw exception if test should be skipped
89+
CheckDependenciesAndThrowIfShouldSkip(test);
9390

9491
if(test.Context is { RetryFunc: not null, TestDetails.RetryLimit: > 0 })
9592
{
@@ -101,6 +98,11 @@ await PropertyInjector.InjectPropertiesAsync(
10198
await ExecuteTestWithHooksAsync(test, instance, cancellationToken);
10299
}
103100
}
101+
catch (TestDependencyException e)
102+
{
103+
test.Context.SkipReason = e.Message;
104+
return await HandleSkippedTestAsync(test, cancellationToken);
105+
}
104106
catch (Exception ex)
105107
{
106108
HandleTestFailure(test, ex);
@@ -401,14 +403,14 @@ private static void RestoreHookContexts(TestContext context)
401403
}
402404
}
403405

404-
private async Task CheckDependenciesAndSetSkipReasonIfNeeded(AbstractExecutableTest test)
406+
private void CheckDependenciesAndThrowIfShouldSkip(AbstractExecutableTest test)
405407
{
406408
if (test.Dependencies.Length == 0)
407409
{
408410
return; // No dependencies to check
409411
}
410412

411-
var failedDependencies = new List<string>();
413+
var failedDependenciesNotAllowingProceed = new List<string>();
412414

413415
foreach (var dependency in test.Dependencies)
414416
{
@@ -419,21 +421,23 @@ private async Task CheckDependenciesAndSetSkipReasonIfNeeded(AbstractExecutableT
419421
var dependencyMetadata = test.Metadata.Dependencies.FirstOrDefault(d =>
420422
DependencyMatches(d, dependency));
421423

422-
// If no matching metadata found or ProceedOnFailure is false, skip the test
423-
if (dependencyMetadata == null || dependencyMetadata.ProceedOnFailure == false)
424+
// Get ProceedOnFailure setting (default to false if no metadata found)
425+
var proceedOnFailure = dependencyMetadata?.ProceedOnFailure ?? false;
426+
427+
// If this dependency doesn't allow proceeding on failure, add it to the list
428+
if (!proceedOnFailure)
424429
{
425-
// Add to failed dependencies list for skip reason
426430
var dependencyName = GetDependencyDisplayName(dependency);
427-
failedDependencies.Add(dependencyName);
431+
failedDependenciesNotAllowingProceed.Add(dependencyName);
428432
}
429433
}
430434
}
431435

432-
if (failedDependencies.Count > 0)
436+
// Only throw if there are dependencies that don't allow proceeding
437+
if (failedDependenciesNotAllowingProceed.Count > 0)
433438
{
434-
var dependencyNames = string.Join(", ", failedDependencies);
435-
test.Context.SkipReason = $"Dependency failed: {dependencyNames}";
436-
await _logger.LogInformationAsync($"Skipping test '{test.Context.TestDetails.TestName}' due to failed dependencies: {dependencyNames}");
439+
var dependencyNames = string.Join(", ", failedDependenciesNotAllowingProceed);
440+
throw new TestDependencyException(dependencyNames, false);
437441
}
438442
}
439443

0 commit comments

Comments
 (0)