/// <inheritdoc/>
        public void Run(IEnumerable<ITestCase> testMethods, IMessageSink messageSink)
        {
            bool cancelled = false;
            var totalSummary = new RunSummary();

            string currentDirectory = Directory.GetCurrentDirectory();

            try
            {
                Directory.SetCurrentDirectory(Path.GetDirectoryName(assemblyInfo.AssemblyPath));

                if (messageSink.OnMessage(new TestAssemblyStarting()))
                {
                    var classGroups = testMethods.Cast<XunitTestCase>().GroupBy(tc => tc.Class).ToList();

                    if (classGroups.Count > 0)
                    {
                        var collectionSummary = new RunSummary();

                        if (messageSink.OnMessage(new TestCollectionStarting()))
                        {
                            foreach (var group in classGroups)
                            {
                                var classSummary = new RunSummary();

                                if (!messageSink.OnMessage(new TestClassStarting { ClassName = group.Key.Name }))
                                    cancelled = true;
                                else
                                {
                                    cancelled = RunTestClass(messageSink, group, classSummary);
                                    collectionSummary.Aggregate(classSummary);
                                }

                                if (!messageSink.OnMessage(new TestClassFinished { Assembly = assemblyInfo, ClassName = group.Key.Name, TestsRun = classSummary.Total }))
                                    cancelled = true;

                                if (cancelled)
                                    break;
                            }
                        }

                        messageSink.OnMessage(new TestCollectionFinished { Assembly = assemblyInfo, TestsRun = collectionSummary.Total });
                        totalSummary.Aggregate(collectionSummary);
                    }
                }

                messageSink.OnMessage(new TestAssemblyFinished
                {
                    Assembly = assemblyInfo,
                    TestsRun = totalSummary.Total,
                    TestsFailed = totalSummary.Failed,
                    TestsSkipped = totalSummary.Skipped,
                    ExecutionTime = totalSummary.Time
                });
            }
            finally
            {
                Directory.SetCurrentDirectory(currentDirectory);
            }
        }
        public async Task<RunSummary> RunAsync()
        {
            var summary = new RunSummary();
            await this.aggregator.RunAsync(async () =>
            {
                if (!this.cancellationTokenSource.IsCancellationRequested)
                {
                    var testClassInstance = this.CreateScenarioClass();

                    if (!this.cancellationTokenSource.IsCancellationRequested)
                    {
                        await this.BeforeScenarioMethodInvokedAsync();

                        if (!this.cancellationTokenSource.IsCancellationRequested && !this.aggregator.HasExceptions)
                        {
                            summary.Aggregate(await this.InvokeScenarioMethodAsync(testClassInstance));
                        }

                        await this.AfterScenarioMethodInvokedAsync();
                    }

                    var disposable = testClassInstance as IDisposable;
                    if (disposable != null)
                    {
                        this.timer.Aggregate(() => this.aggregator.Run(disposable.Dispose));
                    }
                }

                summary.Time += this.timer.Total;
            });

            return summary;
        }
        protected override async Task<RunSummary> RunTestCollectionAsync(IMessageBus messageBus, ITestCollection testCollection, IEnumerable<IXunitTestCase> testCases, CancellationTokenSource cancellationTokenSource)
        {
            var summary = new RunSummary();

            var defaultCases = new List<IXunitTestCase>();
            var observationTestCases = new List<ObservationTestCase>();
            foreach (var testCase in testCases)
            {
                if (testCase is ObservationTestCase)
                    observationTestCases.Add(testCase as ObservationTestCase);
                else
                    defaultCases.Add(testCase);
            }

            if (observationTestCases.Any())
            {
                summary.Aggregate(
                    await new ObservationTestCollectionRunner(
                        testCollection,
                        observationTestCases,
                        DiagnosticMessageSink,
                        messageBus,
                        TestCaseOrderer,
                        new ExceptionAggregator(Aggregator),
                        cancellationTokenSource
                    )
                    .RunAsync()
                );
            }

            if (defaultCases.Any())
            {
                summary.Aggregate(
                    await base.RunTestCollectionAsync(messageBus, testCollection, defaultCases, cancellationTokenSource)
                );
            }

            return summary;
        }
示例#4
0
        /// <summary>
        /// Runs the list of test collections. By default, groups the tests by collection and runs them synchronously.
        /// </summary>
        /// <param name="messageBus">The message bus to report run status to.</param>
        /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param>
        /// <returns>Returns summary information about the tests that were run.</returns>
        protected virtual async Task <RunSummary> RunTestCollectionsAsync(IMessageBus messageBus, CancellationTokenSource cancellationTokenSource)
        {
            var summary = new RunSummary();

            foreach (var collection in OrderTestCollections())
            {
                summary.Aggregate(await RunTestCollectionAsync(messageBus, collection.Item1, collection.Item2, cancellationTokenSource));
                if (cancellationTokenSource.IsCancellationRequested)
                {
                    break;
                }
            }

            return(summary);
        }
示例#5
0
        /// <summary>
        /// Runs the list of test cases. By default, it runs the cases in order, synchronously.
        /// </summary>
        /// <returns>Returns summary information about the tests that were run.</returns>
        protected virtual async Task <RunSummary> RunTestCasesAsync()
        {
            var summary = new RunSummary();

            foreach (var testCase in TestCases)
            {
                summary.Aggregate(await RunTestCaseAsync(testCase));
                if (CancellationTokenSource.IsCancellationRequested)
                {
                    break;
                }
            }

            return(summary);
        }
示例#6
0
        /// <summary>
        /// Runs the list of test classes. By default, groups the tests by class and runs them synchronously.
        /// </summary>
        /// <returns>Returns summary information about the tests that were run.</returns>
        protected virtual async Task <RunSummary> RunTestClassesAsync()
        {
            var summary = new RunSummary();

            foreach (var testCasesByClass in TestCases.GroupBy(tc => tc.Class))
            {
                summary.Aggregate(await RunTestClassAsync((IReflectionTypeInfo)testCasesByClass.Key, testCasesByClass));
                if (CancellationTokenSource.IsCancellationRequested)
                {
                    break;
                }
            }

            return(summary);
        }
示例#7
0
        /// <summary>
        /// Runs the list of test collections. By default, groups the tests by collection and runs them synchronously.
        /// </summary>
        /// <param name="messageBus">The message bus to report run status to.</param>
        /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param>
        /// <returns>Returns summary information about the tests that were run.</returns>
        protected virtual async Task <RunSummary> RunTestCollectionsAsync(IMessageBus messageBus, CancellationTokenSource cancellationTokenSource)
        {
            var summary = new RunSummary();

            foreach (var collectionGroup in TestCases.Cast <TTestCase>().GroupBy(tc => tc.TestMethod.TestClass.TestCollection, TestCollectionComparer.Instance))
            {
                summary.Aggregate(await RunTestCollectionAsync(messageBus, collectionGroup.Key, collectionGroup, cancellationTokenSource));
                if (cancellationTokenSource.IsCancellationRequested)
                {
                    break;
                }
            }

            return(summary);
        }
示例#8
0
        /// <summary>
        /// Runs the list of test methods. By default, orders the tests, groups them by method and runs them synchronously.
        /// </summary>
        /// <returns>Returns summary information about the tests that were run.</returns>
        protected virtual async Task <RunSummary> RunTestMethodsAsync()
        {
            var summary              = new RunSummary();
            var orderedTestCases     = TestCaseOrderer.OrderTestCases(TestCases);
            var constructorArguments = CreateTestClassConstructorArguments();

            foreach (var method in orderedTestCases.GroupBy(tc => tc.Method))
            {
                summary.Aggregate(await RunTestMethodAsync((IReflectionMethodInfo)method.Key, method, constructorArguments));
                if (CancellationTokenSource.IsCancellationRequested)
                {
                    break;
                }
            }

            return(summary);
        }
        public async Task<RunSummary> RunAsync()
        {
            if (!string.IsNullOrEmpty(this.skipReason))
            {
                this.messageBus.Queue(
                    this.scenario, test => new TestSkipped(test, this.skipReason), this.cancellationTokenSource);

                return new RunSummary { Total = 1, Skipped = 1 };
            }
            else
            {
                var summary = new RunSummary();
                var output = string.Empty;
                var childAggregator = new ExceptionAggregator(this.parentAggregator);
                if (!childAggregator.HasExceptions)
                {
                    var tuple = await childAggregator.RunAsync(() => this.InvokeScenarioAsync(childAggregator));
                    summary.Aggregate(tuple.Item1);
                    output = tuple.Item2;
                }

                var exception = childAggregator.ToException();
                if (exception != null)
                {
                    summary.Total++;
                    summary.Failed++;
                    this.messageBus.Queue(
                        this.scenario,
                        test => new TestFailed(test, summary.Time, output, exception),
                        this.cancellationTokenSource);
                }
                else if (summary.Total == 0)
                {
                    summary.Total++;
                    this.messageBus.Queue(
                        this.scenario, test => new TestPassed(test, summary.Time, output), this.cancellationTokenSource);
                }

                return summary;
            }
        }
