예제 #1
0
 /// <summary>
 /// Adds a run summary's totals into this run summary.
 /// </summary>
 /// <param name="other">The run summary to be added.</param>
 public void Aggregate(RunSummary other)
 {
     Total += other.Total;
     Failed += other.Failed;
     Skipped += other.Skipped;
     Time += other.Time;
 }
        protected static void DisplayTestResults(RunSummary summary)
        {
            var caller =
                new StackTrace().GetFrames()
                    .First(f => typeof(NServiceBusPerformanceTest).IsAssignableFrom(f.GetMethod().DeclaringType.BaseType));

            var testCategory =
                caller.GetMethod()
                    .DeclaringType.Namespace.Replace(typeof(NServiceBusPerformanceTest).Namespace + ".", "");
            var testCase = caller.GetMethod().Name;

            var c = (PerformanceTestContext)summary.RunDescriptor.ScenarioContext;

            var messagesPerSecondsProcessed = c.NumberOfTestMessages/
                                              (c.LastMessageProcessedAt - c.FirstMessageProcessedAt).TotalSeconds;

            Console.Out.WriteLine("Results: {0} messages, {1} msg/s", c.NumberOfTestMessages,
                messagesPerSecondsProcessed);

            using (var file = new StreamWriter(".\\PerformanceTestResults.txt", true))
            {
                file.WriteLine(string.Join(";", summary.RunDescriptor.Key, testCategory, testCase,
                    c.NumberOfTestMessages, messagesPerSecondsProcessed));
            }

            Console.Out.WriteLine("##teamcity[buildStatisticValue key='{0}' value='{1:0}']",
                summary.RunDescriptor.Key + "." + testCategory + "." + testCase, messagesPerSecondsProcessed);
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TestClassCallbackHandler" /> class.
        /// </summary>
        /// <param name="testCases">The test cases that are being run.</param>
        /// <param name="messageSink">The message sink to call with the translated results.</param>
        public TestClassCallbackHandler(IList<Xunit1TestCase> testCases, IMessageSink messageSink)
            : base(lastNodeName: "class")
        {
            this.handlers = new Dictionary<string, Predicate<XmlNode>> { { "class", OnClass }, { "start", OnStart }, { "test", OnTest } };
            this.messageSink = messageSink;
            this.testCases = testCases;
            this.testCaseResults = new RunSummary();

            TestClassResults = new RunSummary();
        }
        /// <summary>
        /// Invokes the Steps given Background, Scenario, and TearDown steps.
        /// </summary>
        /// <param name="backgroundSteps"></param>
        /// <param name="scenarioSteps"></param>
        /// <param name="tearDownSteps"></param>
        /// <returns></returns>
        private async Task <RunSummary> InvokeStepsAsync(ICollection <IStepDefinition> backgroundSteps
                                                         , ICollection <IStepDefinition> scenarioSteps, ICollection <IStepDefinition> tearDownSteps)
        {
            var scenarioTypeInfo = this._scenarioClass.GetTypeInfo();
            var filters          = scenarioTypeInfo.Assembly.GetCustomAttributes(typeof(Attribute))
                                   .Concat(scenarioTypeInfo.GetCustomAttributes(typeof(Attribute)))
                                   .Concat(this._scenarioMethod.GetCustomAttributes(typeof(Attribute)))
                                   .OfType <IFilter <IStepDefinition> >();

            var    summary           = new RunSummary();
            string skipReason        = null;
            var    scenarioRollbacks = new List <(StepContext context, Func <IStepContext, Task> callback)>();
            var    stepNumber        = 0;

            foreach (var stepDefinition in filters.Aggregate(backgroundSteps.Concat(scenarioSteps).Concat(tearDownSteps)
                                                             , (current, filter) => filter.Filter(current)))
            {
                stepDefinition.SkipReason = stepDefinition.SkipReason ?? skipReason;

                var stepDisplayName = GetStepDisplayName(this._scenario.DisplayName
                                                         , ++stepNumber
                                                         , stepDefinition.OnDisplayText?.Invoke(
                                                             stepDefinition.Text, stepDefinition.StepDefinitionType)
                                                         );

                var step = new StepTest(this._scenario, stepDisplayName);

                // #1 MWP 2020-07-01 11:56:45 AM: After testing, this should be fine, and better behaved we think.
                using (var interceptingBus = new DelegatingMessageBus(
                           this._messageBus
                           , message =>
                {
                    if (message is ITestFailed && stepDefinition.FailureBehavior == RemainingSteps.Skip)
                    {
                        skipReason = $"Failed to execute preceding step: {step.DisplayName}";
                    }
                })
                       )
                {
                    var stepContext = new StepContext(step);

                    // TODO: TBD: #1 MWP 2020-07-01 11:57:26 AM: it is an xUnit thing, could possibly be IDisposable itself...
                    // TODO: TBD: including assumed ownership of the IDisposable messageBus, for instance, TODO: TBD: but that is outside the scope of xWellBehaved...
                    var stepRunner = new StepTestRunner(
                        stepContext
                        , stepDefinition.Body
                        , step
                        , interceptingBus
                        , this._scenarioClass
                        , this._constructorArguments
                        , this._scenarioMethod
                        , this._scenarioMethodArguments
                        , stepDefinition.SkipReason
                        , Array.Empty <BeforeAfterTestAttribute>()
                        , new ExceptionAggregator(this._aggregator)
                        , this._cancellationTokenSource);

                    summary.Aggregate(await stepRunner.RunAsync());

                    // TODO: TBD: could we use disposable?.Dispose() here?
                    var stepRollbacks = stepContext.Disposables
                                        .Where(disposable => disposable != null)
                                        .Select((Func <IDisposable, Func <IStepContext, Task> >)(disposable => context =>
                    {
                        disposable.Dispose();
                        return(Task.FromResult(0));
                    }))
                                        .Concat(stepDefinition.Rollbacks)
                                        .Where(onRollback => onRollback != null)
                                        .Select(onRollback => (stepContext, onRollback));

                    scenarioRollbacks.AddRange(stepRollbacks);
                }
            }

            if (scenarioRollbacks.Any())
            {
                scenarioRollbacks.Reverse();
                var rollbackTimer      = new ExecutionTimer();
                var rollbackAggregator = new ExceptionAggregator();

                // "Teardowns" not to be confused with TearDown versus Background.
                foreach (var(context, onRollback) in scenarioRollbacks)
                {
                    await Invoker.Invoke(() => onRollback.Invoke(context), rollbackAggregator, rollbackTimer);
                }

                summary.Time += rollbackTimer.Total;

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

                    var stepDisplayName = GetStepDisplayName(this._scenario.DisplayName, ++stepNumber, $"({StepType.Rollback})");

                    this._messageBus.Queue(new StepTest(this._scenario, stepDisplayName)
                                           , test => new TestFailed(test, rollbackTimer.Total, null, rollbackAggregator.ToException())
                                           , this._cancellationTokenSource);
                }
            }

            return(summary);
        }
