How to skip a test case which has Theory attribute not Fact
Asked Answered
M

2

12

How to skip a data driven test case for some reason?

I can skip a test case with Fact but getting an exception when using skip for parametrized test cases.
Exception: Xunit.SkipException: 'Exception of type 'Xunit.SkipException' was thrown.'

[Theory, OwnData(@"Data\own.json"), Category("Own")]
        public void Transfer(OwnDataTestConfig own)
        {
            bool? result = null;
            Skip.IfNot(own.FeatureConfig.SameCurrencyOnly);
result = Own.VerifyTransfer(_basicActions, WebDriver, own);;
            Assert.True(result.Value);
        }

Test case should be skipped if own.FeatureConfig.SameCurrencyOnly is false.

Multiangular answered 20/8, 2019 at 8:56 Comment(1)
[Theory(Skip = "reason why do you skip")]Knockabout
O
16

xUnit does not process SkipException as such.

The way you do that is via a Fact(Skip="Reason").

[Theory] also has a Skip property which works similarly.

Throwing from even one case in a Theory aborts the processing.

So I'd suggest you use an if (bad) return; to skip the processing.

Ootid answered 20/8, 2019 at 17:33 Comment(0)
S
3

Skipping test cases (be it facts or cases from a theory) dynamically, based on a run-time choice, can be done by extending xUnit's features.

I recommend adapting the DynamicSkipExample from xunit.samples (licensed Apache 2.0, copyrighted by their respective authors), which includes this sample usage:

[SkippableTheory]
[InlineData(null)]
[InlineData("Hello, world!")]
public void DynamicallySkipped(string value)
{
    if (value == null)
        throw new SkipTestException("I don't like to run against null data.");

    Assert.StartsWith("foo", value);
}

So basically, in usage, you can dynamically throw a specific exception that leads to Skipped test cases instead of failed ones.

The code can be found in linked repository under its own license. It wires things together with an IXunitTestCaseDiscoverer but the interesting bit are in the TestCase (one for Fact and one for Theory):

public override async Task<RunSummary> RunAsync(IMessageSink diagnosticMessageSink,
                                                IMessageBus messageBus,
                                                object[] constructorArguments,
                                                ExceptionAggregator aggregator,
                                                CancellationTokenSource cancellationTokenSource)
{
    // Duplicated code from SkippableFactTestCase. I'm sure we could find a way to de-dup with some thought.
    var skipMessageBus = new SkippableFactMessageBus(messageBus);
    var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource);
    if (skipMessageBus.DynamicallySkippedTestCount > 0)
    {
        result.Failed -= skipMessageBus.DynamicallySkippedTestCount;
        result.Skipped += skipMessageBus.DynamicallySkippedTestCount;
    }

    return result;
}

And its associated IMessageBus:

public bool QueueMessage(IMessageSinkMessage message)
{
    var testFailed = message as ITestFailed;
    if (testFailed != null)
    {
        var exceptionType = testFailed.ExceptionTypes.FirstOrDefault();
        if (exceptionType == typeof(SkipTestException).FullName)
        {
            DynamicallySkippedTestCount++;
            return innerBus.QueueMessage(new TestSkipped(testFailed.Test, testFailed.Messages.FirstOrDefault()));
        }
    }

    // Nothing we care about, send it on its way
    return innerBus.QueueMessage(message);
}
Sirocco answered 26/8, 2019 at 19:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.