Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 847
Gkm Avatar asked Aug 20 '19 08:08

Gkm


2 Answers

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.

like image 125
Ruben Bartelink Avatar answered Oct 05 '22 08:10

Ruben Bartelink


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);
}
like image 27
Jeroen Avatar answered Oct 05 '22 07:10

Jeroen