public BindingMatch(IStepDefinitionBinding stepDefinitionBinding, StepArgs stepArgs, string[] regexArguments, object[] extraArguments, int scopeMatches) { if (stepDefinitionBinding == null) { throw new ArgumentNullException("stepDefinitionBinding"); } if (stepArgs == null) { throw new ArgumentNullException("stepArgs"); } if (regexArguments == null) { throw new ArgumentNullException("regexArguments"); } if (extraArguments == null) { throw new ArgumentNullException("extraArguments"); } StepBinding = stepDefinitionBinding; StepArgs = stepArgs; RegexArguments = regexArguments; ExtraArguments = extraArguments; ScopeMatches = scopeMatches; Arguments = RegexArguments.Concat(ExtraArguments).ToArray(); }
public override string GetStepDefinitionSkeleton(StepArgs stepArgs) { List<string> extraArgs = new List<string>(); if (stepArgs.MultilineTextArgument != null) extraArgs.Add("ByVal multilineText As String"); if (stepArgs.TableArgument != null) extraArgs.Add("ByVal table As Table"); StringBuilder result = new StringBuilder(); // in VB "When" and "Then" are language keywords - use the fully qualified namespace string namespaceAddition = "TechTalk.SpecFlow."; if (stepArgs.Type == BindingType.Given) { namespaceAddition = ""; } result.AppendFormat(@"<{5}{0}(""{2}"")> _ Public Sub {1}{3}({4}) ScenarioContext.Current.Pending() End Sub", stepArgs.Type, LanguageHelper.GetDefaultKeyword(stepArgs.StepContext.FeatureInfo.Language, stepArgs.Type).ToIdentifier(), EscapeRegex(stepArgs.Text), stepArgs.Text.ToIdentifier(), string.Join(", ", extraArgs.ToArray()), namespaceAddition ); result.AppendLine(); return result.ToString(); }
public void TraceNoMatchingStepDefinition(StepArgs stepArgs, ProgrammingLanguage targetLanguage, List<BindingMatch> matchesWithoutScopeCheck) { // string stepDescription = stepFormatter.GetStepDescription(stepArgs); // return new BindingException( // string.Format("Multiple step definitions found, but none of them have matching scope for step '{0}': {1}", // stepDescription, // string.Join(", ", matches.Select(m => GetMethodText(m.StepBinding.MethodInfo)).ToArray()))); IStepDefinitionSkeletonProvider stepDefinitionSkeletonProvider = ObjectContainer.StepDefinitionSkeletonProvider(targetLanguage); StringBuilder message = new StringBuilder(); if (matchesWithoutScopeCheck == null || matchesWithoutScopeCheck.Count == 0) message.AppendLine("No matching step definition found for the step. Use the following code to create one:"); else { string preMessage = string.Format("No matching step definition found for the step. There are matching step definitions, but none of them have matching scope for this step: {0}.", string.Join(", ", matchesWithoutScopeCheck.Select(m => stepFormatter.GetMatchText(m, null)).ToArray())); traceListener.WriteToolOutput(preMessage); message.AppendLine("Change the scope or use the following code to create a new step definition:"); } message.Append( stepDefinitionSkeletonProvider.GetBindingClassSkeleton( stepDefinitionSkeletonProvider.GetStepDefinitionSkeleton(stepArgs)) .Indent(StepDefinitionSkeletonProviderBase.CODEINDENT)); traceListener.WriteToolOutput(message.ToString()); }
public BindingMatch(StepBinding stepBinding, Match match, object[] extraArguments, StepArgs stepArgs, int scopeMatches) { if (stepBinding == null) { throw new ArgumentNullException("stepBinding"); } if (match == null) { throw new ArgumentNullException("match"); } if (extraArguments == null) { throw new ArgumentNullException("extraArguments"); } if (stepArgs == null) { throw new ArgumentNullException("stepArgs"); } StepBinding = stepBinding; Match = match; ExtraArguments = extraArguments; StepArgs = stepArgs; ScopeMatches = scopeMatches; RegexArguments = Match.Groups.Cast <Group>().Skip(1).Select(g => g.Value).ToArray(); Arguments = RegexArguments.Concat(ExtraArguments).ToArray(); }
public override string GetStepDefinitionSkeleton(StepArgs stepArgs) { List<string> extraArgs = new List<string>(); if (stepArgs.MultilineTextArgument != null) extraArgs.Add("string multilineText"); if (stepArgs.TableArgument != null) extraArgs.Add("Table table"); string stepText = EscapeRegexOutsideQuotes(stepArgs.Text); string methodName = Regex.Replace(EscapeRegex(stepArgs.Text), QuotesRegex, "").ToIdentifier(); extraArgs.AddRange(ParseArgsFromQuotes(ref stepText)); //Adds values passed in via quotes to the args for the method StringBuilder result = new StringBuilder(); result.AppendFormat( @"[{0}(@""{1}"")] public void {0}{2}({3}) {{ ScenarioContext.Current.Pending(); }}", stepArgs.Type, stepText, methodName, string.Join(", ", extraArgs.ToArray())); result.AppendLine(); return result.ToString(); }
public BindingMatch(StepBinding stepBinding, Match match, object[] extraArguments, StepArgs stepArgs) { StepBinding = stepBinding; Match = match; ExtraArguments = extraArguments; StepArgs = stepArgs; }
public Exception GetAmbiguousMatchError(IEnumerable<BindingMatch> matches, StepArgs stepArgs) { string stepDescription = stepFormatter.GetStepDescription(stepArgs); return new BindingException( string.Format("Ambiguous step definitions found for step '{0}': {1}", stepDescription, string.Join(", ", matches.Select(m => GetMethodText(m.StepBinding.MethodInfo)).ToArray()))); }
public Exception GetAmbiguousBecauseParamCheckMatchError(List<BindingMatch> matches, StepArgs stepArgs) { string stepDescription = stepFormatter.GetStepDescription(stepArgs); return new BindingException( string.Format("Multiple step definitions found, but none of them have matching parameter count and type for step '{0}': {1}", stepDescription, string.Join(", ", matches.Select(m => GetMethodText(m.StepBinding.MethodInfo)).ToArray()))); }
public Exception GetNoMatchBecauseOfScopeFilterError(List<BindingMatch> matches, StepArgs stepArgs) { string stepDescription = stepFormatter.GetStepDescription(stepArgs); return new BindingException( string.Format("Multiple step definitions found, but none of them have matching scope for step '{0}': {1}", stepDescription, string.Join(", ", matches.Select(m => GetMethodText(m.StepBinding.MethodInfo)).ToArray()))); }
public BindingMatch(StepBinding stepBinding, Match match, object[] extraArguments, StepArgs stepArgs, bool isScoped) { StepBinding = stepBinding; Match = match; ExtraArguments = extraArguments; StepArgs = stepArgs; IsScoped = isScoped; }
public void TraceNoMatchingStepDefinition(StepArgs stepArgs) { StringBuilder message = new StringBuilder(); message.AppendLine("No matching step definition found for the step. Use the following code to create one:"); message.Append( stepDefinitionSkeletonProvider.GetBindingClassSkeleton( stepDefinitionSkeletonProvider.GetStepDefinitionSkeleton(stepArgs)) .Indent(StepDefinitionSkeletonProvider.CODEINDENT)); traceListener.WriteToolOutput(message.ToString()); }
public void Produces_CSharp_Method_Skeleton_With_Parsed_Doubles() { var expected = new StringBuilder(); expected.Append( @"[Then(@""I can parse a double """"(.*)"""" and another double """"(.*)"""""")] public void ThenICanParseADoubleAndAnotherDouble(double double1, double double2) { ScenarioContext.Current.Pending(); } "); var stepArgs = new StepArgs(BindingType.Then, StepDefinitionKeyword.Then, "I can parse a double \"3.4\" and another double \"902.302\"", null, null, null); string result = skeletonProviderCS.GetStepDefinitionSkeleton(stepArgs); Assert.AreEqual(expected.ToString(), result); }
public void Produces_CSharp_Method_Skeleton() { StringBuilder expected = new StringBuilder(); expected.Append( @"[Given(@""I have a new step"")] public void GivenIHaveANewStep() { ScenarioContext.Current.Pending(); } "); StepArgs stepArgs = new StepArgs(BindingType.Given, StepDefinitionKeyword.Given, "I have a new step", null, null, null); string result = skeletonProviderCS.GetStepDefinitionSkeleton(stepArgs); Assert.AreEqual(expected.ToString(), result); }
public BindingMatch(StepBinding stepBinding, Match match, object[] extraArguments, StepArgs stepArgs, int scopeMatches) { if (stepBinding == null) throw new ArgumentNullException("stepBinding"); if (match == null) throw new ArgumentNullException("match"); if (extraArguments == null) throw new ArgumentNullException("extraArguments"); if (stepArgs == null) throw new ArgumentNullException("stepArgs"); StepBinding = stepBinding; Match = match; ExtraArguments = extraArguments; StepArgs = stepArgs; ScopeMatches = scopeMatches; RegexArguments = Match.Groups.Cast<Group>().Skip(1).Select(g => g.Value).ToArray(); Arguments = RegexArguments.Concat(ExtraArguments).ToArray(); }
public void Produces_CSharp_Method_Skeleton_With_Parsed_Dates() { var expected = new StringBuilder(); expected.Append( @"[When(@""I can parse dates such as """"(.*)"""", """"(.*)"""" and """"(.*)"""""")] public void WhenICanParseDatesSuchAsAnd(DateTime dateTime1, DateTime dateTime2, DateTime dateTime3) { ScenarioContext.Current.Pending(); } "); var stepArgs = new StepArgs(BindingType.When, StepDefinitionKeyword.When, "I can parse dates such as \"20/10/02\", \"12:00\" and \"20.12.09\"", null, null, null); string result = skeletonProviderCS.GetStepDefinitionSkeleton(stepArgs); Assert.AreEqual(expected.ToString(), result); }
public string GetStepText(StepArgs stepArgs) { StringBuilder result = new StringBuilder(); result.Append(LanguageHelper.GetKeyword(FeatureContext.Current.FeatureInfo.Language, stepArgs.StepDefinitionKeyword)); result.Append(" "); result.AppendLine(stepArgs.Text); if (stepArgs.MultilineTextArgument != null) { result.AppendLine("--- multiline step argument ---".Indent(INDENT)); result.AppendLine(stepArgs.MultilineTextArgument.Indent(INDENT)); } if (stepArgs.TableArgument != null) { result.AppendLine("--- table step argument ---".Indent(INDENT)); result.AppendLine(stepArgs.TableArgument.ToString().Indent(INDENT)); } return result.ToString(); }
public override string GetStepDefinitionSkeleton(StepArgs stepArgs) { List<string> extraArgs = new List<string>(); if (stepArgs.MultilineTextArgument != null) extraArgs.Add("ByVal multilineText As String"); if (stepArgs.TableArgument != null) extraArgs.Add("ByVal table As Table"); string stepText = EscapeRegexOutsideQuotes(stepArgs.Text); extraArgs.AddRange(ParseArgsFromQuotes(ref stepText)); //Adds parameters passed in via quotes to the args for the method string methodName = Regex.Replace(EscapeRegex(stepArgs.Text), QuotesRegex, "").ToIdentifier(); StringBuilder result = new StringBuilder(); // in VB "When" and "Then" are language keywords - use the fully qualified namespace string namespaceAddition = "TechTalk.SpecFlow."; if (stepArgs.Type == BindingType.Given) { namespaceAddition = ""; } result.AppendFormat( @"<{4}{0}(""{1}"")> _ Public Sub {0}{2}({3}) {5}ScenarioContext.Current.Pending() End Sub", stepArgs.Type, stepText, methodName, string.Join(", ", extraArgs.ToArray()), namespaceAddition, CODEINDENT ); result.AppendLine(); return result.ToString(); }
public string GetStepDefinitionSkeleton(StepArgs stepArgs) { List<string> extraArgs = new List<string>(); if (stepArgs.MultilineTextArgument != null) extraArgs.Add("string multilineText"); if (stepArgs.TableArgument != null) extraArgs.Add("Table table"); StringBuilder result = new StringBuilder(); result.AppendFormat(@"[{0}(@""{2}"")] public void {1}{3}({4}) {{ ScenarioContext.Current.Pending(); }}", stepArgs.Type, LanguageHelper.GetKeyword(FeatureContext.Current.FeatureInfo.Language, stepArgs.Type).ToIdentifier(), EscapeRegex(stepArgs.Text), stepArgs.Text.ToIdentifier(), string.Join(", ", extraArgs.ToArray()) ); result.AppendLine(); return result.ToString(); }
private BindingMatch Match(StepBinding stepBinding, StepArgs stepArgs, bool useParamMatching, bool useScopeMatching) { Match match = stepBinding.Regex.Match(stepArgs.Text); // Check if regexp is a match if (!match.Success) return null; int scopeMatches = 0; if (useScopeMatching && stepBinding.IsScoped) { if (!stepBinding.BindingScope.Match(stepArgs.StepContext, out scopeMatches)) return null; } var bindingMatch = new BindingMatch(stepBinding, match, CalculateExtraArgs(stepArgs), stepArgs, scopeMatches); if (useParamMatching) { // check if the regex + extra arguments match to the binding method parameters if (bindingMatch.Arguments.Length != stepBinding.ParameterTypes.Length) return null; // Check if regex & extra arguments can be converted to the method parameters if (bindingMatch.Arguments.Where( (arg, argIndex) => !CanConvertArg(arg, stepBinding.ParameterTypes[argIndex])).Any()) return null; } return bindingMatch; }
public void TraceStep(StepArgs stepArgs, bool showAdditionalArguments) { string stepText = stepFormatter.GetStepText(stepArgs); traceListener.WriteTestOutput(stepText.TrimEnd()); }
private BindingMatch Match(StepBinding stepBinding, StepArgs stepArgs, bool useParamMatching, bool useScopeMatching) { Match match = stepBinding.Regex.Match(stepArgs.Text); // Check if regexp is a match if (!match.Success) return null; var extraArgs = CalculateExtraArgs(stepArgs); int scopeMatches = 0; if (useParamMatching) { var regexArgs = match.Groups.Cast<Group>().Skip(1).Select(g => g.Value).ToArray(); // check if the regex + extra arguments match to the binding method parameters if (regexArgs.Length + extraArgs.Length != stepBinding.ParameterTypes.Length) return null; // Check if regex arguments can be converted to the method parameters CultureInfo cultureInfo = FeatureContext.Current.BindingCulture; for (int regexArgIndex = 0; regexArgIndex < regexArgs.Length; regexArgIndex++) { Type parameterType = stepBinding.ParameterTypes[regexArgIndex]; if (!stepArgumentTypeConverter.CanConvert(regexArgs[regexArgIndex], parameterType, cultureInfo)) return null; } // Check if there are corresponting parameters defined for the extra arguments for (int extraArgIndex = 0; extraArgIndex < extraArgs.Length; extraArgIndex++) { Type parameterType = stepBinding.ParameterTypes[extraArgIndex + regexArgs.Length]; Type argType = extraArgs[extraArgIndex].GetType(); if (argType != parameterType) return null; } } if (useScopeMatching && stepBinding.IsScoped) { if (!stepBinding.BindingScope.Match(stepArgs.StepContext, out scopeMatches)) return null; } return new BindingMatch(stepBinding, match, extraArgs, stepArgs, scopeMatches); }
private BindingMatch GetStepMatch(StepArgs stepArgs) { List<BindingMatch> matches = new List<BindingMatch>(); foreach (StepBinding binding in bindingRegistry.Where(b => b.Type == stepArgs.Type)) { BindingMatch match = Match(binding, stepArgs, true); if (match == null) continue; matches.Add(match); if (!RuntimeConfiguration.Current.DetectAmbiguousMatches) break; } if (matches.Count == 0) { // there were either no regex match of it was filtered out by the param matching // to provide better error message for the param matching error, we re-run // the matching without param check List<BindingMatch> matchesWithoutParamCheck = GetMatchesWithoutParamCheck(stepArgs); if (matchesWithoutParamCheck.Count == 1) { // no ambiguouity, but param error -> execute will find it out return matchesWithoutParamCheck[0]; } if (matchesWithoutParamCheck.Count > 1) { // ambiguouity, because of param error throw errorProvider.GetAmbiguousBecauseParamCheckMatchError(matches, stepArgs); } testTracer.TraceNoMatchingStepDefinition(stepArgs); ObjectContainer.ScenarioContext.MissingSteps.Add( stepDefinitionSkeletonProvider.GetStepDefinitionSkeleton(stepArgs)); throw errorProvider.GetMissingStepDefinitionError(); } if (matches.Count > 1) { throw errorProvider.GetAmbiguousMatchError(matches, stepArgs); } return matches[0]; }
private List<BindingMatch> GetMatchesWithoutParamCheck(StepArgs stepArgs) { List<BindingMatch> matches = new List<BindingMatch>(); foreach (StepBinding binding in bindingRegistry.Where(b => b.Type == stepArgs.Type)) { BindingMatch match = Match(binding, stepArgs, false); if (match != null) matches.Add(match); } return matches; }
public void Produces_CSharp_Method_Skeleton_With_Parsed_Ints() { var expected = new StringBuilder(); expected.Append( @"[When(@""I can parse integers such as """"(\d+)"""", """"(\d+)"""" and """"(\d+)"""""")] public void WhenICanParseIntegersSuchAsAnd(int int1, int int2, int int3) { ScenarioContext.Current.Pending(); } "); var stepArgs = new StepArgs(BindingType.When, StepDefinitionKeyword.When, "I can parse integers such as \"20\", \"2147483647\" and \"-9\"", null, null, null); string result = skeletonProviderCS.GetStepDefinitionSkeleton(stepArgs); Assert.AreEqual(expected.ToString(), result); }
private object[] CalculateExtraArgs(StepArgs stepArgs) { if (stepArgs.MultilineTextArgument == null && stepArgs.TableArgument == null) return emptyExtraArgs; var extraArgsList = new List<object>(); if (stepArgs.MultilineTextArgument != null) extraArgsList.Add(stepArgs.MultilineTextArgument); if (stepArgs.TableArgument != null) extraArgsList.Add(stepArgs.TableArgument); return extraArgsList.ToArray(); }
public abstract string GetStepDefinitionSkeleton(StepArgs steps);
public string GetStepDescription(StepArgs stepArgs) { return string.Format("{0} {1}", stepArgs.Type, stepArgs.Text); }
private BindingMatch GetStepMatch(StepArgs stepArgs) { List<BindingMatch> matches = bindingRegistry .Where(b => b.Type == stepArgs.Type) .Select(binding => Match(binding, stepArgs, true, true)) .Where(match => match != null) .ToList(); if (matches.Count > 1) { // if there are both scoped and non-scoped matches, we take the ones with the higher degree of scope matches int maxScopeMatches = matches.Max(m => m.ScopeMatches); matches.RemoveAll(m => m.ScopeMatches < maxScopeMatches); } if (matches.Count > 1) { // we remove duplicate maches for the same method (take the first from each) matches = matches.GroupBy(m => m.StepBinding.MethodInfo, (methodInfo, methodMatches) => methodMatches.First()).ToList(); } if (matches.Count == 0) { // there were either no regex match or it was filtered out by the param/scope matching // to provide better error message for the param matching error, we re-run // the matching without param check List<BindingMatch> matchesWithoutScopeCheck = GetMatchesWithoutScopeCheck(stepArgs); // if (matchesWithoutScopeCheck.Count > 0) // { // no match, because of scope filter // throw errorProvider.GetNoMatchBecauseOfScopeFilterError(matchesWithoutScopeCheck, stepArgs); // } if (matchesWithoutScopeCheck.Count == 0) { List<BindingMatch> matchesWithoutParamCheck = GetMatchesWithoutParamCheck(stepArgs); if (matchesWithoutParamCheck.Count == 1) { // no ambiguouity, but param error -> execute will find it out return matchesWithoutParamCheck[0]; } if (matchesWithoutParamCheck.Count > 1) { // ambiguouity, because of param error throw errorProvider.GetAmbiguousBecauseParamCheckMatchError(matchesWithoutParamCheck, stepArgs); } } testTracer.TraceNoMatchingStepDefinition(stepArgs, contextManager.FeatureContext.FeatureInfo.GenerationTargetLanguage, matchesWithoutScopeCheck); contextManager.ScenarioContext.MissingSteps.Add( currentStepDefinitionSkeletonProvider.GetStepDefinitionSkeleton(stepArgs)); throw errorProvider.GetMissingStepDefinitionError(); } if (matches.Count > 1) { if (runtimeConfiguration.DetectAmbiguousMatches) throw errorProvider.GetAmbiguousMatchError(matches, stepArgs); } return matches[0]; }
public BindingMatch(IStepDefinitionBinding stepDefinitionBinding, Match match, object[] extraArguments, StepArgs stepArgs, int scopeMatches) : this(stepDefinitionBinding, stepArgs, match.Groups.Cast <Group>().Skip(1).Select(g => g.Value).ToArray(), extraArguments, scopeMatches) { }
private void ExecuteStep(StepArgs stepArgs) { HandleBlockSwitch(stepArgs.Type.ToScenarioBlock()); testTracer.TraceStep(stepArgs, true); BindingMatch match = null; object[] arguments = null; try { match = GetStepMatch(stepArgs); arguments = GetExecuteArguments(match); if (contextManager.ScenarioContext.TestStatus == TestStatus.OK) { TimeSpan duration = ExecuteStepMatch(match, arguments); if (runtimeConfiguration.TraceSuccessfulSteps) testTracer.TraceStepDone(match, arguments, duration); } else { testTracer.TraceStepSkipped(); } } catch(PendingStepException) { Debug.Assert(match != null); Debug.Assert(arguments != null); testTracer.TraceStepPending(match, arguments); contextManager.ScenarioContext.PendingSteps.Add( stepFormatter.GetMatchText(match, arguments)); if (contextManager.ScenarioContext.TestStatus < TestStatus.StepDefinitionPending) contextManager.ScenarioContext.TestStatus = TestStatus.StepDefinitionPending; } catch(MissingStepDefinitionException) { if (contextManager.ScenarioContext.TestStatus < TestStatus.MissingStepDefinition) contextManager.ScenarioContext.TestStatus = TestStatus.MissingStepDefinition; } catch(BindingException ex) { testTracer.TraceBindingError(ex); if (contextManager.ScenarioContext.TestStatus < TestStatus.BindingError) { contextManager.ScenarioContext.TestStatus = TestStatus.BindingError; contextManager.ScenarioContext.TestError = ex; } } catch(Exception ex) { testTracer.TraceError(ex); if (contextManager.ScenarioContext.TestStatus < TestStatus.TestError) { contextManager.ScenarioContext.TestStatus = TestStatus.TestError; contextManager.ScenarioContext.TestError = ex; } if (runtimeConfiguration.StopAtFirstError) throw; } }
public void Produces_CSharp_Method_Skeleton_With_Parsed_Booleans() { var expected = new StringBuilder(); expected.Append( @"[Given(@""I can parse booleans such as """"(True|False)"""" and """"(True|False)"""""")] public void GivenICanParseBooleansSuchAsAnd(bool bool1, bool bool2) { ScenarioContext.Current.Pending(); } "); var stepArgs = new StepArgs(BindingType.Given, StepDefinitionKeyword.Given, "I can parse booleans such as \"True\" and \"False\"", null, null, null); string result = skeletonProviderCS.GetStepDefinitionSkeleton(stepArgs); Assert.AreEqual(expected.ToString(), result); }
private List<BindingMatch> GetMatchesWithoutScopeCheck(StepArgs stepArgs) { return bindingRegistry.Where(b => b.Type == stepArgs.Type).Select(binding => Match(binding, stepArgs, true, false)).Where(match => match != null).ToList(); }
private BindingMatch GetStepMatch(StepArgs stepArgs) { List<BindingMatch> matches = stepDefinitionMatcher.GetMatches(stepArgs); if (matches.Count == 0) { // there were either no regex match or it was filtered out by the param/scope matching // to provide better error message for the param matching error, we re-run // the matching without param check List<BindingMatch> matchesWithoutScopeCheck = stepDefinitionMatcher.GetMatchesWithoutScopeCheck(stepArgs); if (matchesWithoutScopeCheck.Count == 0) { List<BindingMatch> matchesWithoutParamCheck = stepDefinitionMatcher.GetMatchesWithoutParamCheck(stepArgs); if (matchesWithoutParamCheck.Count == 1) { // no ambiguouity, but param error -> execute will find it out return matchesWithoutParamCheck[0]; } if (matchesWithoutParamCheck.Count > 1) { // ambiguouity, because of param error throw errorProvider.GetAmbiguousBecauseParamCheckMatchError(matchesWithoutParamCheck, stepArgs); } } testTracer.TraceNoMatchingStepDefinition(stepArgs, contextManager.FeatureContext.FeatureInfo.GenerationTargetLanguage, matchesWithoutScopeCheck); contextManager.ScenarioContext.MissingSteps.Add( currentStepDefinitionSkeletonProvider.GetStepDefinitionSkeleton(stepArgs)); throw errorProvider.GetMissingStepDefinitionError(); } if (matches.Count > 1) { if (runtimeConfiguration.DetectAmbiguousMatches) throw errorProvider.GetAmbiguousMatchError(matches, stepArgs); } return matches[0]; }