예제 #5
0
 public void Parse(RunSummary runSummary)
 {
     _runSummary = runSummary;
 }
        private RunSummary RunNBenchTest(object testClassInstance)
        {
            //TODO: It is not strictly required to use a RunSummary at the moment - needs more investigation to see
            //if we can provide more useful information via the standard xUnit mechanism. For now, what we have is sufficient.
            var summary = new RunSummary();

            var discovery = new ReflectionDiscovery(new ActionBenchmarkOutput(report => { }, results =>
            {
                if (results.Data.Exceptions.Any())
                {
                    throw new AggregateException(results.Data.Exceptions);
                }

                WriteTestOutput("");

                if (results.AssertionResults.Count > 0)
                {
                    //TODO: We should determine the accurate elapsed time at this point, to report it in the xUnit runner.
                    summary.Time = (decimal)results.Data.StatsByMetric.Values.First().Runs.First().ElapsedSeconds;

                    foreach (var assertion in results.AssertionResults)
                    {
                        //TODO: Maybe it is bubble to bubble this up, and provide the original line number?
                        Assert.True(assertion.Passed, assertion.Message);

                        summary.Total++;
                        if (!assertion.Passed)
                        {
                            summary.Failed++;
                        }
                        WriteTestOutput(assertion.Message);
                        WriteTestOutput("");
                    }
                }
                else
                {
                    WriteTestOutput("No assertions returned.");
                }

                WriteTestOutput("");
                WriteTestOutput("---------- Measurements ----------");
                WriteTestOutput("");

                if (results.Data.StatsByMetric.Count > 0)
                {
                    foreach (var measurement in results.Data.StatsByMetric)
                    {
                        WriteTestOutput("Metric : " + measurement.Key.ToHumanFriendlyString());
                        WriteTestOutput("");
                        WriteTestOutput($"Per Second ( {measurement.Value.Unit} )");

                        WriteTestOutput($"Average         : {measurement.Value.PerSecondStats.Average}");
                        WriteTestOutput($"Max             : {measurement.Value.PerSecondStats.Max}");
                        WriteTestOutput($"Min             : {measurement.Value.PerSecondStats.Min}");
                        WriteTestOutput($"Std. Deviation  : {measurement.Value.PerSecondStats.StandardDeviation}");
                        WriteTestOutput($"Std. Error      : {measurement.Value.PerSecondStats.StandardError}");
                        WriteTestOutput("");

                        WriteTestOutput($"Per Test ( {measurement.Value.Unit} )");
                        WriteTestOutput($"Average         : {measurement.Value.Stats.Average}");
                        WriteTestOutput($"Max             : {measurement.Value.Stats.Max}");
                        WriteTestOutput($"Min             : {measurement.Value.Stats.Min}");
                        WriteTestOutput($"Std. Deviation  : {measurement.Value.Stats.StandardDeviation}");
                        WriteTestOutput($"Std. Error      : {measurement.Value.Stats.StandardError}");

                        WriteTestOutput("");
                        WriteTestOutput("----------");
                        WriteTestOutput("");
                    }
                }
                else
                {
                    WriteTestOutput("No measurements returned.");
                }
            }));

            var testClassType = TestClass;

            //TODO: At the moment this is performing work that is not required, but is pragmatic in that a change is not required to the NBench core.
            var benchmarkMetaData = ReflectionDiscovery.CreateBenchmarksForClass(testClassType).First(b => b.Run.InvocationMethod.Name == TestMethod.Name);

            try
            {
                var invoker =
                    new XUnitReflectionBenchmarkInvoker(benchmarkMetaData, testClassInstance, TestMethodArguments);

                var settings  = discovery.CreateSettingsForBenchmark(benchmarkMetaData);
                var benchmark = new Benchmark(settings, invoker, discovery.Output, discovery.BenchmarkAssertions);

                Benchmark.PrepareForRun();
                benchmark.Run();
                benchmark.Finish();
            }
            catch (ReflectionTypeLoadException ex)
            {
                foreach (var e in ex.LoaderExceptions)
                {
                    WriteTestOutput(e.ToString());
                }

                throw;
            }

            return(summary);
        }
예제 #7
0
        TestableTestCaseRunner(ITestCase testCase, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource tokenSource, RunSummary result)
            : base(testCase, messageBus, aggregator, tokenSource)
        {
            this.result = result;

            TestCase    = testCase;
            TokenSource = tokenSource;
        }
예제 #8
0
        /// <summary>
        /// Gets the hash code
        /// </summary>
        /// <returns>Hash code</returns>
        public override int GetHashCode()
        {
            unchecked // Overflow is fine, just wrap
            {
                var hashCode = 41;
                // Suitable nullity checks etc, of course :)
                if (Class != null)
                {
                    hashCode = hashCode * 59 + Class.GetHashCode();
                }
                if (Links != null)
                {
                    hashCode = hashCode * 59 + Links.GetHashCode();
                }

                hashCode = hashCode * 59 + DurationInMillis.GetHashCode();
                if (EnQueueTime != null)
                {
                    hashCode = hashCode * 59 + EnQueueTime.GetHashCode();
                }
                if (EndTime != null)
                {
                    hashCode = hashCode * 59 + EndTime.GetHashCode();
                }

                hashCode = hashCode * 59 + EstimatedDurationInMillis.GetHashCode();
                if (Id != null)
                {
                    hashCode = hashCode * 59 + Id.GetHashCode();
                }
                if (Organization != null)
                {
                    hashCode = hashCode * 59 + Organization.GetHashCode();
                }
                if (Pipeline != null)
                {
                    hashCode = hashCode * 59 + Pipeline.GetHashCode();
                }
                if (Result != null)
                {
                    hashCode = hashCode * 59 + Result.GetHashCode();
                }
                if (RunSummary != null)
                {
                    hashCode = hashCode * 59 + RunSummary.GetHashCode();
                }
                if (StartTime != null)
                {
                    hashCode = hashCode * 59 + StartTime.GetHashCode();
                }
                if (State != null)
                {
                    hashCode = hashCode * 59 + State.GetHashCode();
                }
                if (Type != null)
                {
                    hashCode = hashCode * 59 + Type.GetHashCode();
                }
                if (CommitId != null)
                {
                    hashCode = hashCode * 59 + CommitId.GetHashCode();
                }
                return(hashCode);
            }
        }
