Skip to content

Commit

Permalink
Merge branch 'master' into fix_async_binding_calls_2600
Browse files Browse the repository at this point in the history
* master:
  Report binding problems to binding registry and show them as errors during test execution (#2663)
  Fix for SF2649: Aggregate exceptions lost from async step definitions (#2667)

# Conflicts:
#	TechTalk.SpecFlow/Bindings/BindingInvoker.cs
#	Tests/TechTalk.SpecFlow.RuntimeTests/Bindings/BindingInvokerTests.cs
  • Loading branch information
gasparnagy committed Nov 9, 2022
2 parents 93db25a + 697fe33 commit fef0211
Show file tree
Hide file tree
Showing 22 changed files with 489 additions and 165 deletions.
20 changes: 20 additions & 0 deletions TechTalk.SpecFlow/Bindings/BindingError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace TechTalk.SpecFlow.Bindings;

public class BindingError
{
public BindingErrorType Type { get; }
public string Message { get; }

public BindingError(BindingErrorType type, string message)
{
Type = type;
Message = message;
}
}

public enum BindingErrorType
{
TypeLoadError,
BindingError,
StepDefinitionError,
}
12 changes: 3 additions & 9 deletions TechTalk.SpecFlow/Bindings/BindingInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using TechTalk.SpecFlow.Bindings.Reflection;
Expand Down Expand Up @@ -78,17 +79,10 @@ public virtual async Task<object> InvokeBindingAsync(IBinding binding, IContextM
catch (TargetInvocationException invEx)
{
var ex = invEx.InnerException;
ex = ex.PreserveStackTrace(errorProvider.GetMethodText(binding.Method));
stopwatch.Stop();
durationHolder.Duration = stopwatch.Elapsed;
throw ex;
}
catch (AggregateException aggregateEx)
{
var ex = aggregateEx.InnerExceptions.First();
ex = ex.PreserveStackTrace(errorProvider.GetMethodText(binding.Method));
stopwatch.Stop();
durationHolder.Duration = stopwatch.Elapsed;
ExceptionDispatchInfo.Capture(ex).Throw();
//hack,hack,hack - the compiler doesn't recognize that ExceptionDispatchInfo.Throw() exits the method; the next line will never be executed
throw ex;
}
catch (Exception)
Expand Down
48 changes: 34 additions & 14 deletions TechTalk.SpecFlow/Bindings/BindingRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace TechTalk.SpecFlow.Bindings
{
public class BindingRegistry : IBindingRegistry
{
private readonly List<IStepDefinitionBinding> stepDefinitions = new List<IStepDefinitionBinding>();
private readonly List<IStepArgumentTransformationBinding> stepArgumentTransformations = new List<IStepArgumentTransformationBinding>();
private readonly Dictionary<HookType, List<IHookBinding>> hooks = new Dictionary<HookType, List<IHookBinding>>();
private readonly List<IStepDefinitionBinding> _stepDefinitions = new();
private readonly List<IStepArgumentTransformationBinding> _stepArgumentTransformations = new();
private readonly Dictionary<HookType, List<IHookBinding>> _hooks = new();
private readonly List<BindingError> _genericBindingErrors = new();

public bool Ready { get; set; }

public bool IsValid => !GetErrorMessages().Any();

public IEnumerable<IStepDefinitionBinding> GetStepDefinitions()
{
return stepDefinitions;
return _stepDefinitions;
}

public IEnumerable<IStepDefinitionBinding> GetConsideredStepDefinitions(StepDefinitionType stepDefinitionType, string stepText)
{
//TODO: later optimize to return step definitions that has a chance to match to stepText
return stepDefinitions.Where(sd => sd.StepDefinitionType == stepDefinitionType);
return _stepDefinitions.Where(sd => sd.StepDefinitionType == stepDefinitionType);
}

public virtual IEnumerable<IHookBinding> GetHooks()
{
return hooks.Values.SelectMany(hookList => hookList);
return _hooks.Values.SelectMany(hookList => hookList);
}

public virtual IEnumerable<IHookBinding> GetHooks(HookType bindingEvent)
Expand All @@ -34,28 +38,39 @@ public virtual IEnumerable<IHookBinding> GetHooks(HookType bindingEvent)

private IEnumerable<IHookBinding> GetHookList(HookType bindingEvent)
{
if (hooks.TryGetValue(bindingEvent, out var list))
if (_hooks.TryGetValue(bindingEvent, out var list))
return list;

return Enumerable.Empty<IHookBinding>();
}

public virtual IEnumerable<IStepArgumentTransformationBinding> GetStepTransformations()
{
return stepArgumentTransformations;
}

return _stepArgumentTransformations;
}

public IEnumerable<BindingError> GetErrorMessages()
{
foreach (var genericBindingError in _genericBindingErrors)
yield return genericBindingError;

foreach (var stepDefinitionBinding in _stepDefinitions.Where(sd => !sd.IsValid))
{
yield return new BindingError(BindingErrorType.StepDefinitionError, stepDefinitionBinding.ErrorMessage);
}
}

public virtual void RegisterStepDefinitionBinding(IStepDefinitionBinding stepDefinitionBinding)
{
stepDefinitions.Add(stepDefinitionBinding);
_stepDefinitions.Add(stepDefinitionBinding);
}

private List<IHookBinding> GetHookListForRegister(HookType bindingEvent)
{
if (!hooks.TryGetValue(bindingEvent, out var list))
if (!_hooks.TryGetValue(bindingEvent, out var list))
{
list = new List<IHookBinding>();
hooks.Add(bindingEvent, list);
_hooks.Add(bindingEvent, list);
}

return list;
Expand All @@ -71,7 +86,12 @@ public virtual void RegisterHookBinding(IHookBinding hookBinding)

public virtual void RegisterStepArgumentTransformationBinding(IStepArgumentTransformationBinding stepArgumentTransformationBinding)
{
stepArgumentTransformations.Add(stepArgumentTransformationBinding);
_stepArgumentTransformations.Add(stepArgumentTransformationBinding);
}

public void RegisterGenericBindingError(BindingError error)
{
_genericBindingErrors.Add(error);
}
}
}
2 changes: 2 additions & 0 deletions TechTalk.SpecFlow/Bindings/Discovery/BindingSourceMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ public class BindingSourceMethod
public bool IsStatic { get; set; }

public BindingSourceAttribute[] Attributes { get; set; }

public override string ToString() => BindingMethod.ToString();
}
}
Loading

0 comments on commit fef0211

Please sign in to comment.