示例#10
0
        public async Task <RunSummary> RunAsync()
        {
            OnTestClassStarting();

            var classSummary = new RunSummary();

            if (!MessageBus.QueueMessage(new TestClassStarting(TestCollection, TestClass.Name)))
            {
                CancellationTokenSource.Cancel();
            }
            else
            {
                var orderedTestCases     = TestCaseOrderer.OrderTestCases(TestCases);
                var methodGroups         = orderedTestCases.GroupBy(tc => tc.Method);
                var constructorArguments = CreateTestClassConstructorArguments();

                foreach (var method in methodGroups)
                {
                    var methodSummary = await RunTestMethodAsync(constructorArguments, (IReflectionMethodInfo)method.Key, method);

                    classSummary.Aggregate(methodSummary);

                    if (CancellationTokenSource.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }

            if (!MessageBus.QueueMessage(new TestClassFinished(TestCollection, TestClass.Name, classSummary.Time, classSummary.Total, classSummary.Failed, classSummary.Skipped)))
            {
                CancellationTokenSource.Cancel();
            }

            OnTestClassFinished();

            return(classSummary);
        }
示例#11
0
        protected override async Task<RunSummary> RunTestAsync()
        {
            var dataDiscoveryException = this.GetDataDiscoveryException();
            if (dataDiscoveryException != null)
                return this.RunTest_DataDiscoveryException();

            var runSummary = new RunSummary();
            var testRunners = this.GetTestRunners();

            foreach (var testRunner in testRunners)
                runSummary.Aggregate(await RunTestAsync(testRunner));

            // Run the cleanup here so we can include cleanup time in the run summary,
            // but save any exceptions so we can surface them during the cleanup phase,
            // so they get properly reported as test case cleanup failures.
            var timer = new ExecutionTimer();
            var cleanupAggregator = this.GetCleanupAggregator();
            var toDispose = this.GetToDispose();
            foreach (var disposable in toDispose)
                timer.Aggregate(() => cleanupAggregator.Run(() => disposable.Dispose()));

            runSummary.Time += timer.Total;
            return runSummary;
        }
        private async Task<RunSummary> InvokeStepsAsync(
            ICollection<IStepDefinition> backGroundStepDefinitions, ICollection<IStepDefinition> scenarioStepDefinitions)
        {
            var filters = this.scenarioClass.Assembly.GetCustomAttributes(typeof(Attribute))
                .Concat(this.scenarioClass.GetCustomAttributes(typeof(Attribute)))
                .Concat(this.scenarioMethod.GetCustomAttributes(typeof(Attribute)))
                .OfType<IFilter<IStepDefinition>>();

            var stepDefinitions = filters
                .Aggregate(
                    backGroundStepDefinitions.Concat(scenarioStepDefinitions),
                    (current, filter) => filter.Filter(current))
                .ToArray();

            var summary = new RunSummary();
            string skipReason = null;
            var teardowns = new List<Action>();
            var stepNumber = 0;
            foreach (var stepDefinition in stepDefinitions)
            {
                stepDefinition.SkipReason = stepDefinition.SkipReason ?? skipReason;

                var stepDisplayName = GetStepDisplayName(
                    this.scenario.DisplayName,
                    ++stepNumber,
                    stepNumber <= backGroundStepDefinitions.Count,
                    stepDefinition.Text,
                    this.scenarioMethodArguments);

                var step = new Step(this.scenario, stepDisplayName);

                var interceptingBus = new DelegatingMessageBus(
                    this.messageBus,
                    message =>
                    {
                        if (message is ITestFailed && stepDefinition.FailureBehavior == RemainingSteps.Skip)
                        {
                            skipReason = string.Format(
                                CultureInfo.InvariantCulture,
                                "Failed to execute preceding step: {0}",
                                step.DisplayName);
                        }
                    });

                var stepRunner = new StepRunner(
                    step,
                    stepDefinition.Body,
                    interceptingBus,
                    this.scenarioClass,
                    this.constructorArguments,
                    this.scenarioMethod,
                    this.scenarioMethodArguments,
                    stepDefinition.SkipReason,
                    new ExceptionAggregator(this.aggregator),
                    this.cancellationTokenSource);

                summary.Aggregate(await stepRunner.RunAsync());
                teardowns.AddRange(stepRunner.Disposables.Select(disposable => (Action)disposable.Dispose)
                    .Concat(stepDefinition.Teardowns.Where(teardown => teardown != null)).ToArray());
            }

            if (teardowns.Any())
            {
                teardowns.Reverse();
                var teardownTimer = new ExecutionTimer();
                var teardownAggregator = new ExceptionAggregator();
                foreach (var teardown in teardowns)
                {
                    teardownTimer.Aggregate(() => teardownAggregator.Run(() => teardown()));
                }

                summary.Time += teardownTimer.Total;

                if (teardownAggregator.HasExceptions)
                {
                    summary.Failed++;
                    summary.Total++;

                    var stepDisplayName = GetStepDisplayName(
                        this.scenario.DisplayName,
                        ++stepNumber,
                        false,
                        "(Teardown)",
                        this.scenarioMethodArguments);

                    this.messageBus.Queue(
                        new Step(this.scenario, stepDisplayName),
                        test => new TestFailed(test, teardownTimer.Total, null, teardownAggregator.ToException()),
                        this.cancellationTokenSource);
                }
            }

            return summary;
        }
示例#13
0
        private async Task<RunSummary> RunTestCollectionAsync(IMessageBus messageBus,
                                                              ITestCollection collection,
                                                              IEnumerable<XunitTestCase> testCases,
                                                              ITestCaseOrderer orderer,
                                                              CancellationTokenSource cancellationTokenSource)
        {
            var collectionSummary = new RunSummary();
            var collectionFixtureMappings = new Dictionary<Type, object>();
            var aggregator = new ExceptionAggregator();

            if (collection.CollectionDefinition != null)
            {
                var declarationType = ((IReflectionTypeInfo)collection.CollectionDefinition).Type;
                foreach (var interfaceType in declarationType.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionFixture<>)))
                    CreateFixture(interfaceType, aggregator, collectionFixtureMappings);

                var ordererAttribute = collection.CollectionDefinition.GetCustomAttributes(typeof(TestCaseOrdererAttribute)).SingleOrDefault();
                if (ordererAttribute != null)
                    orderer = GetTestCaseOrderer(ordererAttribute);
            }

            if (messageBus.QueueMessage(new TestCollectionStarting(collection)))
            {
                foreach (var testCasesByClass in testCases.GroupBy(tc => tc.Class))
                {
                    var classSummary = new RunSummary();

                    if (!messageBus.QueueMessage(new TestClassStarting(collection, testCasesByClass.Key.Name)))
                        cancellationTokenSource.Cancel();
                    else
                    {
                        await RunTestClassAsync(messageBus, collection, collectionFixtureMappings, (IReflectionTypeInfo)testCasesByClass.Key, testCasesByClass, orderer, classSummary, aggregator, cancellationTokenSource);
                        collectionSummary.Aggregate(classSummary);
                    }

                    if (!messageBus.QueueMessage(new TestClassFinished(collection, testCasesByClass.Key.Name, classSummary.Time, classSummary.Total, classSummary.Failed, classSummary.Skipped)))
                        cancellationTokenSource.Cancel();

                    if (cancellationTokenSource.IsCancellationRequested)
                        break;
                }
            }

            foreach (var fixture in collectionFixtureMappings.Values.OfType<IDisposable>())
            {
                try
                {
                    fixture.Dispose();
                }
                catch (Exception ex)
                {
                    if (!messageBus.QueueMessage(new ErrorMessage(ex.Unwrap())))
                        cancellationTokenSource.Cancel();
                }
            }

            messageBus.QueueMessage(new TestCollectionFinished(collection, collectionSummary.Time, collectionSummary.Total, collectionSummary.Failed, collectionSummary.Skipped));
            return collectionSummary;
        }