예제 #9
0
 public virtual Task DisposeAsync(RunSummary result, IMessageBus messageBus) => Task.CompletedTask;
예제 #10
0
        private static async Task <RunSummary> RunTestAsyncCore(XunitTestRunner runner,
                                                                IMessageBus messageBus,
                                                                ExceptionAggregator aggregator)
        {
            try
            {
                DelayedMessageBus delayedMessageBus = null;
                RunSummary        summary           = null;

                // First run
                if (!KuduUtils.DisableRetry)
                {
                    // This is really the only tricky bit: we need to capture and delay messages (since those will
                    // contain run status) until we know we've decided to accept the final result;
                    delayedMessageBus = new DelayedMessageBus(messageBus);

                    runner.SetMessageBus(delayedMessageBus);
                    summary = await RunTestInternalAsync(runner);

                    if (delayedMessageBus.TestSkipped)
                    {
                        summary.Failed  -= 1;
                        summary.Skipped += 1;
                    }

                    // if succeeded
                    if (summary.Failed == 0 || aggregator.HasExceptions)
                    {
                        delayedMessageBus.Flush(false);
                        return(summary);
                    }
                }

                // Final run
                var kuduMessageBus = new KuduTraceMessageBus(messageBus);
                runner.SetMessageBus(kuduMessageBus);
                summary = await RunTestInternalAsync(runner);

                if (kuduMessageBus.TestSkipped)
                {
                    summary.Failed  -= 1;
                    summary.Skipped += 1;
                }

                // flush delay messages
                if (delayedMessageBus != null)
                {
                    delayedMessageBus.Flush(summary.Failed == 0 && !aggregator.HasExceptions);
                }

                return(summary);
            }
            catch (Exception ex)
            {
                // this is catastrophic
                messageBus.QueueMessage(new TestFailed(runner.GetTest(), 0, null, ex));

                return(new RunSummary {
                    Failed = 1, Total = 1
                });
            }
            finally
            {
                // set to original
                runner.SetMessageBus(messageBus);
            }
        }
        public async Task <RunSummary> Run()
        {
            var        runCount = 1;
            RunSummary summary  = new RunSummary();

            var test   = (ITest) new XunitTest(this.TestCase, this.DisplayName);
            var output = string.Empty;

            while (runCount <= _runCount)
            {
                await this.AfterTestCaseStartingAsync();

                summary = new RunSummary()
                {
                    Total = 1
                };

                this.Aggregator = new ExceptionAggregator(Aggregator);
                var customerRunner = new XunitCustomRunner(test, this.MessageBus, this.TestClass, this.ConstructorArguments, TestMethod, TestMethodArguments, SkipReason, BeforeAfterAttributes, this.Aggregator, CancellationTokenSource);
                output = await customerRunner.RunAsync(summary);

                await this.BeforeTestCaseFinishedAsync();

                var exception = this.Aggregator.ToException();

                if (exception == null)
                {
                    var testResultMessage = (TestResultMessage) new TestPassed(test, summary.Time, output);
                    if (!this.CancellationTokenSource.IsCancellationRequested && !this.MessageBus.QueueMessage((IMessageSinkMessage)testResultMessage))
                    {
                        this.CancellationTokenSource.Cancel();
                    }
                    break;
                }

                if (exception.GetType() == _exceptionToIgnoreTest)
                {
                    SkipReason = exception.Message;
                    var testResultMessage = (TestResultMessage) new TestSkipped(test, SkipReason);
                    if (!this.CancellationTokenSource.IsCancellationRequested && !this.MessageBus.QueueMessage((IMessageSinkMessage)testResultMessage))
                    {
                        this.CancellationTokenSource.Cancel();
                    }
                    break;
                }

                runCount++;
            }

            if (this.Aggregator.HasExceptions)
            {
                var ex         = this.Aggregator.ToException();
                var testResult = (TestResultMessage) new TestFailed(test, summary.Time, output, ex);
                ++summary.Failed;

                if (!this.CancellationTokenSource.IsCancellationRequested && !this.MessageBus.QueueMessage((IMessageSinkMessage)testResult))
                {
                    this.CancellationTokenSource.Cancel();
                }
            }

            if (!this.MessageBus.QueueMessage((IMessageSinkMessage) new TestCaseFinished((ITestCase)this.TestCase, summary.Time, summary.Total, summary.Failed, summary.Skipped)))
            {
                this.CancellationTokenSource.Cancel();
            }

            return(summary);
        }
예제 #12
0
            public override async Task <RunSummary> RunAsync(IMessageSink diagnosticMessageSink, IMessageBus messageBus, object[] constructorArguments, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource)
            {
                var runSummary = new RunSummary();

                if (this.SkipReason != null)
                {
                    runSummary.Skipped++;
                    runSummary.Total++;
                    if (!messageBus.QueueMessage(new TestSkipped(new XunitTest(this, this.DisplayName), this.SkipReason)))
                    {
                        cancellationTokenSource.Cancel();
                    }

                    return(runSummary);
                }

                if (this.parts == null && this.assemblies == null)
                {
                    this.parts = GetNestedTypesRecursively(this.TestMethod.TestClass.Class.ToRuntimeType()).Where(t => (!t.GetTypeInfo().IsAbstract || t.GetTypeInfo().IsSealed) && !t.GetTypeInfo().IsInterface).ToArray();
                }

#if DESKTOP
                if (this.compositionVersions.HasFlag(CompositionEngines.V1))
                {
                    var runner = new LegacyMefTestCaseRunner(this, "V1", null, constructorArguments, messageBus, aggregator, cancellationTokenSource, CompositionEngines.V1, this.parts, this.assemblies, this.invalidConfiguration);
                    runSummary.Aggregate(await runner.RunAsync());
                }
#endif

                if (this.compositionVersions.HasFlag(CompositionEngines.V2))
                {
                    var runner = new LegacyMefTestCaseRunner(this, "V2", null, constructorArguments, messageBus, aggregator, cancellationTokenSource, CompositionEngines.V2, this.parts, this.assemblies, this.invalidConfiguration);
                    runSummary.Aggregate(await runner.RunAsync());
                }

                if ((this.compositionVersions & CompositionEngines.V3EnginesMask) == CompositionEngines.Unspecified)
                {
                    if (!this.noCompatGoal)
                    {
                        // Call out that we're *not* testing V3 functionality for this test.
                        if (!messageBus.QueueMessage(new TestSkipped(new XunitTest(this, "V3"), "Test does not include V3 test.")))
                        {
                            cancellationTokenSource.Cancel();
                        }
                    }
                }
                else
                {
                    var v3DiscoveryTest = new Mef3DiscoveryTestCaseRunner(this, "V3 composition", null, constructorArguments, messageBus, aggregator, cancellationTokenSource, this.compositionVersions, this.parts ?? new Type[0], this.assemblies ?? ImmutableList <string> .Empty, this.invalidConfiguration);
                    runSummary.Aggregate(await v3DiscoveryTest.RunAsync());

                    if (v3DiscoveryTest.Passed && (!this.invalidConfiguration || this.compositionVersions.HasFlag(CompositionEngines.V3AllowConfigurationWithErrors)))
                    {
                        foreach (var namedConfiguration in v3DiscoveryTest.ResultingConfigurations)
                        {
                            string name = "V3 engine";
                            if (!string.IsNullOrEmpty(namedConfiguration.Description))
                            {
                                name += $"({namedConfiguration.Description})";
                            }

                            var runner = new Mef3TestCaseRunner(this, name, null, constructorArguments, messageBus, aggregator, cancellationTokenSource, namedConfiguration.Configuration, this.compositionVersions);
                            runSummary.Aggregate(await runner.RunAsync());
                        }
                    }
                }

                return(runSummary);
            }
