Last active
January 14, 2021 21:57
-
-
Save safern/30135f81c5361c815d7e189e4e40b8ba to your computer and use it in GitHub Desktop.
Custom xunit fact attribute to skip quarantined tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace XunitExtensions | |
{ | |
public class QuarantineDiscoverer : IXunitTestCaseDiscoverer | |
{ | |
public QuarantineDiscoverer(IMessageSink diagnosticMessageSink) | |
{ | |
DiagnosticMessageSink = diagnosticMessageSink; | |
} | |
public IMessageSink DiagnosticMessageSink { get; } | |
public IEnumerable<IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute) | |
{ | |
// Add logic here to get ActiveIssueAttribute and call it's discoverer to see if the conditions apply. | |
return new[] { new QuarantinedTestCase(DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), discoveryOptions.MethodDisplayOptionsOrDefault(), testMethod) }; | |
} | |
} | |
[XunitTestCaseDiscoverer("XunitExtensions.QuarantineDiscoverer", "MyTests")] | |
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] | |
public class CustomFact : FactAttribute | |
{ | |
} | |
public class QuarantinedTestCase : XunitTestCase | |
{ | |
[Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes", error: true)] | |
public QuarantinedTestCase() { } | |
public QuarantinedTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, TestMethodDisplayOptions defaultMethodDisplayOptions, ITestMethod testMethod, object[] testMethodArguments = null) | |
: base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod, testMethodArguments) { } | |
public override async Task<RunSummary> RunAsync(IMessageSink diagnosticMessageSink, | |
IMessageBus messageBus, | |
object[] constructorArguments, | |
ExceptionAggregator aggregator, | |
CancellationTokenSource cancellationTokenSource) | |
{ | |
QuarantinedTestMessageBus skipMessageBus = new QuarantinedTestMessageBus(messageBus); | |
var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource); | |
if (skipMessageBus.SkippedTestCount > 0) | |
{ | |
result.Failed -= skipMessageBus.SkippedTestCount; | |
result.Skipped += skipMessageBus.SkippedTestCount; | |
} | |
return result; | |
} | |
} | |
public class QuarantinedTestMessageBus : IMessageBus | |
{ | |
readonly IMessageBus innerBus; | |
public QuarantinedTestMessageBus(IMessageBus innerBus) | |
{ | |
this.innerBus = innerBus; | |
} | |
public int SkippedTestCount { get; private set; } | |
public void Dispose() { } | |
public bool QueueMessage(IMessageSinkMessage message) | |
{ | |
var testFailed = message as ITestFailed; | |
if (testFailed != null) | |
{ | |
XunitTest test = new XunitTest(testFailed.TestCase as IXunitTestCase, $"[Quarantined] {testFailed.Test.DisplayName}"); | |
SkippedTestCount++; | |
return innerBus.QueueMessage(new TestSkipped(test, testFailed.Messages.FirstOrDefault())); | |
} | |
// Nothing we care about, send it on its way | |
return innerBus.QueueMessage(message); | |
} | |
} | |
} | |
namespace MyTests | |
{ | |
public class TestClass1 | |
{ | |
[CustomFact] | |
public void SantiCustomTest() | |
{ | |
Assert.False(true); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment