示例#1
0
        public ScenarioInfo(IMethodInfo testMethod, object[] dataRow, string scenarioOutlineDisplayName)
        {
            var parameters     = testMethod.GetParameters().ToList();
            var typeParameters = testMethod.GetGenericArguments().ToList();

            ITypeInfo[] typeArguments;
            if (testMethod.IsGenericMethodDefinition)
            {
                typeArguments = typeParameters
                                .Select(typeParameter => InferTypeArgument(typeParameter.Name, parameters, dataRow))
                                .ToArray();

                this.MethodToRun = testMethod.MakeGenericMethod(typeArguments).ToRuntimeMethod();
            }
            else
            {
                typeArguments    = new ITypeInfo[0];
                this.MethodToRun = testMethod.ToRuntimeMethod();
            }

            var passedArguments = Reflector.ConvertArguments(
                dataRow, this.MethodToRun.GetParameters().Select(p => p.ParameterType).ToArray());

            var generatedArguments = GetGeneratedArguments(
                typeParameters, typeArguments, parameters, passedArguments.Length);

            var arguments = passedArguments
                            .Select(value => new Argument(value))
                            .Concat(generatedArguments)
                            .ToList();

            this.ScenarioDisplayName = GetScenarioDisplayName(scenarioOutlineDisplayName, typeArguments, parameters, arguments);
            this.ConvertedDataRow    = arguments.Select(argument => argument.Value).ToList();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="XunitTestCaseRunner"/> class.
        /// </summary>
        /// <param name="testCase">The test case to be run.</param>
        /// <param name="displayName">The display name of the test case.</param>
        /// <param name="skipReason">The skip reason, if the test is to be skipped.</param>
        /// <param name="constructorArguments">The arguments to be passed to the test class constructor.</param>
        /// <param name="testMethodArguments">The arguments to be passed to the test method.</param>
        /// <param name="messageBus">The message bus to report run status to.</param>
        /// <param name="aggregator">The exception aggregator used to run code and collect exceptions.</param>
        /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param>
        public XunitTestCaseRunner(
            IXunitTestCase testCase,
            string displayName,
            string?skipReason,
            object?[] constructorArguments,
            object?[]?testMethodArguments,
            IMessageBus messageBus,
            ExceptionAggregator aggregator,
            CancellationTokenSource cancellationTokenSource)
            : base(testCase, messageBus, aggregator, cancellationTokenSource)
        {
            this.displayName          = Guard.ArgumentNotNull(nameof(displayName), displayName);
            this.constructorArguments = Guard.ArgumentNotNull(nameof(constructorArguments), constructorArguments);

            SkipReason = skipReason;

            testClass  = TestCase.TestMethod.TestClass.Class.ToRuntimeType() ?? throw new ArgumentException("testCase.TestMethod.TestClass.Class does not map to a Type object", nameof(testCase));
            testMethod = TestCase.Method.ToRuntimeMethod() ?? throw new ArgumentException("testCase.TestMethod does not map to a MethodInfo object", nameof(testCase));

            var parameters     = TestMethod.GetParameters();
            var parameterTypes = new Type[parameters.Length];

            for (var i = 0; i < parameters.Length; i++)
            {
                parameterTypes[i] = parameters[i].ParameterType;
            }

            TestMethodArguments = Reflector.ConvertArguments(testMethodArguments, parameterTypes);
        }
示例#3
0
        public void ConvertsStringToGuid(string text)
        {
            var guid = Guid.Parse(text);

            var args = Reflector.ConvertArguments(new object[] { text }, new[] { typeof(Guid) });

            Assert.Equal(guid, Assert.IsType <Guid>(args[0]));
        }
示例#4
0
        public void ConvertsStringToDateTimeOffset(string text)
        {
            var dateTimeOffset = DateTimeOffset.Parse(text, CultureInfo.InvariantCulture);

            var args = Reflector.ConvertArguments(new object[] { text }, new[] { typeof(DateTimeOffset) });

            Assert.Equal(dateTimeOffset, Assert.IsType <DateTimeOffset>(args[0]));
        }
示例#5
0
        static string[] GetCultures(IAttributeInfo culturedTheoryAttribute)
        {
            var ctorArgs = culturedTheoryAttribute.GetConstructorArguments().ToArray();
            var cultures = Reflector.ConvertArguments(ctorArgs, new[] { typeof(string[]) }).Cast <string[]>().Single();

            if (cultures == null || cultures.Length == 0)
            {
                cultures = new[] { "en-US", "fr-FR" };
            }

            return(cultures);
        }
示例#6
0
        protected override async Task AfterTestCaseStartingAsync()
        {
            await base.AfterTestCaseStartingAsync();

            try
            {
                var dataAttributes = TestCase.TestMethod.Method.GetCustomAttributes(typeof(DataAttribute));

                foreach (var dataAttribute in dataAttributes)
                {
                    var discovererAttribute = dataAttribute.GetCustomAttributes(typeof(DataDiscovererAttribute)).First();
                    var args           = discovererAttribute.GetConstructorArguments().Cast <string>().ToList();
                    var discovererType = SerializationHelper.GetType(args[1], args[0]);
                    var discoverer     = ExtensibilityPointFactory.GetDataDiscoverer(_diagnosticMessageSink, discovererType);

                    foreach (var dataRow in discoverer.GetData(dataAttribute, TestCase.TestMethod.Method))
                    {
                        _toDispose.AddRange(dataRow.OfType <IDisposable>());

                        ITypeInfo[] resolvedTypes = null;
                        var         methodToRun   = TestMethod;

                        if (methodToRun.IsGenericMethodDefinition)
                        {
                            resolvedTypes = TestCase.TestMethod.Method.ResolveGenericTypes(dataRow);
                            methodToRun   = methodToRun.MakeGenericMethod(resolvedTypes.Select(t => ((IReflectionTypeInfo)t).Type).ToArray());
                        }

                        var parameterTypes   = methodToRun.GetParameters().Select(p => p.ParameterType).ToArray();
                        var convertedDataRow = Reflector.ConvertArguments(dataRow, parameterTypes);

                        string theoryDisplayName;
                        if (convertedDataRow.Length == 1 && convertedDataRow[0] is Test.IReadableTestCase)
                        {
                            theoryDisplayName = ((Test.IReadableTestCase)convertedDataRow[0]).TestCase();
                        }
                        else
                        {
                            theoryDisplayName = TestCase.TestMethod.Method.GetDisplayNameWithArguments(DisplayName, convertedDataRow, resolvedTypes);
                        }

                        var test       = new XunitTest(TestCase, theoryDisplayName);
                        var skipReason = SkipReason ?? dataAttribute.GetNamedArgument <string>("Skip");
                        _testRunners.Add(new XunitTestRunner(test, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, skipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource));
                    }
                }
            }
            catch (Exception ex)
            {
                // Stash the exception so we can surface it during RunTestAsync
                _dataDiscoveryException = ex;
            }
        }
        public static async Task InvokeAsync(this MethodInfo method, object obj, object[] arguments)
        {
            method = method ?? throw new ArgumentNullException(nameof(method));

            var parameterTypes = method.GetParameters().Select(parameter => parameter.ParameterType).ToArray();

            Reflector.ConvertArguments(arguments, parameterTypes);

            if (method.Invoke(obj, arguments) is Task task)
            {
                await task;
            }
        }
示例#8
0
        public static async Task InvokeAsync(this MethodInfo method, object obj, object[] arguments)
        {
            Guard.AgainstNullArgument(nameof(method), method);

            var parameterTypes = method.GetParameters().Select(parameter => parameter.ParameterType).ToArray();

            Reflector.ConvertArguments(arguments, parameterTypes);

            if (method.Invoke(obj, arguments) is Task task)
            {
                await task;
            }
        }
示例#9
0
        public IEnumerable <IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
        {
            var ctorArgs = factAttribute.GetConstructorArguments().ToArray();
            var cultures = Reflector.ConvertArguments(ctorArgs, new[] { typeof(string[]) }).Cast <string[]>().Single();

            if (cultures == null || cultures.Length == 0)
            {
                cultures = new[] { "en-US", "fr-FR" }
            }
            ;

            return(cultures.Select(culture => new CulturedXunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod, culture)).ToList());
        }
    }
        public ScenarioRunner Create(object[] scenarioMethodArguments)
        {
            var parameters     = this.scenarioOutlineMethod.GetParameters().ToArray();
            var typeParameters = this.scenarioOutlineMethod.GetGenericArguments().ToArray();

            ITypeInfo[] typeArguments;
            MethodInfo  scenarioMethod;

            if (this.scenarioOutlineMethod.IsGenericMethodDefinition)
            {
                typeArguments = typeParameters
                                .Select(typeParameter => InferTypeArgument(typeParameter.Name, parameters, scenarioMethodArguments))
                                .ToArray();

                scenarioMethod = this.scenarioOutlineMethod.MakeGenericMethod(typeArguments.ToArray()).ToRuntimeMethod();
            }
            else
            {
                typeArguments  = new ITypeInfo[0];
                scenarioMethod = this.scenarioOutlineMethod.ToRuntimeMethod();
            }

            var passedArguments = Reflector.ConvertArguments(
                scenarioMethodArguments, scenarioMethod.GetParameters().Select(p => p.ParameterType).ToArray());

            var generatedArguments = GetGeneratedArguments(
                typeParameters, typeArguments, parameters, passedArguments.Length);

            var arguments = passedArguments
                            .Select(value => new Argument(value))
                            .Concat(generatedArguments)
                            .ToArray();

            var scenarioDisplayName = GetScenarioDisplayName(
                this.scenarioOutlineDisplayName, typeArguments, parameters, arguments);

            var scenario = new Scenario(this.scenarioOutline, scenarioDisplayName);

            return(new ScenarioRunner(
                       scenario,
                       this.messageBus,
                       this.scenarioClass,
                       this.constructorArguments,
                       scenarioMethod,
                       arguments.Select(argument => argument.Value).ToArray(),
                       this.skipReason,
                       this.beforeAfterScenarioAttributes,
                       new ExceptionAggregator(this.aggregator),
                       this.cancellationTokenSource));
        }
        public IEnumerable <IXunitTestCase> Discover(ITestCollection testCollection, IAssemblyInfo assembly, ITypeInfo testClass, IMethodInfo testMethod, IAttributeInfo factAttribute)
        {
            var ctorArgs = factAttribute.GetConstructorArguments().ToArray();
            var cultures = Reflector.ConvertArguments(ctorArgs, new[] { typeof(string[]) }).Cast <string[]>().Single();

            if (cultures == null || cultures.Length == 0)
            {
                cultures = new[] { "en-US", "fr-FR" }
            }
            ;

            return(cultures.Select(culture => new CulturedXunitTestCase(testCollection, assembly, testClass, testMethod, factAttribute, culture)).ToList());
        }
    }
 /// <summary>
 ///
 /// </summary>
 /// <param name="testCase"></param>
 /// <param name="displayName"></param>
 /// <param name="skipReason"></param>
 /// <param name="constructorArguments"></param>
 /// <param name="testMethodArguments"></param>
 /// <param name="messageBus"></param>
 /// <param name="aggregator"></param>
 /// <param name="cancellationTokenSource"></param>
 public ScenarioTestCaseRunner(IXunitTestCase testCase, string displayName, string skipReason, object[] constructorArguments, object[] testMethodArguments, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource)
     : base(testCase, displayName, skipReason, constructorArguments, testMethodArguments, messageBus, aggregator, cancellationTokenSource)
 {
     DisplayName          = displayName;
     SkipReason           = skipReason;
     ConstructorArguments = constructorArguments;
     TestClass            = base.TestCase.TestMethod.TestClass.Class.ToRuntimeType();
     TestMethod           = base.TestCase.Method.ToRuntimeMethod();
     ParameterInfo[] parameters     = TestMethod.GetParameters();
     Type[]          parameterTypes = new Type[parameters.Length];
     for (int i = 0; i < parameters.Length; i++)
     {
         parameterTypes[i] = parameters[i].ParameterType;
     }
     TestMethodArguments = Reflector.ConvertArguments(testMethodArguments, parameterTypes);
 }
示例#13
0
        private void CreateTheorySpecificTestRunners()
        {
            try
            {
                var dataAttributes = TestCase.TestMethod.Method.GetCustomAttributes(typeof(DataAttribute));

                foreach (var dataAttribute in dataAttributes)
                {
                    var discovererAttribute = dataAttribute.GetCustomAttributes(typeof(DataDiscovererAttribute)).First();
                    var args           = discovererAttribute.GetConstructorArguments().Cast <string>().ToList();
                    var discovererType = LoadType(args[1], args[0]);
                    var discoverer     = ExtensibilityPointFactory.GetDataDiscoverer(_diagnosticMessageSink, discovererType);

                    foreach (var dataRow in discoverer.GetData(dataAttribute, TestCase.TestMethod.Method))
                    {
                        _toDispose.AddRange(dataRow.OfType <IDisposable>());

                        ITypeInfo[] resolvedTypes = null;
                        var         methodToRun   = TestMethod;

                        if (methodToRun.IsGenericMethodDefinition)
                        {
                            resolvedTypes = TestCase.TestMethod.Method.ResolveGenericTypes(dataRow);
                            methodToRun   = methodToRun.MakeGenericMethod(resolvedTypes.Select(t => ((IReflectionTypeInfo)t).Type).ToArray());
                        }

                        var parameterTypes    = methodToRun.GetParameters().Select(p => p.ParameterType).ToArray();
                        var convertedDataRow  = Reflector.ConvertArguments(dataRow, parameterTypes);
                        var theoryDisplayName = TestCase.TestMethod.Method.GetDisplayNameWithArguments(DisplayName, convertedDataRow, resolvedTypes);
                        var test = new XunitTest(TestCase, theoryDisplayName);

                        _testRunners.Add(new ScenarioTestRunner(test, MessageBus, TestClass, ConstructorArguments, methodToRun,
                                                                convertedDataRow, SkipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource));
                    }
                }
            }
            catch (Exception ex)
            {
                // Stash the exception so we can surface it during RunTestAsync
                _dataDiscoveryException = ex;
            }
        }
        public ScenarioInfo(IMethodInfo testMethod, object[] actualArgs, string scenarioOutlineDisplayName)
        {
            //Guard.AgainstNullArgument(nameof(testMethod), testMethod);

#if DEBUG
            testMethod = testMethod.RequiresNotNull(nameof(testMethod));
#endif

            // Which, we "do", in DEBUG mode.
#pragma warning disable CA1062 // ...validate parameter 'name' is non-null before using it...
            var parameters = testMethod.GetParameters().ToList();
#pragma warning restore CA1062 // ...validate parameter 'name' is non-null before using it...

            var typeParams = testMethod.GetGenericArguments().ToList();

            ITypeInfo[] typeArgs;
            if (testMethod.IsGenericMethodDefinition)
            {
                typeArgs = typeParams
                           .Select(typeParameter => InferTypeArgument(typeParameter.Name, parameters, actualArgs))
                           .ToArray();

                this.MethodToRun = testMethod.MakeGenericMethod(typeArgs).ToRuntimeMethod();
            }
            else
            {
                typeArgs         = Array.Empty <ITypeInfo>();
                this.MethodToRun = testMethod.ToRuntimeMethod();
            }

            var passedArgs = Reflector.ConvertArguments(actualArgs, this.MethodToRun.GetParameters().Select(p => p.ParameterType).ToArray());

            var generatedArguments = GetGeneratedArguments(typeParams, typeArgs, parameters, passedArgs.Length);

            var args = passedArgs
                       .Select(value => new Argument(value))
                       .Concat(generatedArguments)
                       .ToList();

            this.ScenarioDisplayName = GetScenarioDisplayName(scenarioOutlineDisplayName, typeArgs, parameters, args);
            this.ConvertedActualArgs = args.Select(arg => arg.Value).ToList();
        }
