File: XUnit\ConditionalTheoryDiscoverer.cs
Web Access
Project: src\test\TestUtilities\TestUtilities.csproj (Microsoft.TestUtilities)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
// Borrowed from https://github.com/dotnet/aspnetcore/blob/95ed45c67/src/Testing/src/xunit/
 
using System.Collections.Generic;
using Xunit.Abstractions;
using Xunit.Sdk;
 
// Do not change this namespace without changing the usage in ConditionalTheoryAttribute
namespace Microsoft.TestUtilities;
 
internal sealed class ConditionalTheoryDiscoverer : TheoryDiscoverer
{
    public ConditionalTheoryDiscoverer(IMessageSink diagnosticMessageSink)
        : base(diagnosticMessageSink)
    {
    }
 
    private sealed class OptionsWithPreEnumerationEnabled : ITestFrameworkDiscoveryOptions
    {
        private const string PreEnumerateTheories = "xunit.discovery.PreEnumerateTheories";
 
        private readonly ITestFrameworkDiscoveryOptions _original;
 
        public OptionsWithPreEnumerationEnabled(ITestFrameworkDiscoveryOptions original)
        {
            _original = original;
        }
 
        public TValue GetValue<TValue>(string name)
            => (name == PreEnumerateTheories) ? (TValue)(object)true : _original.GetValue<TValue>(name);
 
        public void SetValue<TValue>(string name, TValue value)
            => _original.SetValue(name, value);
    }
 
    public override IEnumerable<IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo theoryAttribute)
        => base.Discover(new OptionsWithPreEnumerationEnabled(discoveryOptions), testMethod, theoryAttribute);
 
    protected override IEnumerable<IXunitTestCase> CreateTestCasesForTheory(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo theoryAttribute)
    {
        var skipReason = testMethod.EvaluateSkipConditions();
        return skipReason != null
           ? new[] { new SkippedTestCase(skipReason, DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), TestMethodDisplayOptions.None, testMethod) }
           : base.CreateTestCasesForTheory(discoveryOptions, testMethod, theoryAttribute);
    }
 
    protected override IEnumerable<IXunitTestCase> CreateTestCasesForDataRow(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo theoryAttribute, object[]? dataRow)
    {
        var skipReason = testMethod.EvaluateSkipConditions();
        if (skipReason == null && dataRow?.Length > 0)
        {
            var obj = dataRow[0];
            if (obj != null)
            {
                var type = obj.GetType();
                var property = type.GetProperty("Skip");
                if (property != null && property.PropertyType.Equals(typeof(string)))
                {
                    skipReason = property.GetValue(obj) as string;
                }
            }
        }
 
        return skipReason != null ?
            base.CreateTestCasesForSkippedDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow, skipReason)
            : base.CreateTestCasesForDataRow(discoveryOptions, testMethod, theoryAttribute, dataRow);
    }
 
    protected override IEnumerable<IXunitTestCase> CreateTestCasesForSkippedDataRow(
        ITestFrameworkDiscoveryOptions discoveryOptions,
        ITestMethod testMethod,
        IAttributeInfo theoryAttribute,
        object[] dataRow,
        string skipReason)
    {
        return new[]
        {
            new WORKAROUND_SkippedDataRowTestCase(DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), discoveryOptions.MethodDisplayOptionsOrDefault(), testMethod, skipReason, dataRow),
        };
    }
}