private async Task <RunSummary> InvokeScenarioMethodAsync(object scenarioClassInstance) { var backgroundStepDefinitions = new List <IStepDefinition>(); var scenarioStepDefinitions = new List <IStepDefinition>(); await this.aggregator.RunAsync(async() => { using (CurrentThread.EnterStepDefinitionContext()) { foreach (var backgroundMethod in this.scenario.TestCase.TestMethod.TestClass.Class .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); } using (CurrentThread.EnterStepDefinitionContext()) { await this.timer.AggregateAsync(() => this.scenarioMethod.InvokeAsync(scenarioClassInstance, this.scenarioMethodArguments)); scenarioStepDefinitions.AddRange(CurrentThread.StepDefinitions); } }); var runSummary = new RunSummary { Time = this.timer.Total }; if (!this.aggregator.HasExceptions) { runSummary.Aggregate(await this.InvokeStepsAsync(backgroundStepDefinitions, scenarioStepDefinitions)); } return(runSummary); }
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); }