示例#15
0
    /// <summary>
    /// Computes values from the test case and resolves the test method arguments. To be called by the public RunAsync method that
    /// will end up being exposed by the derived class as the primary public API.
    /// </summary>
    /// <param name="testCase">The test case that is being run</param>
    /// <param name="testMethodArguments">The test method arguments to be converted</param>
    protected (Type TestClass, MethodInfo TestMethod, IReadOnlyCollection <BeforeAfterTestAttribute> BeforeAfterTestAttributes) Initialize(
        IXunitTestCase testCase,
        ref object?[]?testMethodArguments)
    {
        // TODO: This means XunitTestFramework can never run test cases without a class & method
        var testClass  = testCase.TestClass?.Class.ToRuntimeType() ?? throw new ArgumentException("testCase.TestClass.Class does not map to a Type object", nameof(testCase));
        var testMethod = testCase.Method.ToRuntimeMethod() ?? throw new ArgumentException("testCase.TestMethod does not map to a MethodInfo object", nameof(testCase));

        var parameters     = testMethod.GetParameters();
        var parameterTypes = new Type[parameters.Length];

        for (var i = 0; i < parameters.Length; i++)
        {
            parameterTypes[i] = parameters[i].ParameterType;
        }

        testMethodArguments = Reflector.ConvertArguments(testMethodArguments, parameterTypes);

        IEnumerable <Attribute> beforeAfterTestCollectionAttributes;

        if (testCase.TestCollection.CollectionDefinition is _IReflectionTypeInfo collectionDefinition)
        {
            beforeAfterTestCollectionAttributes = collectionDefinition.Type.GetCustomAttributes(typeof(BeforeAfterTestAttribute));
        }
        else
        {
            beforeAfterTestCollectionAttributes = Enumerable.Empty <Attribute>();
        }

        var beforeAfterTestAttributes =
            beforeAfterTestCollectionAttributes
            .Concat(testClass.GetCustomAttributes(typeof(BeforeAfterTestAttribute)))
            .Concat(testMethod.GetCustomAttributes(typeof(BeforeAfterTestAttribute)))
            .Concat(testClass.Assembly.GetCustomAttributes(typeof(BeforeAfterTestAttribute)))
            .Cast <BeforeAfterTestAttribute>()
            .CastOrToReadOnlyCollection();

        return(testClass, testMethod, beforeAfterTestAttributes);
    }