示例#14
0
        /// <inheritdoc/>
        protected override async Task <RunSummary> RunTestAsync()
        {
            var testRunners = new List <XunitTestRunner>();
            var toDispose   = new List <IDisposable>();

            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 = Reflector.GetType(args[1], args[0]);
                    var discoverer     = ExtensibilityPointFactory.GetDataDiscoverer(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 = TypeUtility.ResolveGenericTypes(TestCase.TestMethod.Method, 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 = TypeUtility.GetDisplayNameWithArguments(TestCase.TestMethod.Method, DisplayName, convertedDataRow, resolvedTypes);

                        testRunners.Add(new XunitTestRunner(TestCase, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, theoryDisplayName, SkipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource));
                    }
                }
            }
            catch (Exception ex)
            {
                if (!MessageBus.QueueMessage(new TestStarting(TestCase, DisplayName)))
                {
                    CancellationTokenSource.Cancel();
                }
                else
                {
                    if (!MessageBus.QueueMessage(new TestFailed(TestCase, DisplayName, 0, null, ex.Unwrap())))
                    {
                        CancellationTokenSource.Cancel();
                    }
                }

                if (!MessageBus.QueueMessage(new TestFinished(TestCase, DisplayName, 0, null)))
                {
                    CancellationTokenSource.Cancel();
                }

                return(new RunSummary {
                    Total = 1, Failed = 1
                });
            }

            var runSummary = new RunSummary();

            foreach (var testRunner in testRunners)
            {
                runSummary.Aggregate(await testRunner.RunAsync());
            }

            var timer      = new ExecutionTimer();
            var aggregator = new ExceptionAggregator();

            // REVIEW: What should be done with these leftover errors?

            foreach (var disposable in toDispose)
            {
                timer.Aggregate(() => aggregator.Run(() => disposable.Dispose()));
            }

            runSummary.Time += timer.Total;

            return(runSummary);
        }
 #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
 public override async Task<RunSummary> RunAsync
 #pragma warning restore CS1998
   ( IMessageSink diagnosticMessageSink
   , IMessageBus bus
   , object[] constructorArguments
   , ExceptionAggregator aggregator
   , CancellationTokenSource cancellationTokenSource
   )
 {   var summary = new RunSummary();
     var test = new XunitTest(this, DisplayName);
     if (Inv == null)
     {   var msg = "Return Type must be Invariant.";
         bus.QueueMessage
           ( new TestFailed(test, 0, null, new Exception(msg))
           );
         summary.Aggregate(new RunSummary { Total = 1, Failed = 1 });
         return summary;
     }
     var output = new TestOutputHelper();
     var timer = new ExecutionTimer();
     output.Initialize(bus, test);
     bus.QueueMessage(new TestStarting(test));
     InvariantResult result;
     timer.Aggregate(() => result = Inv.Results(Config(output)).First());
     var xresult = ToXunitResult(test, result, timer.Total);
     bus.QueueMessage(xresult.Item1);
     summary.Aggregate(xresult.Item2);
     return summary;
 }
        /// <inheritdoc/>
        protected override async Task<RunSummary> RunTestAsync()
        {
            var testRunners = new List<XunitTestRunner>();
            var toDispose = new List<IDisposable>();

            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 = Reflector.GetType(args[1], args[0]);
                    var discoverer = ExtensibilityPointFactory.GetDataDiscoverer(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 = TypeUtility.ResolveGenericTypes(TestCase.TestMethod.Method, 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 = TypeUtility.GetDisplayNameWithArguments(TestCase.TestMethod.Method, DisplayName, convertedDataRow, resolvedTypes);
                        var test = new XunitTest(TestCase, theoryDisplayName);

                        testRunners.Add(new XunitTestRunner(test, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, SkipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource));
                    }
                }
            }
            catch (Exception ex)
            {
                var test = new XunitTest(TestCase, DisplayName);

                if (!MessageBus.QueueMessage(new TestStarting(test)))
                    CancellationTokenSource.Cancel();
                else
                {
                    if (!MessageBus.QueueMessage(new TestFailed(test, 0, null, ex.Unwrap())))
                        CancellationTokenSource.Cancel();
                }

                if (!MessageBus.QueueMessage(new TestFinished(test, 0, null)))
                    CancellationTokenSource.Cancel();

                return new RunSummary { Total = 1, Failed = 1 };
            }

            var runSummary = new RunSummary();

            foreach (var testRunner in testRunners)
                runSummary.Aggregate(await testRunner.RunAsync());

            var timer = new ExecutionTimer();
            var aggregator = new ExceptionAggregator();
            // REVIEW: What should be done with these leftover errors?

            foreach (var disposable in toDispose)
                timer.Aggregate(() => aggregator.Run(() => disposable.Dispose()));

            runSummary.Time += timer.Total;

            return runSummary;
        }