예제 #13
0
        public static async Task <RunSummary> RunTestAsync(XunitTestRunner runner,
                                                           IMessageBus messageBus,
                                                           ExceptionAggregator aggregator,
                                                           bool disableRetry)
        {
            // defense in depth to avoid forever lock
            bool acquired = await _semaphore.WaitAsync(TimeSpan.FromHours(2));

            try
            {
                DelayedMessageBus delayedMessageBus = null;
                RunSummary        summary           = null;

                if (!acquired)
                {
                    throw new TimeoutException("Wait for thread to run the test timeout!");
                }

                // First run
                if (!disableRetry)
                {
                    // This is really the only tricky bit: we need to capture and delay messages (since those will
                    // contain run status) until we know we've decided to accept the final result;
                    delayedMessageBus = new DelayedMessageBus(messageBus);

                    runner.SetMessageBus(delayedMessageBus);
                    summary = await RunTestInternalAsync(runner);

                    // if succeeded
                    if (summary.Failed == 0 || aggregator.HasExceptions)
                    {
                        delayedMessageBus.Flush(false);
                        return(summary);
                    }
                }

                // Final run
                runner.SetMessageBus(new KuduTraceMessageBus(messageBus));
                summary = await RunTestInternalAsync(runner);

                // flush delay messages
                if (delayedMessageBus != null)
                {
                    delayedMessageBus.Flush(summary.Failed == 0 && !aggregator.HasExceptions);
                }

                return(summary);
            }
            catch (Exception ex)
            {
                // this is catastrophic
                messageBus.QueueMessage(new TestFailed(runner.GetTest(), 0, null, ex));

                return(new RunSummary {
                    Failed = 1, Total = 1
                });
            }
            finally
            {
                if (acquired)
                {
                    _semaphore.Release();
                }

                // set to original
                runner.SetMessageBus(messageBus);
            }
        }
예제 #14
0
        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);
        }
예제 #15
0
        async Task DoCorrelation()
        {
            var outputs = getOutputs();

            var usedRoleInstanceNames = new HashSet <string>();

            string getUniqueRoleInstanceName(ILogSource logSource)
            {
                for (int tryCount = 0; ; ++tryCount)
                {
                    var ret = string.Format(
                        tryCount == 0 ? "{0}" : "{0} ({1})",
                        logSource.GetShortDisplayNameWithAnnotation(),
                        tryCount
                        );
                    if (usedRoleInstanceNames.Add(ret))
                    {
                        return(ret);
                    }
                }
            }

            NodeId makeNodeId(ILogSource logSource) =>
            new NodeId(logSource.Provider.Factory.ToString(), getUniqueRoleInstanceName(logSource));

            var allLogs =
                outputs
                .Select(output => output.OutputData)
                .OfType <ICorrelatorOutput>()
                .Select(data => new NodeInfo(data.LogSource, makeNodeId(data.LogSource), data.RotatedLogPartToken, data.Events, data.SameNodeDetectionToken))
                .ToArray();

            var fixedConstraints =
                allLogs
                .GroupBy(l => l.SameNodeDetectionToken, new SameNodeEqualityComparer())
                .SelectMany(group => LinqUtils.ZipWithNext(group).Select(pair => new FixedConstraint()
            {
                Node1 = pair.Key.NodeId,
                Node2 = pair.Value.NodeId,
                Value = pair.Value.SameNodeDetectionToken.DetectSameNode(pair.Key.SameNodeDetectionToken).TimeDiff
            }))
                .ToList();

            ICorrelator correlator = new Correlator(new InternodeMessagesDetector(), solverFactory());

            var allowInstacesMergingForRoles = new HashSet <string>();
            var correlatorSolution           = await correlator.Correlate(
                allLogs.ToDictionary(i => i.NodeId, i => i.Messages),
                fixedConstraints,
                allowInstacesMergingForRoles
                );

            var nodeIdToLogSources =
                (from l in allLogs
                 from ls in l.LogSources
                 select new { L = l.NodeId, Ls = ls })
                .ToLookup(i => i.L, i => i.Ls);

            var grouppedLogsReport = new StringBuilder();

            foreach (var group in allLogs.Where(g => g.LogSources.Length > 1))
            {
                if (grouppedLogsReport.Length == 0)
                {
                    grouppedLogsReport.AppendLine();
                    grouppedLogsReport.AppendLine("Groupped logs info:");
                }
                grouppedLogsReport.AppendLine(string.Format(
                                                  "  - {0} were groupped to represent node {1}",
                                                  string.Join(", ", group.LogSources.Select(ls => '\"' + ls.GetShortDisplayNameWithAnnotation() + '\"')),
                                                  group.NodeId));
            }

            var timeOffsets =
                (from ns in correlatorSolution.NodeSolutions
                 from ls in nodeIdToLogSources[ns.Key]
                 select new { Sln = ns.Value, Ls = ls })
                .ToImmutableDictionary(i => i.Ls, i => i.Sln);

            await modelThreadSync.Invoke(() =>
            {
                foreach (var ls in logSourcesManager.Items)
                {
                    if (timeOffsets.TryGetValue(ls, out var sln))
                    {
                        ITimeOffsetsBuilder builder = logSourcesManager.CreateTimeOffsetsBuilder();
                        builder.SetBaseOffset(sln.BaseDelta);
                        if (sln.TimeDeltas != null)
                        {
                            foreach (var d in sln.TimeDeltas)
                            {
                                builder.AddOffset(d.At, d.Delta);
                            }
                        }
                        ls.TimeOffsets = builder.ToTimeOffsets();
                    }
                }
            });

            logConnectionIdToLastRunResult = timeOffsets.ToImmutableDictionary(
                to => to.Key.GetSafeConnectionId(),
                to => new CorrelatorRunResult(to.Value, GetCorrelatableLogsConnectionIds(outputs))
                );
            lastRunSummary = new RunSummary {
                Report = correlatorSolution.CorrelationLog + grouppedLogsReport
            };

            changeNotification.Post();
        }