示例#16
0
        public ValueTask <IReadOnlyCollection <IXunitTestCase> > Discover(
            _ITestFrameworkDiscoveryOptions discoveryOptions,
            _ITestMethod testMethod,
            _IAttributeInfo factAttribute)
        {
            var ctorArgs = factAttribute.GetConstructorArguments().ToArray();
            var cultures = Reflector.ConvertArguments(ctorArgs, new[] { typeof(string[]) }).Cast <string[]>().Single();

            if (cultures == null || cultures.Length == 0)
            {
                cultures = new[] { "en-US", "fr-FR" }
            }
            ;

            var methodDisplay        = discoveryOptions.MethodDisplayOrDefault();
            var methodDisplayOptions = discoveryOptions.MethodDisplayOptionsOrDefault();

            var result =
                cultures
                .Select(culture => CreateTestCase(testMethod, culture, methodDisplay, methodDisplayOptions))
                .CastOrToReadOnlyCollection();

            return(new(result));
        }

        CulturedXunitTestCase CreateTestCase(
            _ITestMethod testMethod,
            string culture,
            TestMethodDisplay methodDisplay,
            TestMethodDisplayOptions methodDisplayOptions)
        {
            return(new CulturedXunitTestCase(
                       methodDisplay,
                       methodDisplayOptions,
                       testMethod,
                       culture
                       ));
        }
    }
        private async Task ExecuteTestMethod(MethodInfo runtimeMethod, RunSummary runSummary, IEnumerable <WebDriverAttribute> driverAttributes, object[] dataRow)
        {
            foreach (var driverAttribute in driverAttributes)
            {
                foreach (var driver in driverAttribute.GetDrivers(runtimeMethod))
                {
                    Fixture newFixture        = null;
                    object  initializerReturn = null;

                    ITypeInfo[] resolvedTypes = null;
                    var         methodToRun   = runtimeMethod;

                    if (methodToRun.IsGenericMethodDefinition)
                    {
                        resolvedTypes = TestCase.TestMethod.Method.ResolveGenericTypes(dataRow);
                        methodToRun   = methodToRun.MakeGenericMethod(resolvedTypes.Select(t => ((IReflectionTypeInfo)t).Type).ToArray());
                    }

                    List <object> parameterList = new List <object>();
                    var           parameters    = methodToRun.GetParameters().ToArray();

                    try
                    {
                        newFixture = FixtureCreationAttribute.GetNewFixture(driver, runtimeMethod);

                        var initializeDataAttributes = ReflectionHelper.GetAttributes <FixtureInitializationAttribute>(runtimeMethod);

                        foreach (var initializeDataAttribute in initializeDataAttributes)
                        {
                            if (initializeDataAttribute is IMethodInfoAware)
                            {
#if DNX
                                var property = initializeDataAttribute.GetType().GetRuntimeProperty("Method");

                                property.SetValue(initializeDataAttribute, runtimeMethod);
#else
                                ((IMethodInfoAware)initializeDataAttribute).Method = runtimeMethod;
#endif
                            }

                            initializeDataAttribute.Initialize(newFixture.Data);
                        }

                        var initializeAttribute = ReflectionHelper.GetAttribute <IFixtureInitializationAttribute>(runtimeMethod);

                        if (initializeAttribute != null)
                        {
                            initializerReturn = initializeAttribute.Initialize(runtimeMethod, newFixture);
                        }

                        int dataRowIndex = 0;

                        for (int i = 0; i < parameters.Length; i++)
                        {
                            var parameter  = parameters[i];
                            var attributes = parameter.GetCustomAttributes(true);

                            if (parameter.ParameterType == typeof(IWebDriver))
                            {
                                parameterList.Add(driver);
                            }
                            else if (parameter.ParameterType == typeof(Fixture))
                            {
                                parameterList.Add(newFixture);
                            }
                            else if (attributes.Any(a => a is GenerateAttribute))
                            {
                                var generateAttribute = (GenerateAttribute)attributes.First(a => a is GenerateAttribute);

                                InitializeCustomAttribute(generateAttribute, runtimeMethod, parameter);

                                var constraintName = generateAttribute.ConstraintName ?? parameter.Name;
                                var min            = generateAttribute.Min;
                                var max            = generateAttribute.Max;

                                var value = newFixture.Data.Generate(parameter.ParameterType, constraintName, new { min, max });
                                parameterList.Add(value);
                            }
                            else if (attributes.Any(a => a is LocateAttribute))
                            {
                                var locateAttribute = (LocateAttribute)attributes.First(a => a is LocateAttribute);

                                InitializeCustomAttribute(locateAttribute, runtimeMethod, parameter);

                                var value = locateAttribute.Value;

                                if (value == null)
                                {
                                    value = newFixture.Data.Generate(new SimpleFixture.DataRequest(null,
                                                                                                   newFixture.Data,
                                                                                                   parameter.ParameterType,
                                                                                                   parameter.Name,
                                                                                                   false,
                                                                                                   null,
                                                                                                   null));
                                }

                                parameterList.Add(value);
                            }
                            else if (attributes.Any(a => a is FreezeAttribute))
                            {
                                var freeze = (FreezeAttribute)attributes.FirstOrDefault(a => a is FreezeAttribute);

                                InitializeCustomAttribute(freeze, runtimeMethod, parameter);

                                var value = freeze.Value;

                                if (value == null)
                                {
                                    var constraintName = freeze.ConstraintName ?? parameter.Name;
                                    var min            = freeze.Min;
                                    var max            = freeze.Max;

                                    value = newFixture.Data.Generate(parameter.ParameterType, constraintName, new { min, max });
                                }

                                parameterList.Add(value);

                                object lastObject         = parameterList.Last();
                                var    closedFreezeMethod =
                                    FreezeMethod.MakeGenericMethod(lastObject.GetType());

                                closedFreezeMethod.Invoke(null, new object[] { newFixture.Data, value, freeze.For });
                            }
                            else if (initializerReturn != null && parameter.ParameterType == initializerReturn.GetType())
                            {
                                parameterList.Add(initializerReturn);
                                initializerReturn = null;
                            }
                            else if (dataRowIndex < dataRow.Length)
                            {
                                var dataValue = dataRow[dataRowIndex];
                                dataRowIndex++;
                                parameterList.Add(dataValue);
                            }
                            else
                            {
                                var value = newFixture.Data.Generate(parameter.ParameterType, parameter.Name);
                                parameterList.Add(value);
                            }
                        }
                    }
                    catch (Exception exp)
                    {
                        Aggregator.Add(exp);
                    }

                    var convertedDataRow  = Reflector.ConvertArguments(parameterList.ToArray(), parameters.Select(p => p.ParameterType).ToArray());
                    var theoryDisplayName =
                        TestCase.TestMethod.Method.GetDisplayNameWithArguments(DisplayName + " " + GetDriverName(driver),
                                                                               dataRow,
                                                                               resolvedTypes);

                    var             test       = new XunitTest(TestCase, theoryDisplayName);
                    var             skipReason = SkipReason;
                    XunitTestRunner testRunner = CreateTestRunner(test, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, skipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource);

                    runSummary.Aggregate(await testRunner.RunAsync());

                    var timer = new ExecutionTimer();
                    timer.Aggregate(() => DisposeOfData(driverAttribute, driver, newFixture, dataRow));

                    runSummary.Time += timer.Total;
                }
            }
        }
