NUnitTestFixtureBuilder
NUnitTestFixtureBuilder is able to build a fixture given
            a class marked with a TestFixtureAttribute or an unmarked
            class containing test methods. In the first case, it is
            called by the attribute and in the second directly by
            NUnitSuiteBuilder.
            
                using NUnit.Framework.Interfaces;
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NUnit.Framework.Internal.Builders
{
    [System.Runtime.CompilerServices.NullableContext(1)]
    [System.Runtime.CompilerServices.Nullable(0)]
    public class NUnitTestFixtureBuilder
    {
        private const string NO_TYPE_ARGS_MSG = "Fixture type contains generic parameters. You must either provide Type arguments or specify constructor arguments that allow NUnit to deduce the Type arguments.";
        private const string PARALLEL_NOT_ALLOWED_MSG = "ParallelizableAttribute is only allowed on test methods and fixtures";
        private readonly ITestCaseBuilder _testBuilder = new DefaultTestCaseBuilder();
        public TestSuite BuildFrom(ITypeInfo typeInfo, IPreFilter filter)
        {
            TestFixture testFixture = new TestFixture(typeInfo, (object[])null);
            if (testFixture.RunState != 0)
                CheckTestFixtureIsValid(testFixture);
            testFixture.ApplyAttributesToTest(typeInfo.Type.Assembly.GetAttributes<FixtureLifeCycleAttribute>());
            testFixture.ApplyAttributesToTest(typeInfo.Type);
            AddTestCasesToFixture(testFixture, filter);
            return testFixture;
        }
        public TestSuite BuildFrom(ITypeInfo typeInfo, IPreFilter filter, ITestFixtureData testFixtureData)
        {
            Guard.ArgumentNotNull(testFixtureData, "testFixtureData");
            object[] array = testFixtureData.Arguments;
            if (typeInfo.ContainsGenericParameters) {
                Type[] typeArgsOut = testFixtureData.TypeArgs;
                if (typeArgsOut == null || typeArgsOut.Length == 0) {
                    int num = 0;
                    object[] array2 = array;
                    foreach (object obj in array2) {
                        if (!(obj is Type))
                            break;
                        num++;
                    }
                    typeArgsOut = new Type[num];
                    for (int j = 0; j < num; j++) {
                        typeArgsOut[j] = (Type)array[j];
                    }
                    if (num > 0) {
                        object[] array3 = new object[array.Length - num];
                        for (int k = 0; k < array3.Length; k++) {
                            array3[k] = array[num + k];
                        }
                        array = array3;
                    }
                }
                if (typeArgsOut.Length != 0 || TypeHelper.CanDeduceTypeArgsFromArgs(typeInfo.Type, array, ref typeArgsOut))
                    typeInfo = typeInfo.MakeGenericType(typeArgsOut);
            }
            TestFixture testFixture = new TestFixture(typeInfo, array);
            string name = testFixture.Name;
            if (testFixtureData.TestName != null)
                testFixture.Name = testFixtureData.TestName;
            else {
                string[] array4 = (testFixtureData as TestParameters)?.ArgDisplayNames;
                if (array4 != null) {
                    testFixture.Name = typeInfo.GetDisplayName();
                    if (array4.Length != 0) {
                        TestFixture testFixture2 = testFixture;
                        testFixture2.Name = testFixture2.Name + "(" + string.Join(", ", array4) + ")";
                    }
                } else if (array != null && array.Length != 0) {
                    testFixture.Name = typeInfo.GetDisplayName(array);
                }
            }
            if (testFixture.Name != name) {
                string namespace = typeInfo.Namespace;
                testFixture.FullName = ((!string.IsNullOrEmpty(namespace)) ? (namespace + "." + testFixture.Name) : testFixture.Name);
            }
            if (testFixture.RunState != 0)
                testFixture.RunState = testFixtureData.RunState;
            foreach (string key in testFixtureData.Properties.Keys) {
                foreach (object item in testFixtureData.Properties[key]) {
                    testFixture.Properties.Add(key, item);
                }
            }
            if (testFixture.RunState != 0)
                CheckTestFixtureIsValid(testFixture);
            AddTestCasesToFixture(testFixture, filter);
            return testFixture;
        }
        private void AddTestCasesToFixture(TestFixture fixture, IPreFilter filter)
        {
            if (fixture.TypeInfo.ContainsGenericParameters)
                fixture.MakeInvalid("Fixture type contains generic parameters. You must either provide Type arguments or specify constructor arguments that allow NUnit to deduce the Type arguments.");
            else {
                IMethodInfo[] methods = fixture.TypeInfo.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                IMethodInfo[] array = methods;
                foreach (IMethodInfo methodInfo in array) {
                    if (filter.IsMatch(fixture.TypeInfo.Type, methodInfo.MethodInfo)) {
                        Test test = BuildTestCase(methodInfo, fixture);
                        if (test != null)
                            fixture.Add(test);
                        else if (methodInfo.MethodInfo.HasAttribute<ParallelizableAttribute>(false)) {
                            fixture.MakeInvalid("ParallelizableAttribute is only allowed on test methods and fixtures");
                        }
                    }
                }
            }
        }
        [return: System.Runtime.CompilerServices.Nullable(2)]
        private Test BuildTestCase(IMethodInfo method, TestSuite suite)
        {
            if (!_testBuilder.CanBuildFrom(method, suite))
                return null;
            return _testBuilder.BuildFrom(method, suite);
        }
        private static void CheckTestFixtureIsValid(TestFixture fixture)
        {
            if (fixture.TypeInfo.ContainsGenericParameters)
                fixture.MakeInvalid("Fixture type contains generic parameters. You must either provide Type arguments or specify constructor arguments that allow NUnit to deduce the Type arguments.");
            else if (!fixture.TypeInfo.IsStaticClass) {
                Type[] typeArray = Reflect.GetTypeArray(fixture.Arguments);
                if (!Reflect.GetConstructors(fixture.TypeInfo.Type, typeArray).Any())
                    fixture.MakeInvalid("No suitable constructor was found");
            }
        }
    }
}