예제 #16
0
        static CorrelationStateSummary GetCorrelatorStateSummary(
            ImmutableArray <LogSourcePostprocessorState> correlationOutputs,
            ImmutableDictionary <string, CorrelatorRunResult> lastResult,
            RunSummary lastRunSummary,
            int _timeShiftsRevision
            )
        {
            if (correlationOutputs.Length < 2)
            {
                return(new CorrelationStateSummary {
                    Status = CorrelationStateSummary.StatusCode.PostprocessingUnavailable
                });
            }
            if (lastRunSummary?.IsFailure == true)
            {
                return(new CorrelationStateSummary {
                    Status = CorrelationStateSummary.StatusCode.ProcessingFailed, Report = lastRunSummary.Report
                });
            }
            var    correlatableLogsIds             = GetCorrelatableLogsConnectionIds(correlationOutputs);
            int    numMissingOutput                = 0;
            int    numProgressing                  = 0;
            int    numFailed                       = 0;
            int    numCorrelationContextMismatches = 0;
            int    numCorrelationResultMismatches  = 0;
            double?progress = null;

            foreach (var i in correlationOutputs)
            {
                if (i.OutputStatus == LogSourcePostprocessorState.Status.InProgress ||
                    i.OutputStatus == LogSourcePostprocessorState.Status.Loading)
                {
                    numProgressing++;
                    if (progress == null && i.Progress != null)
                    {
                        progress = i.Progress;
                    }
                }
                lastResult.TryGetValue(i.LogSource.GetSafeConnectionId(), out var typedOutput);
                if (typedOutput == null)
                {
                    ++numMissingOutput;
                }
                else
                {
                    if (!typedOutput.CorrelatedLogsConnectionIds.IsSupersetOf(correlatableLogsIds))
                    {
                        ++numCorrelationContextMismatches;
                    }
                    var actualOffsets = i.LogSource.IsDisposed ? TimeOffsets.Empty : i.LogSource.Provider.TimeOffsets;
                    if (typedOutput.Solution.BaseDelta != actualOffsets.BaseOffset)
                    {
                        ++numCorrelationResultMismatches;
                    }
                }
                if (i.OutputStatus == LogSourcePostprocessorState.Status.Failed)
                {
                    ++numFailed;
                }
            }
            if (numProgressing != 0)
            {
                return(new CorrelationStateSummary()
                {
                    Status = CorrelationStateSummary.StatusCode.ProcessingInProgress,
                    Progress = progress
                });
            }
            string report = lastRunSummary?.Report;

            if (numFailed != 0)
            {
                IPostprocessorRunSummary summaryWithError = correlationOutputs
                                                            .Select(output => output.LastRunSummary)
                                                            .OfType <IPostprocessorRunSummary>()
                                                            .Where(summary => summary.HasErrors)
                                                            .FirstOrDefault();
                if (summaryWithError != null)
                {
                    return(new CorrelationStateSummary()
                    {
                        Status = CorrelationStateSummary.StatusCode.ProcessingFailed,
                        Report = summaryWithError.Report
                    });
                }
                return(new CorrelationStateSummary()
                {
                    Status = CorrelationStateSummary.StatusCode.ProcessingFailed,
                    Report = report
                });
            }
            if (numMissingOutput != 0 || numCorrelationContextMismatches != 0 || numCorrelationResultMismatches != 0)
            {
                return(new CorrelationStateSummary()
                {
                    Status = CorrelationStateSummary.StatusCode.NeedsProcessing
                });
            }
            return(new CorrelationStateSummary()
            {
                Status = CorrelationStateSummary.StatusCode.Processed,
                Report = report
            });
        }
예제 #17
0
파일: Xunit1.cs 프로젝트: JayBazuzi/xunit
        /// <inheritdoc/>
        public void Run(IEnumerable<ITestCase> testCases, IMessageSink messageSink)
        {
            var results = new RunSummary();
            var environment = String.Format("{0}-bit .NET {1}", IntPtr.Size * 8, Environment.Version);

            // TODO: Contract for Run() states that null "testCases" means "run everything".

            if (messageSink.OnMessage(new TestAssemblyStarting(assemblyFileName, configFileName, DateTime.Now, environment, TestFrameworkDisplayName)))
                foreach (var testCollectionGroup in testCases.Cast<Xunit1TestCase>().GroupBy(tc => tc.TestCollection))
                {
                    var collectionResults = RunTestCollection(testCollectionGroup.Key, testCollectionGroup, messageSink);
                    results.Aggregate(collectionResults);
                    if (!collectionResults.Continue)
                        break;
                }

            messageSink.OnMessage(new TestAssemblyFinished(new Xunit1AssemblyInfo(assemblyFileName), results.Time, results.Total, results.Failed, results.Skipped));
        }
예제 #18
0
    /// <summary>
    /// Runs the tests in the test method.
    /// </summary>
    /// <param name="ctxt">The context that describes the current test method</param>
    /// <returns>Returns summary information about the tests that were run.</returns>
    protected async ValueTask <RunSummary> RunAsync(TContext ctxt)
    {
        await ctxt.InitializeAsync();

        try
        {
            SetTestContext(ctxt, TestEngineStatus.Initializing);

            var methodSummary          = new RunSummary();
            var testCollection         = ctxt.TestCases.First().TestCollection;
            var testAssemblyUniqueID   = testCollection.TestAssembly.UniqueID;
            var testCollectionUniqueID = testCollection.UniqueID;
            var testClassUniqueID      = ctxt.TestClass.UniqueID;
            var testMethodUniqueID     = ctxt.TestMethod.UniqueID;

            var methodStarting = new _TestMethodStarting
            {
                AssemblyUniqueID       = testAssemblyUniqueID,
                TestClassUniqueID      = testClassUniqueID,
                TestCollectionUniqueID = testCollectionUniqueID,
                TestMethod             = ctxt.TestMethod.Method.Name,
                TestMethodUniqueID     = testMethodUniqueID
            };

            if (!ctxt.MessageBus.QueueMessage(methodStarting))
            {
                ctxt.CancellationTokenSource.Cancel();
                return(methodSummary);
            }

            try
            {
                await AfterTestMethodStarting(ctxt);

                SetTestContext(ctxt, TestEngineStatus.Running);

                methodSummary = await RunTestCasesAsync(ctxt);

                SetTestContext(ctxt, TestEngineStatus.CleaningUp);

                ctxt.Aggregator.Clear();
                await BeforeTestMethodFinished(ctxt);

                if (ctxt.Aggregator.HasExceptions)
                {
                    var methodCleanupFailure = _TestMethodCleanupFailure.FromException(ctxt.Aggregator.ToException() !, testAssemblyUniqueID, testCollectionUniqueID, testClassUniqueID, testMethodUniqueID);
                    if (!ctxt.MessageBus.QueueMessage(methodCleanupFailure))
                    {
                        ctxt.CancellationTokenSource.Cancel();
                    }
                }

                return(methodSummary);
            }
            finally
            {
                var testMethodFinished = new _TestMethodFinished
                {
                    AssemblyUniqueID       = testAssemblyUniqueID,
                    ExecutionTime          = methodSummary.Time,
                    TestClassUniqueID      = testClassUniqueID,
                    TestCollectionUniqueID = testCollectionUniqueID,
                    TestMethodUniqueID     = testMethodUniqueID,
                    TestsFailed            = methodSummary.Failed,
                    TestsRun     = methodSummary.Total,
                    TestsSkipped = methodSummary.Skipped
                };

                if (!ctxt.MessageBus.QueueMessage(testMethodFinished))
                {
                    ctxt.CancellationTokenSource.Cancel();
                }
            }
        }
        finally
        {
            await ctxt.DisposeAsync();
        }
    }