示例#17
0
        private RunSummary RunTestCollection(IMessageBus messageBus,
                                             ITestCollection collection,
                                             IEnumerable <XunitTestCase> testCases,
                                             ITestCaseOrderer orderer,
                                             CancellationTokenSource cancellationTokenSource)
        {
            var collectionSummary         = new RunSummary();
            var collectionFixtureMappings = new Dictionary <Type, object>();
            var aggregator = new ExceptionAggregator();

            if (collection.CollectionDefinition != null)
            {
                var declarationType = ((IReflectionTypeInfo)collection.CollectionDefinition).Type;
                foreach (var interfaceType in declarationType.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionFixture <>)))
                {
                    CreateFixture(interfaceType, aggregator, collectionFixtureMappings);
                }

                var ordererAttribute = collection.CollectionDefinition.GetCustomAttributes(typeof(TestCaseOrdererAttribute)).SingleOrDefault();
                if (ordererAttribute != null)
                {
                    orderer = GetTestCaseOrderer(ordererAttribute);
                }
            }

            if (messageBus.QueueMessage(new TestCollectionStarting(collection)))
            {
                foreach (var testCasesByClass in testCases.GroupBy(tc => tc.Class))
                {
                    var classSummary = new RunSummary();

                    if (!messageBus.QueueMessage(new TestClassStarting(collection, testCasesByClass.Key.Name)))
                    {
                        cancellationTokenSource.Cancel();
                    }
                    else
                    {
                        RunTestClass(messageBus, collection, collectionFixtureMappings, (IReflectionTypeInfo)testCasesByClass.Key, testCasesByClass, orderer, classSummary, aggregator, cancellationTokenSource);
                        collectionSummary.Aggregate(classSummary);
                    }

                    if (!messageBus.QueueMessage(new TestClassFinished(collection, testCasesByClass.Key.Name, classSummary.Time, classSummary.Total, classSummary.Failed, classSummary.Skipped)))
                    {
                        cancellationTokenSource.Cancel();
                    }

                    if (cancellationTokenSource.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }

            foreach (var fixture in collectionFixtureMappings.Values.OfType <IDisposable>())
            {
                try
                {
                    fixture.Dispose();
                }
                catch (Exception ex)
                {
                    if (!messageBus.QueueMessage(new ErrorMessage(ex.Unwrap())))
                    {
                        cancellationTokenSource.Cancel();
                    }
                }
            }

            messageBus.QueueMessage(new TestCollectionFinished(collection, collectionSummary.Time, collectionSummary.Total, collectionSummary.Failed, collectionSummary.Skipped));
            return(collectionSummary);
        }
        protected override async Task<RunSummary> RunTestAsync()
        {
            if (this.dataDiscoveryException != null)
            {
                this.MessageBus.Queue(
                    new XunitTest(this.TestCase, this.DisplayName),
                    test => new TestFailed(test, 0, null, this.dataDiscoveryException.Unwrap()),
                    this.CancellationTokenSource);

                return new RunSummary { Total = 1, Failed = 1 };
            }

            var summary = new RunSummary();
            foreach (var scenarioRunner in this.scenarioRunners)
            {
                summary.Aggregate(await scenarioRunner.RunAsync());
            }

            // Run the cleanup here so we can include cleanup time in the run summary,
            // but save any exceptions so we can surface them during the cleanup phase,
            // so they get properly reported as test case cleanup failures.
            var timer = new ExecutionTimer();
            foreach (var disposable in this.disposables)
            {
                timer.Aggregate(() => this.cleanupAggregator.Run(() => disposable.Dispose()));
            }

            summary.Time += timer.Total;
            return summary;
        }
        private async Task<RunSummary> InvokeScenarioMethodAsync(object scenarioClassInstance)
        {
            var backgroundStepDefinitions = new List<IStepDefinition>();
            var scenarioStepDefinitions = new List<IStepDefinition>();
            await this.aggregator.RunAsync(async () =>
            {
                try
                {
                    foreach (
                        var backgroundMethod in
                            this.scenario.TestCase.TestMethod.Method.Type.GetMethods(false)
                                .Where(candidate => candidate.GetCustomAttributes(typeof(BackgroundAttribute)).Any())
                                .Select(method => method.ToRuntimeMethod()))
                    {
                        await this.timer.AggregateAsync(() => backgroundMethod.InvokeAsync(scenarioClassInstance, null));
                    }

                    backgroundStepDefinitions.AddRange(CurrentThread.StepDefinitions);
                }
                catch (Exception ex)
                {
                    
                }
                finally
                {
                    CurrentThread.StepDefinitions.Clear();
                }

                try
                {
                    await this.timer.AggregateAsync(() =>
                        this.scenarioMethod.InvokeAsync(scenarioClassInstance, this.scenarioMethodArguments));

                    scenarioStepDefinitions.AddRange(CurrentThread.StepDefinitions);
                }
                finally
                {
                    CurrentThread.StepDefinitions.Clear();
                }
            });

            var runSummary = new RunSummary { Time = this.timer.Total };
            if (!this.aggregator.HasExceptions)
            {
                runSummary.Aggregate(await this.InvokeStepsAsync(backgroundStepDefinitions, scenarioStepDefinitions));
            }

            return runSummary;
        }