示例#18
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MettleTestCaseRunner"/> class.
        /// </summary>
        /// <param name="testCase">The test case to be run.</param>
        /// <param name="displayName">The display name of the test case.</param>
        /// <param name="skipReason">The skip reason, if the test is to be skipped.</param>
        /// <param name="constructorArguments">The arguments to be passed to the test class constructor.</param>
        /// <param name="testMethodArguments">The arguments to be passed to the test method.</param>
        /// <param name="messageBus">The message bus to report run status to.</param>
        /// <param name="aggregator">The exception aggregator used to run code and collect exceptions.</param>
        /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param>
        public MettleTestCaseRunner(IXunitTestCase testCase,
                                    string displayName,
                                    string skipReason,
                                    object[] constructorArguments,
                                    object[] testMethodArguments,
                                    IMessageBus messageBus,
                                    ExceptionAggregator aggregator,
                                    CancellationTokenSource cancellationTokenSource,
                                    IServiceProvider serviceProvider)
            : base(testCase, messageBus, aggregator, cancellationTokenSource)
        {
            DisplayName          = displayName;
            SkipReason           = skipReason;
            TestClass            = TestCase.TestMethod.TestClass.Class.ToRuntimeType();
            TestMethod           = TestCase.Method.ToRuntimeMethod();
            this.serviceProvider = serviceProvider;

            var ctor       = TestClass.GetConstructors().FirstOrDefault();
            var parameters = ctor.GetParameters();

            Type[]   parameterTypes;
            object[] args;

            if (constructorArguments != null || constructorArguments.Length > 0)
            {
                parameterTypes = new Type[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                {
                    parameterTypes[i] = parameters[i].ParameterType;
                }

                args = constructorArguments ?? Array.Empty <object>();
                var ctorArgs = new object[parameters.Length];
                Array.Copy(args, ctorArgs, args.Length);

                for (int i = 0; i < parameters.Length; i++)
                {
                    var obj = ctorArgs[i];
                    if (obj == null)
                    {
                        obj = this.serviceProvider?.GetService(parameters[i].ParameterType);
                    }

                    ctorArgs[i] = obj;
                }

                ConstructorArguments = Reflector.ConvertArguments(ctorArgs, parameterTypes);
            }
            else
            {
                ConstructorArguments = constructorArguments;
            }

            parameters     = TestMethod.GetParameters();
            parameterTypes = new Type[parameters.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                parameterTypes[i] = parameters[i].ParameterType;
            }

            args = testMethodArguments ?? Array.Empty <object>();
            if (parameters.Length != args.Length)
            {
                var methodArgs = new object[parameters.Length];
                Array.Copy(args, methodArgs, args.Length);
                for (var i = 0; i < parameters.Length; i++)
                {
                    var obj = methodArgs[i];
                    if (obj == null)
                    {
                        obj = this.serviceProvider?.GetService(parameters[i].ParameterType);
                    }

                    methodArgs[i] = obj;
                }

                args = methodArgs;
            }

            TestMethodArguments = Reflector.ConvertArguments(args, parameterTypes);
        }
示例#19
0
        protected override async Task AfterTestCaseStartingAsync()
        {
            await base.AfterTestCaseStartingAsync();

            try
            {
                var dataAttributes = TestCase.TestMethod.Method.GetCustomAttributes(typeof(DataAttribute));

                foreach (var dataAttribute in dataAttributes)
                {
                    var discovererAttribute = dataAttribute.GetCustomAttributes(typeof(DataDiscovererAttribute)).First();
                    var args           = discovererAttribute.GetConstructorArguments().Cast <string>().ToList();
                    var discovererType = LoadType(args[1], args[0]);
                    if (discovererType == null)
                    {
                        if (dataAttribute is IReflectionAttributeInfo reflectionAttribute)
                        {
                            Aggregator.Add(new InvalidOperationException($"Data discoverer specified for {reflectionAttribute.Attribute.GetType()} on {TestCase.TestMethod.TestClass.Class.Name}.{TestCase.TestMethod.Method.Name} does not exist."));
                        }
                        else
                        {
                            Aggregator.Add(new InvalidOperationException($"A data discoverer specified on {TestCase.TestMethod.TestClass.Class.Name}.{TestCase.TestMethod.Method.Name} does not exist."));
                        }

                        continue;
                    }

                    IDataDiscoverer discoverer;
                    try
                    {
                        discoverer = ExtensibilityPointFactory.GetDataDiscoverer(_diagnosticMessageSink, discovererType);
                    }
                    catch (InvalidCastException)
                    {
                        if (dataAttribute is IReflectionAttributeInfo reflectionAttribute)
                        {
                            Aggregator.Add(new InvalidOperationException($"Data discoverer specified for {reflectionAttribute.Attribute.GetType()} on {TestCase.TestMethod.TestClass.Class.Name}.{TestCase.TestMethod.Method.Name} does not implement IDataDiscoverer."));
                        }
                        else
                        {
                            Aggregator.Add(new InvalidOperationException($"A data discoverer specified on {TestCase.TestMethod.TestClass.Class.Name}.{TestCase.TestMethod.Method.Name} does not implement IDataDiscoverer."));
                        }

                        continue;
                    }

                    var data = discoverer.GetData(dataAttribute, TestCase.TestMethod.Method);
                    if (data == null)
                    {
                        Aggregator.Add(new InvalidOperationException($"Test data returned null for {TestCase.TestMethod.TestClass.Class.Name}.{TestCase.TestMethod.Method.Name}. Make sure it is statically initialized before this test method is called."));
                        continue;
                    }

                    foreach (var dataRow in data)
                    {
                        _toDispose.AddRange(dataRow.OfType <IDisposable>());

                        ITypeInfo[] resolvedTypes    = null;
                        var         methodToRun      = TestMethod;
                        var         convertedDataRow = methodToRun.ResolveMethodArguments(dataRow);

                        if (methodToRun.IsGenericMethodDefinition)
                        {
                            resolvedTypes = TestCase.TestMethod.Method.ResolveGenericTypes(convertedDataRow);
                            methodToRun   = methodToRun.MakeGenericMethod(resolvedTypes.Select(t => ((IReflectionTypeInfo)t).Type).ToArray());
                        }

                        var parameterTypes = methodToRun.GetParameters().Select(p => p.ParameterType).ToArray();
                        convertedDataRow = Reflector.ConvertArguments(convertedDataRow, parameterTypes);

                        var theoryDisplayName = TestCase.TestMethod.Method.GetDisplayNameWithArguments(DisplayName, convertedDataRow, resolvedTypes);
                        var test       = CreateTest(TestCase, theoryDisplayName);
                        var skipReason = SkipReason ?? dataAttribute.GetNamedArgument <string>("Skip");
                        _testRunners.Add(new ScenarioTestRunner(test, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, skipReason, BeforeAfterAttributes, new ExceptionAggregator(Aggregator), CancellationTokenSource));
                    }
                }
            }
            catch (Exception ex)
            {
                // Stash the exception so we can surface it during RunTestAsync
                _dataDiscoveryException = ex;
            }
        }
示例#20
0
        private async Task ExecuteTestMethod(MethodInfo runtimeMethod, RunSummary runSummary, IEnumerable <IApplicationAttribute> applicationAttributes, object[] dataRow)
        {
            foreach (var applicationAttribute in applicationAttributes)
            {
                Application   application = null;
                Window        mainWindow  = null;
                WindowFixture fixture     = null;

                try
                {
                    application = applicationAttribute.ProvideApplication(runtimeMethod);

                    application.WaitWhileBusy();

                    mainWindow = null;

                    if (!string.IsNullOrEmpty(applicationAttribute.Window))
                    {
                        mainWindow = application.GetWindow(applicationAttribute.Window);
                    }
                    else
                    {
                        mainWindow = application.GetWindows().FirstOrDefault();
                    }

                    if (mainWindow == null)
                    {
                        throw new Exception("Could not locate main window " + applicationAttribute.Window);
                    }

                    fixture = new WindowFixture(application, mainWindow);
                    ITypeInfo[] resolvedTypes = null;
                    var         methodToRun   = runtimeMethod;

                    if (methodToRun.IsGenericMethodDefinition)
                    {
                        resolvedTypes = TestCase.TestMethod.Method.ResolveGenericTypes(dataRow);
                        methodToRun   = methodToRun.MakeGenericMethod(resolvedTypes.Select(t => ((IReflectionTypeInfo)t).Type).ToArray());
                    }

                    List <object> parameterList     = new List <object>();
                    var           parameters        = methodToRun.GetParameters().ToArray();
                    object        initializerReturn = null;

                    int dataRowIndex = 0;

                    for (int i = 0; i < parameters.Length; i++)
                    {
                        var parameter  = parameters[i];
                        var attributes = parameter.GetCustomAttributes(true);

                        if (parameter.ParameterType == typeof(Window))
                        {
                            parameterList.Add(mainWindow);
                        }
                        else if (parameter.ParameterType == typeof(IWindowFixture))
                        {
                            parameterList.Add(fixture);
                        }
                        else if (attributes.Any(a => a is GenerateAttribute))
                        {
                            var generateAttribute = (GenerateAttribute)attributes.First(a => a is GenerateAttribute);

                            InitializeCustomAttribute(generateAttribute, runtimeMethod, parameter);

                            var constraintName = generateAttribute.ConstraintName ?? parameter.Name;
                            var min            = generateAttribute.Min;
                            var max            = generateAttribute.Max;

                            var value = fixture.Data.Generate(parameter.ParameterType, constraintName, new { min, max });
                            parameterList.Add(value);
                        }
                        else if (attributes.Any(a => a is LocateAttribute))
                        {
                            var locateAttribute = (LocateAttribute)attributes.First(a => a is LocateAttribute);

                            InitializeCustomAttribute(locateAttribute, runtimeMethod, parameter);

                            var value = locateAttribute.Value;

                            if (value == null)
                            {
                                value = fixture.Data.Generate(new SimpleFixture.DataRequest(null,
                                                                                            fixture.Data,
                                                                                            parameter.ParameterType,
                                                                                            parameter.Name,
                                                                                            false,
                                                                                            null,
                                                                                            null));
                            }

                            parameterList.Add(value);
                        }
                        else if (attributes.Any(a => a is FreezeAttribute))
                        {
                            var freeze = (FreezeAttribute)attributes.FirstOrDefault(a => a is FreezeAttribute);

                            InitializeCustomAttribute(freeze, runtimeMethod, parameter);

                            var value = freeze.Value;

                            if (value == null)
                            {
                                var constraintName = freeze.ConstraintName ?? parameter.Name;
                                var min            = freeze.Min;
                                var max            = freeze.Max;

                                value = fixture.Data.Generate(parameter.ParameterType, constraintName, new { min, max });
                            }

                            parameterList.Add(value);

                            object lastObject         = parameterList.Last();
                            var    closedFreezeMethod =
                                FreezeMethod.MakeGenericMethod(lastObject.GetType());

                            closedFreezeMethod.Invoke(null, new object[] { fixture.Data, value, freeze.For });
                        }
                        else if (initializerReturn != null && parameter.ParameterType == initializerReturn.GetType())
                        {
                            parameterList.Add(initializerReturn);
                            initializerReturn = null;
                        }
                        else if (dataRowIndex < dataRow.Length)
                        {
                            var dataValue = dataRow[dataRowIndex];
                            dataRowIndex++;
                            parameterList.Add(dataValue);
                        }
                        else
                        {
                            var value = fixture.Data.Generate(parameter.ParameterType, parameter.Name);
                            parameterList.Add(value);
                        }
                    }

                    var convertedDataRow  = Reflector.ConvertArguments(parameterList.ToArray(), parameters.Select(p => p.ParameterType).ToArray());
                    var theoryDisplayName =
                        TestCase.TestMethod.Method.GetDisplayNameWithArguments(DisplayName + " " + applicationAttribute.Application,
                                                                               dataRow,
                                                                               resolvedTypes);

                    var             test       = new XunitTest(TestCase, theoryDisplayName);
                    var             skipReason = SkipReason;
                    XunitTestRunner testRunner = CreateTestRunner(test, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, skipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource);

                    runSummary.Aggregate(await testRunner.RunAsync());
                }
                catch (Exception exp)
                {
                    Aggregator.Add(exp);
                }
                finally
                {
                    var timer = new ExecutionTimer();
                    timer.Aggregate(() => DisposeOfData(application, mainWindow, fixture, dataRow));

                    runSummary.Time += timer.Total;
                }
            }
        }
        private async Task <RunSummary> InvokeScenarioMethodAsync(object scenarioClassInstance)
        {
            var backgroundSteps = new List <IStepDefinition>();
            var scenarioSteps   = new List <IStepDefinition>();
            var tearDownSteps   = new List <IStepDefinition>();

            await this._aggregator.RunAsync(async() =>
            {
                // We leverage this for both Background and TearDown methods.
                async Task OnDiscoverSupportMethodsAsync <TAttribute>(
                    IScenario scenario, ExecutionTimer timer)
                where TAttribute : SupportMethodAttribute
                {
                    var methods = scenario.TestCase.TestMethod.TestClass.Class
                                  .GetMethods(false)
                                  .Where(candidate => candidate.GetCustomAttributes(typeof(TAttribute)).Any())
                                  .Select(method => method.ToRuntimeMethod())
                                  // #2 MWP 2020-07-01 12:28:03 PM: the rubber meeting the road here.
                                  .OrderBy(method => method, new MethodInfoComparer()).ToList();

                    // Thus ensuring correct front to back Background, reverse TearDown.
                    if (typeof(TAttribute) == typeof(TearDownAttribute))
                    {
                        methods.Reverse();
                    }

                    foreach (var method in methods)
                    {
                        /* #4 MWP 2020-07-09 05:47:25 PM / We support seeding default values into
                         * Background methods with parameters. However, this is the extent of what
                         * we can accomplish there. It does not make any sense to cross any Theory
                         * dataRow bridges for Background methods. */
                        var argTypes = method.GetParameters().Select(param => param.ParameterType).ToArray();
                        var args     = argTypes.Select(paramType => paramType.GetDefault()).ToArray();

                        var convertedArgs = Reflector.ConvertArguments(args, argTypes);
                        convertedArgs     = convertedArgs.Any() ? convertedArgs : null;

                        await timer.AggregateAsync(() => method.InvokeAsync(scenarioClassInstance, convertedArgs));
                    }
                }

                using (CurrentThread.EnterStepDefinitionContext())
                {
                    await OnDiscoverSupportMethodsAsync <BackgroundAttribute>(this._scenario, this._timer);

                    backgroundSteps.AddRange(CurrentThread.StepDefinitions);
                }

                using (CurrentThread.EnterStepDefinitionContext())
                {
                    await this._timer.AggregateAsync(() => this._scenarioMethod.InvokeAsync(scenarioClassInstance, this._scenarioMethodArguments));

                    scenarioSteps.AddRange(CurrentThread.StepDefinitions);
                }

                // MWP Sun, 06 Dec 2020 11:00:56 AM / Rinse and repeat Background, except for TearDown...
                using (CurrentThread.EnterStepDefinitionContext())
                {
                    await OnDiscoverSupportMethodsAsync <TearDownAttribute>(this._scenario, this._timer);

                    tearDownSteps.AddRange(CurrentThread.StepDefinitions);
                }
            });

            var runSummary = new RunSummary {
                Time = this._timer.Total
            };

            if (!this._aggregator.HasExceptions)
            {
                // Assumes Scenario for StepDefinitionType.
                backgroundSteps.ForEach(x => x.StepDefinitionType = StepType.Background);
                tearDownSteps.ForEach(x => x.StepDefinitionType   = StepType.TearDown);
                runSummary.Aggregate(await this.InvokeStepsAsync(backgroundSteps, scenarioSteps, tearDownSteps));
            }

            return(runSummary);
        }