예제 #19
0
 private static void GenerateProcessingErrorsSection(StringBuilder sb, RunSummary runSummary)
 {
     sb.AppendLine(GenerateTitle("Processing errors"));
     sb.AppendLine(runSummary.ProcessingErrorsReport());
 }
예제 #20
0
 public Task DisposeAsync(RunSummary result, IMessageBus messageBus) => ContainerHost.Decrement();
예제 #21
0
        private static void GenerateWorkbookGeneratorResultsSection(StringBuilder sb, RunSummary runSummary)
        {
            sb.AppendLine(GenerateTitle("Generated workbooks"));

            var workbookTemplates     = runSummary.WorkbookGeneratorResults.WorkbookTemplates ?? Enumerable.Empty <PackagedWorkbookTemplateInfo>();
            var allAvailableTemplates = workbookTemplates.Select(template => template.Name).OrderBy(name => name);

            sb.AppendLine($"Workbook templates available: {string.Join("; ", allAvailableTemplates)}");

            var completedWorkbooks    = runSummary.WorkbookGeneratorResults.CompletedWorkbooks ?? Enumerable.Empty <CompletedWorkbookInfo>();
            var successfullyGenerated = completedWorkbooks.Where(cwi => cwi.GeneratedSuccessfully).ToList();
            var workbooksWithData     = successfullyGenerated
                                        .Where(cwi => cwi.HasAnyData)
                                        .Select(cwi => cwi.OriginalWorkbookName)
                                        .OrderBy(workbookName => workbookName)
                                        .ToList();

            if (workbooksWithData.Count > 0)
            {
                sb.AppendLine($"Successfully generated workbooks with data: {GenerateHorizontalList(workbooksWithData)}");
            }

            var workbooksWithoutData = successfullyGenerated
                                       .Where(cwi => !cwi.HasAnyData)
                                       .Select(cwi => cwi.OriginalWorkbookName)
                                       .OrderBy(workbookName => workbookName)
                                       .ToList();

            if (workbooksWithoutData.Count > 0)
            {
                sb.AppendLine($"Empty workbooks: {GenerateHorizontalList(workbooksWithoutData)}");
            }

            if (runSummary.HasWorkbookGeneratorErrors())
            {
                sb.AppendLine(runSummary.WorkbookGeneratorErrorsReport());
            }
        }
예제 #22
0
        /// <summary>
        /// Returns true if PipelineRunImpl instances are equal
        /// </summary>
        /// <param name="other">Instance of PipelineRunImpl to be compared</param>
        /// <returns>Boolean</returns>
        public bool Equals(PipelineRunImpl other)
        {
            if (other is null)
            {
                return(false);
            }
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            return
                ((
                     Class == other.Class ||
                     Class != null &&
                     Class.Equals(other.Class)
                     ) &&
                 (
                     Links == other.Links ||
                     Links != null &&
                     Links.Equals(other.Links)
                 ) &&
                 (
                     DurationInMillis == other.DurationInMillis ||

                     DurationInMillis.Equals(other.DurationInMillis)
                 ) &&
                 (
                     EnQueueTime == other.EnQueueTime ||
                     EnQueueTime != null &&
                     EnQueueTime.Equals(other.EnQueueTime)
                 ) &&
                 (
                     EndTime == other.EndTime ||
                     EndTime != null &&
                     EndTime.Equals(other.EndTime)
                 ) &&
                 (
                     EstimatedDurationInMillis == other.EstimatedDurationInMillis ||

                     EstimatedDurationInMillis.Equals(other.EstimatedDurationInMillis)
                 ) &&
                 (
                     Id == other.Id ||
                     Id != null &&
                     Id.Equals(other.Id)
                 ) &&
                 (
                     Organization == other.Organization ||
                     Organization != null &&
                     Organization.Equals(other.Organization)
                 ) &&
                 (
                     Pipeline == other.Pipeline ||
                     Pipeline != null &&
                     Pipeline.Equals(other.Pipeline)
                 ) &&
                 (
                     Result == other.Result ||
                     Result != null &&
                     Result.Equals(other.Result)
                 ) &&
                 (
                     RunSummary == other.RunSummary ||
                     RunSummary != null &&
                     RunSummary.Equals(other.RunSummary)
                 ) &&
                 (
                     StartTime == other.StartTime ||
                     StartTime != null &&
                     StartTime.Equals(other.StartTime)
                 ) &&
                 (
                     State == other.State ||
                     State != null &&
                     State.Equals(other.State)
                 ) &&
                 (
                     Type == other.Type ||
                     Type != null &&
                     Type.Equals(other.Type)
                 ) &&
                 (
                     CommitId == other.CommitId ||
                     CommitId != null &&
                     CommitId.Equals(other.CommitId)
                 ));
        }
예제 #23
0
 public static bool LogReadingCompletedSuccessfully(this RunSummary runSummary)
 {
     return(runSummary?.ProcessLogSetResult != null &&
            runSummary.ProcessLogSetResult.IsSuccessful);
 }
예제 #24
0
        private async Task <RunSummary> InvokeStepsAsync(
            ICollection <IStepDefinition> backGroundStepDefinitions, ICollection <IStepDefinition> scenarioStepDefinitions)
        {
            var scenarioTypeInfo = this.scenarioClass.GetTypeInfo();
            var filters          = scenarioTypeInfo.Assembly.GetCustomAttributes(typeof(Attribute))
                                   .Concat(scenarioTypeInfo.GetCustomAttributes(typeof(Attribute)))
                                   .Concat(this.scenarioMethod.GetCustomAttributes(typeof(Attribute)))
                                   .OfType <IFilter <IStepDefinition> >();

            var    summary           = new RunSummary();
            string skipReason        = null;
            var    scenarioTeardowns = new List <Tuple <StepContext, Func <IStepContext, Task> > >();
            var    stepNumber        = 0;

            foreach (var stepDefinition in filters.Aggregate(
                         backGroundStepDefinitions.Concat(scenarioStepDefinitions),
                         (current, filter) => filter.Filter(current)))
            {
                stepDefinition.SkipReason = stepDefinition.SkipReason ?? skipReason;

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

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

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

                var stepContext = new StepContext(step);

                var stepRunner = new StepTestRunner(
                    stepContext,
                    stepDefinition.Body,
                    step,
                    interceptingBus,
                    this.scenarioClass,
                    this.constructorArguments,
                    this.scenarioMethod,
                    this.scenarioMethodArguments,
                    stepDefinition.SkipReason,
                    new BeforeAfterTestAttribute[0],
                    new ExceptionAggregator(this.aggregator),
                    this.cancellationTokenSource);

                summary.Aggregate(await stepRunner.RunAsync());

                var stepTeardowns = stepContext.Disposables
                                    .Where(disposable => disposable != null)
                                    .Select((Func <IDisposable, Func <IStepContext, Task> >)(disposable =>
                                                                                             context =>
                {
                    disposable.Dispose();
                    return(Task.FromResult(0));
                }))
                                    .Concat(stepDefinition.Teardowns)
                                    .Where(teardown => teardown != null)
                                    .Select(teardown => Tuple.Create(stepContext, teardown));

                scenarioTeardowns.AddRange(stepTeardowns);
            }

            if (scenarioTeardowns.Any())
            {
                scenarioTeardowns.Reverse();
                var teardownTimer      = new ExecutionTimer();
                var teardownAggregator = new ExceptionAggregator();
                foreach (var teardown in scenarioTeardowns)
                {
                    await Invoker.Invoke(() => teardown.Item2(teardown.Item1), teardownAggregator, teardownTimer);
                }

                summary.Time += teardownTimer.Total;

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

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

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

            return(summary);
        }
예제 #25
0
 public static bool HasProcessingErrors(this RunSummary runSummary)
 {
     return(runSummary?.ProcessingNotificationsCollector != null &&
            runSummary.ProcessingNotificationsCollector.TotalErrorsReported > 0);
 }
예제 #26
0
        public static TestableTestCaseRunner Create(IMessageBus messageBus, ITestCase testCase = null, RunSummary result = null, Exception aggregatorSeedException = null)
        {
            var aggregator = new ExceptionAggregator();

            if (aggregatorSeedException != null)
            {
                aggregator.Add(aggregatorSeedException);
            }

            return(new TestableTestCaseRunner(
                       testCase ?? Mocks.TestCase <Object>("ToString"),
                       messageBus,
                       aggregator,
                       new CancellationTokenSource(),
                       result ?? new RunSummary()
                       ));
        }
예제 #27
0
 public static bool HasWorkbookGeneratorErrors(this RunSummary runSummary)
 {
     return(runSummary?.WorkbookGeneratorResults?.CompletedWorkbooks != null &&
            runSummary.WorkbookGeneratorResults.CompletedWorkbooks.Any(result => !result.GeneratedSuccessfully));
 }
        protected override async Task <RunSummary> RunTestAsync()
        {
            var scenarioFactTestCase = (ScenarioFactTestCase)TestCase;
            var test             = CreateTest(TestCase, DisplayName);
            var aggregatedResult = new RunSummary();

            // Theories are called with required arguments. Keep track of what arguments we already tested so that we can skip those accordingly
            var testedArguments = new HashSet <object>();

            // Each time we find a new theory argument, we will want to restart our Test so that we can collect subsequent test cases
            bool pendingRestart;

            do
            {
                // Safeguarding against abuse
                if (testedArguments.Count >= scenarioFactTestCase.TheoryTestCaseLimit)
                {
                    pendingRestart = false;
                    MessageBus.QueueMessage(new TestSkipped(test, "Theory tests are capped to prevent infinite loops. You can configure a different limit by setting TheoryTestCaseLimit on the Scenario attribute"));
                    aggregatedResult.Aggregate(new RunSummary
                    {
                        Skipped = 1,
                        Total   = 1
                    });
                }
                else
                {
                    var bufferedMessageBus  = new BufferedMessageBus(MessageBus);
                    var stopwatch           = Stopwatch.StartNew();
                    var skipAdditionalTests = false;
                    var testRecorded        = false;
                    pendingRestart = false; // By default we dont expect a new restart

                    object?         capturedArgument = null;
                    ScenarioContext scenarioContext  = null;

                    scenarioContext = new ScenarioContext(scenarioFactTestCase.FactName, async(ScenarioTestCaseDescriptor descriptor) =>
                    {
                        // If we're hitting our target test
                        if (descriptor.Name == scenarioFactTestCase.FactName)
                        {
                            testRecorded = true;

                            if (skipAdditionalTests)
                            {
                                pendingRestart = true; // when we discovered more tests after a test completed, allow us to restart
                                scenarioContext.EndScenarioConditionally();
                                return;
                            }

                            if (descriptor.Argument is not null)
                            {
                                // If we've already received this test case, don't run it again
                                if (testedArguments.Contains(descriptor.Argument))
                                {
                                    return;
                                }

                                testedArguments.Add(descriptor.Argument);
                                capturedArgument = descriptor.Argument;
                            }

                            // At this stage we found our first valid test case, any subsequent test case should issue a restart instead
                            skipAdditionalTests = true;
                            try
                            {
                                await descriptor.Invocation();
                            }
                            catch (Exception)
                            {
                                // If we caught an exception but we're in a theory, we will want to try for additional test cases
                                if (descriptor.Argument is not null)
                                {
                                    pendingRestart = true;
                                }

                                throw;
                            }
                            finally
                            {
                                scenarioContext.IsTargetConclusive = true;
                            }
                        }
                        else
                        {
                            // We may be hitting a shared fact, those need to be invoked as well but not recorded as our primary target
                            if (!scenarioFactTestCase.RunInIsolation || descriptor.Flags.HasFlag(ScenarioTestCaseFlags.Shared))
                            {
                                await descriptor.Invocation();
                            }
                        }
                    });

                    scenarioContext.AutoAbort = scenarioFactTestCase.ExecutionPolicy is ScenarioTestExecutionPolicy.EndAfterConclusion;

                    TestMethodArguments = new object[] { scenarioContext };

                    RunSummary result;

                    result = await CreateTestRunner(test, bufferedMessageBus, TestClass, ConstructorArguments, TestMethod, TestMethodArguments, SkipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource).RunAsync();

                    aggregatedResult.Aggregate(result);

                    stopwatch.Stop();
                    var testInvocationTest = capturedArgument switch
                    {
                        null => CreateTest(TestCase, DisplayName),
                        not null => CreateTest(TestCase, $"{DisplayName} ({capturedArgument})")
                    };

                    var bufferedMessages = bufferedMessageBus.QueuedMessages;

                    // We should have expected at least one test run. We probably returned before our target test was able to run
                    if (!testRecorded && result.Failed == 0)
                    {
                        bufferedMessageBus.QueueMessage(new TestSkipped(test, scenarioContext.SkippedReason ?? "No applicable tests were able to run"));
                        result = new RunSummary {
                            Skipped = 1, Total = 1
                        };
                    }

                    // If we skipped this test, make sure that this is reported accordingly
                    if (scenarioContext.Skipped && !bufferedMessages.OfType <TestSkipped>().Any())
                    {
                        bufferedMessages = bufferedMessages.Concat(new[] { new TestSkipped(testInvocationTest, scenarioContext.SkippedReason) });
                    }

                    // If we have indeed skipped this test, make sure that we're not reporting it as passed or failed
                    if (bufferedMessages.OfType <TestSkipped>().Any())
                    {
                        bufferedMessages = bufferedMessages.Where(x => x is not TestPassed and not TestFailed);
                    }

                    // If we have a failure in post conditions, don't mark this test case as passed
                    if (bufferedMessages.OfType <TestFailed>().Any())
                    {
                        bufferedMessages = bufferedMessages.Where(x => x is not TestPassed);
                    }

                    var output = string.Join("", bufferedMessages
                                             .OfType <ITestOutput>()
                                             .Select(x => x.Output));

                    var duration = (decimal)stopwatch.Elapsed.TotalSeconds;

                    foreach (var queuedMessage in bufferedMessages)
                    {
                        var transformedMessage = queuedMessage switch
                        {
                            TestStarting testStarting => new TestStarting(testInvocationTest),
                            TestSkipped testSkipped => new TestSkipped(testInvocationTest, testSkipped.Reason),
                            TestPassed testPassed => new TestPassed(testInvocationTest, duration, output),
                            TestFailed testFailed => new TestFailed(testInvocationTest, duration, output, testFailed.ExceptionTypes, testFailed.Messages, testFailed.StackTraces, testFailed.ExceptionParentIndices),
                            TestFinished testFinished => new TestFinished(testInvocationTest, duration, output),
                            _ => queuedMessage
                        };

                        if (!MessageBus.QueueMessage(transformedMessage))
                        {
                            return(aggregatedResult);
                        }
                    }
                }
            }while (pendingRestart);

            return(aggregatedResult);
        }
    }
}
예제 #29
0
 public static string LogSetProcessingStatusReport(this RunSummary runSummary)
 {
     return(runSummary.LogReadingCompletedSuccessfully()
         ? "LogShark successfully processed all logs"
         : $"Error occurred while processing logs: {runSummary.ProcessLogSetResult.ErrorMessage}");
 }
        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);
        }
        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;
                }
            }
        }
예제 #32
0
파일: Xunit1.cs 프로젝트: JayBazuzi/xunit
        RunSummary RunTestCollection(ITestCollection testCollection, IEnumerable<Xunit1TestCase> testCases, IMessageSink messageSink)
        {
            var results = new RunSummary();
            results.Continue = messageSink.OnMessage(new TestCollectionStarting(testCollection));

            if (results.Continue)
                foreach (var testClassGroup in testCases.GroupBy(tc => tc.Class.Name))
                {
                    var classResults = RunTestClass(testCollection, testClassGroup.Key, testClassGroup.ToList(), messageSink);
                    results.Aggregate(classResults);
                    if (!classResults.Continue)
                        break;
                }

            results.Continue = messageSink.OnMessage(new TestCollectionFinished(testCollection, results.Time, results.Total, results.Failed, results.Skipped)) && results.Continue;
            return results;
        }
예제 #33
0
        public async Task <RunSummary> RunScenarioAsync()
        {
            var runSummary = new RunSummary {
                Total = 1
            };
            var output = string.Empty;

            if (!MessageBus.QueueMessage(new TestStarting(Test)))
            {
                CancellationTokenSource.Cancel();
            }
            else
            {
                AfterTestStarting();

                if (!string.IsNullOrEmpty(SkipReason))
                {
                    runSummary.Skipped++;

                    if (!MessageBus.QueueMessage(new TestSkipped(Test, SkipReason)))
                    {
                        CancellationTokenSource.Cancel();
                    }
                }
                else
                {
                    var aggregator = new ExceptionAggregator(Aggregator);

                    if (!aggregator.HasExceptions)
                    {
                        var tuple = await aggregator.RunAsync(() => InvokeTestAsync(aggregator));

                        runSummary.Time = tuple.Item1;
                        output          = tuple.Item2;
                    }

                    var exception = aggregator.ToException();
                    TestResultMessage testResult;

                    if (exception == null)
                    {
                        testResult = new TestPassed(Test, runSummary.Time, output);
                    }
                    else if (exception is IgnoreException)
                    {
                        testResult = new TestSkipped(Test, exception.Message);
                        runSummary.Skipped++;
                    }
                    else
                    {
                        testResult = new TestFailed(Test, runSummary.Time, output, exception);
                        runSummary.Failed++;
                    }

                    if (!CancellationTokenSource.IsCancellationRequested)
                    {
                        if (!MessageBus.QueueMessage(testResult))
                        {
                            CancellationTokenSource.Cancel();
                        }
                    }
                }

                Aggregator.Clear();
                BeforeTestFinished();

                if (Aggregator.HasExceptions)
                {
                    if (!MessageBus.QueueMessage(new TestCleanupFailure(Test, Aggregator.ToException())))
                    {
                        CancellationTokenSource.Cancel();
                    }
                }
            }

            if (!MessageBus.QueueMessage(new TestFinished(Test, runSummary.Time, output)))
            {
                CancellationTokenSource.Cancel();
            }

            return(runSummary);
        }
예제 #34
0
 public Task DisposeAsync(RunSummary result, IMessageBus messageBus)
 {
     return(Task.CompletedTask);
 }
예제 #35
0
 public virtual Task DisposeAsync(RunSummary result, IMessageBus messageBus)
 {
     Dispose(true);
     return(ContainerHost.Decrement());
 }