Best Gherkin-dotnet code snippet using Gherkin.Ast.Feature.Feature
ScenarioOutlineExecutorTests.cs
Source:ScenarioOutlineExecutorTests.cs  
...10namespace UnitTests11{12    public sealed class ScenarioOutlineExecutorTests13    {14        private readonly Mock<IFeatureFileRepository> _featureFileRepository = new Mock<IFeatureFileRepository>();15        private readonly ScenarioOutlineExecutor _sut;16        public ScenarioOutlineExecutorTests()17        {18            _sut = new ScenarioOutlineExecutor(_featureFileRepository.Object);19        }20        [Fact]21        public async Task ExecuteScenarioOutlineAsync_Requires_FeatureInstance()22        {23            //act / assert.24            await Assert.ThrowsAsync<ArgumentNullException>(async () => await _sut.ExecuteScenarioOutlineAsync(null, "scenario name", "example name", 0));25        }26        [Theory]27        [InlineData(null, "example name", 0, typeof(ArgumentNullException))]28        [InlineData("", "example name", 0, typeof(ArgumentNullException))]29        [InlineData("   ", "example name", 0, typeof(ArgumentNullException))]30        [InlineData("scenario name", "example name", -1, typeof(ArgumentException))]31        public async Task ExecuteScenarioOutlineAsync_Requires_Arguments(32            string scenarioOutlineName,33            string exampleName,34            int exampleRowIndex,35            Type expectedExceptionType)36        {37            //arrange.38            var featureInstance = new FeatureForNullArgumentTests();39            //act / assert.40            await Assert.ThrowsAsync(expectedExceptionType, async () => await _sut.ExecuteScenarioOutlineAsync(featureInstance, scenarioOutlineName, exampleName, exampleRowIndex));41        }42        private sealed class FeatureForNullArgumentTests : Feature43        { }44		[Fact]45		public async Task ScenarioOutline_Runs_Background_Steps_First()46		{47			var feature = new GherkinFeatureBuilder()48				.WithBackground(sb => sb49					.Given("background", null))50				.WithScenarioOutline("test outline", sb => sb51					.Given("I chose <a> as first number", null)52					.And("I chose <b> as second number", null)53					.When("I press add", null)54					.Then("the result should be <sum> on the screen", null),55					 eb => eb56						.WithExampleHeadings("a", "b", "sum")57						.WithExamples("", db => db.WithData("1", "2", "3")))58				.Build();59			60			_featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithScenarioSteps)}.feature"))61				.Returns(new FeatureFile(new Gherkin.Ast.GherkinDocument(feature, new Gherkin.Ast.Comment[0])))62				.Verifiable();63			var featureInstance = new FeatureWithScenarioSteps();64			var output = new Mock<ITestOutputHelper>();65			featureInstance.InternalOutput = output.Object;66		67			await _sut.ExecuteScenarioOutlineAsync(featureInstance, "test outline", "", 0);68            _featureFileRepository.Verify();69			Assert.Equal(5, featureInstance.CallStack.Count);70			Assert.Equal(nameof(FeatureWithScenarioSteps.BackgroundStep), featureInstance.CallStack[0].Key);71		}72        [Theory]73        [InlineData("", 0, 0, 1, 1)]74        [InlineData("", 1, 1, 9, 10)]75        [InlineData("of bigger numbers", 0, 99, 1, 100)]76        [InlineData("of bigger numbers", 1, 100, 200, 300)]77        [InlineData("of large numbers", 0, 999, 1, 1000)]78        [InlineData("of large numbers", 1, 9999, 1, 10000)]79        public async Task ExecuteScenarioOutlineAsync_Executes_All_Scenario_Steps(80            string exampleName,81            int exampleRowIndex,82            int a,83            int b,84            int sum85            )86        {87            //arrange.88            var step1Text = "Given " + FeatureWithScenarioSteps.ScenarioStep1Text.Replace(@"(\d+)", $"{a}", StringComparison.InvariantCultureIgnoreCase);89            var step2Text = "And " + FeatureWithScenarioSteps.ScenarioStep2Text.Replace(@"(\d+)", $"{b}", StringComparison.InvariantCultureIgnoreCase);90            var step3Text = "When " + FeatureWithScenarioSteps.ScenarioStep3Text;91            var step4Text = "Then " + FeatureWithScenarioSteps.ScenarioStep4Text.Replace(@"(\d+)", $"{sum}", StringComparison.InvariantCultureIgnoreCase);92            var scenarioOutlineName = "scenario 12345";93            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithScenarioSteps)}.feature"))94                .Returns(new FeatureFile(CreateGherkinDocument(scenarioOutlineName)))95                .Verifiable();96            var featureInstance = new FeatureWithScenarioSteps();97            var output = new Mock<ITestOutputHelper>();98            featureInstance.InternalOutput = output.Object;99            //act.100            await _sut.ExecuteScenarioOutlineAsync(featureInstance, scenarioOutlineName, exampleName, exampleRowIndex);101            //assert.102            _featureFileRepository.Verify();103            Assert.Equal(4, featureInstance.CallStack.Count);104            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep1), featureInstance.CallStack[0].Key);105            Assert.NotNull(featureInstance.CallStack[0].Value);106            Assert.Single(featureInstance.CallStack[0].Value);107            Assert.Equal(a, featureInstance.CallStack[0].Value[0]);108            output.Verify(o => o.WriteLine($"{step1Text}: PASSED"), Times.Once);109            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep2), featureInstance.CallStack[1].Key);110            Assert.NotNull(featureInstance.CallStack[1].Value);111            Assert.Single(featureInstance.CallStack[1].Value);112            Assert.Equal(b, featureInstance.CallStack[1].Value[0]);113            output.Verify(o => o.WriteLine($"{step2Text}: PASSED"), Times.Once);114            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep3), featureInstance.CallStack[2].Key);115            Assert.Null(featureInstance.CallStack[2].Value);116            output.Verify(o => o.WriteLine($"{step3Text}: PASSED"), Times.Once);117            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep4), featureInstance.CallStack[3].Key);118            Assert.NotNull(featureInstance.CallStack[3].Value);119            Assert.Single(featureInstance.CallStack[3].Value);120            Assert.Equal(sum, featureInstance.CallStack[3].Value[0]);121            output.Verify(o => o.WriteLine($"{step4Text}: PASSED"), Times.Once);122        }123        private static Gherkin.Ast.GherkinDocument CreateGherkinDocument(124            string outlineName,125            Gherkin.Ast.StepArgument stepArgument = null)126        {127			return new Gherkin.Ast.GherkinDocument(128				new GherkinFeatureBuilder()					129					.WithScenarioOutline(outlineName, sb => sb130						.Given("I chose <a> as first number", stepArgument)131						.And("I chose <b> as second number", stepArgument)132						.When("I press add", stepArgument)133						.Then("the result should be <sum> on the screen", stepArgument),134							eb => eb135							.WithExampleHeadings("a", "b", "sum")136							.WithExamples("", db => db137								.WithData(0, 1, 1)138								.WithData(1, 9, 10))139							.WithExamples("of bigger numbers", db => db140								.WithData(99, 1, 100)141								.WithData(100, 200, 300))142							.WithExamples("of large numbers", db => db143								.WithData(999, 1, 1000)144								.WithData(9999, 1, 10000)))145					.Build(),					146					new Gherkin.Ast.Comment[0]);147        }148        private sealed class FeatureWithScenarioSteps : Feature149        {150            public List<KeyValuePair<string, object[]>> CallStack { get; } = new List<KeyValuePair<string, object[]>>();151			[Given("background")]152			public void BackgroundStep()153			{154				CallStack.Add(new KeyValuePair<string, object[]>(nameof(BackgroundStep), null));155			}156            [Given("Non matching given")]157            public void NonMatchingStep1_before()158            {159                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_before), null));160            }161            public const string ScenarioStep1Text = @"I chose (\d+) as first number";162            [Given(ScenarioStep1Text)]163            public void ScenarioStep1(int firstNumber)164            {165                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep1), new object[] { firstNumber }));166            }167            [Given("Non matching given")]168            public void NonMatchingStep1_after()169            {170                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_after), null));171            }172            [And("Non matching and")]173            public void NonMatchingStep2_before()174            {175                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_before), null));176            }177            public const string ScenarioStep2Text = @"I chose (\d+) as second number";178            [And(ScenarioStep2Text)]179            public void ScenarioStep2(int secondNumber)180            {181                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep2), new object[] { secondNumber }));182            }183            [And("Non matching and")]184            public void NonMatchingStep2_after()185            {186                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_after), null));187            }188            [When("Non matching when")]189            public void NonMatchingStep3_before()190            {191                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_before), null));192            }193            public const string ScenarioStep3Text = "I press add";194            [When(ScenarioStep3Text)]195            public void ScenarioStep3()196            {197                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep3), null));198            }199            [When("Non matching when")]200            public void NonMatchingStep3_after()201            {202                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_after), null));203            }204            [Then("Non matching then")]205            public void NonMatchingStep4_before()206            {207                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_before), null));208            }209            public const string ScenarioStep4Text = @"the result should be (\d+) on the screen";210            [Then(ScenarioStep4Text)]211            public void ScenarioStep4(int result)212            {213                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep4), new object[] { result }));214            }215            [Then("Non matching then")]216            public void NonMatchingStep4_after()217            {218                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_after), null));219            }220        }221        [Theory]222        [InlineData("", 0, 0, 1, 1)]223        [InlineData("", 1, 1, 9, 10)]224        [InlineData("of bigger numbers", 0, 99, 1, 100)]225        [InlineData("of bigger numbers", 1, 100, 200, 300)]226        [InlineData("of large numbers", 0, 999, 1, 1000)]227        [InlineData("of large numbers", 1, 9999, 1, 10000)]228        public async Task ExecuteScenarioOutlineAsync_Executes_Successful_Scenario_Steps_And_Skips_The_Rest(229            string exampleName,230            int exampleRowIndex,231            int a,232            int b,233            int sum234            )235        {236            //arrange.237            var step1Text = "Given " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep1Text.Replace(@"(\d+)", $"{a}", StringComparison.InvariantCultureIgnoreCase);238            var step2Text = "And " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep2Text.Replace(@"(\d+)", $"{b}", StringComparison.InvariantCultureIgnoreCase);239            var step3Text = "When " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep3Text;240            var step4Text = "Then " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep4Text.Replace(@"(\d+)", $"{sum}", StringComparison.InvariantCultureIgnoreCase);241            var outlineName = "scenario 12345";242            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithScenarioSteps_And_Throwing)}.feature"))243                .Returns(new FeatureFile(CreateGherkinDocument(outlineName)))244                .Verifiable();245            var featureInstance = new FeatureWithScenarioSteps_And_Throwing();246            var output = new Mock<ITestOutputHelper>();247            featureInstance.InternalOutput = output.Object;248            //act.249            var exceptiion = await Assert.ThrowsAsync<TargetInvocationException>(async () => await _sut.ExecuteScenarioOutlineAsync(featureInstance, outlineName, exampleName, exampleRowIndex));250            Assert.IsType<InvalidOperationException>(exceptiion.InnerException);251            //assert.252            _featureFileRepository.Verify();253            Assert.Equal(2, featureInstance.CallStack.Count);254            Assert.Equal(nameof(FeatureWithScenarioSteps_And_Throwing.ScenarioStep1), featureInstance.CallStack[0].Key);255            Assert.NotNull(featureInstance.CallStack[0].Value);256            Assert.Single(featureInstance.CallStack[0].Value);257            Assert.Equal(a, featureInstance.CallStack[0].Value[0]);258            output.Verify(o => o.WriteLine($"{step1Text}: PASSED"), Times.Once);259            Assert.Equal(nameof(FeatureWithScenarioSteps_And_Throwing.ScenarioStep2), featureInstance.CallStack[1].Key);260            Assert.NotNull(featureInstance.CallStack[1].Value);261            Assert.Single(featureInstance.CallStack[1].Value);262            Assert.Equal(b, featureInstance.CallStack[1].Value[0]);263            output.Verify(o => o.WriteLine($"{step2Text}: FAILED"), Times.Once);264            output.Verify(o => o.WriteLine($"{step3Text}: SKIPPED"), Times.Once);265            output.Verify(o => o.WriteLine($"{step4Text}: SKIPPED"), Times.Once);266        }267        private sealed class FeatureWithScenarioSteps_And_Throwing : Feature268        {269            public List<KeyValuePair<string, object[]>> CallStack { get; } = new List<KeyValuePair<string, object[]>>();270            [Given("Non matching given")]271            public void NonMatchingStep1_before()272            {273                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_before), null));274            }275            public const string ScenarioStep1Text = @"I chose (\d+) as first number";276            [Given(ScenarioStep1Text)]277            public void ScenarioStep1(int firstNumber)278            {279                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep1), new object[] { firstNumber }));280            }281            [Given("Non matching given")]282            public void NonMatchingStep1_after()283            {284                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_after), null));285            }286            [And("Non matching and")]287            public void NonMatchingStep2_before()288            {289                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_before), null));290            }291            public const string ScenarioStep2Text = @"I chose (\d+) as second number";292            [And(ScenarioStep2Text)]293            public void ScenarioStep2(int secondNumber)294            {295                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep2), new object[] { secondNumber }));296                throw new InvalidOperationException("Some exception to stop execution of next steps.");297            }298            [And("Non matching and")]299            public void NonMatchingStep2_after()300            {301                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_after), null));302            }303            [When("Non matching when")]304            public void NonMatchingStep3_before()305            {306                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_before), null));307            }308            public const string ScenarioStep3Text = "I press add";309            [When(ScenarioStep3Text)]310            public void ScenarioStep3()311            {312                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep3), null));313            }314            [When("Non matching when")]315            public void NonMatchingStep3_after()316            {317                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_after), null));318            }319            [Then("Non matching then")]320            public void NonMatchingStep4_before()321            {322                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_before), null));323            }324            public const string ScenarioStep4Text = @"the result should be (\d+) on the screen";325            [Then(ScenarioStep4Text)]326            public void ScenarioStep4(int result)327            {328                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep4), new object[] { result }));329            }330            [Then("Non matching then")]331            public void NonMatchingStep4_after()332            {333                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_after), null));334            }335        }336        [Theory]337        [InlineData("", 0)]338        [InlineData("", 1)]339        [InlineData("of bigger numbers", 0)]340        [InlineData("of bigger numbers", 1)]341        [InlineData("of large numbers", 0)]342        [InlineData("of large numbers", 1)]343        public async Task ExecuteScenarioOutlineAsync_Executes_ScenarioStep_With_DataTable(344            string exampleName,345            int exampleRowIndex)346        {347            //arrange.348            var scenarioName = "scenario123";349            var featureInstance = new FeatureWithDataTableScenarioStep();350            var output = new Mock<ITestOutputHelper>();351            featureInstance.InternalOutput = output.Object;352            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithDataTableScenarioStep)}.feature"))353                .Returns(new FeatureFile(FeatureWithDataTableScenarioStep.CreateGherkinDocument(scenarioName,354                    new Gherkin.Ast.DataTable(new Gherkin.Ast.TableRow[]355                    {356                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]357                        {358                            new Gherkin.Ast.TableCell(null, "First argument"),359                            new Gherkin.Ast.TableCell(null, "Second argument"),360                            new Gherkin.Ast.TableCell(null, "Result"),361                        }),362                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]363                        {364                            new Gherkin.Ast.TableCell(null, "1"),365                            new Gherkin.Ast.TableCell(null, "2"),366                            new Gherkin.Ast.TableCell(null, "3"),367                        }),368                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]369                        {370                            new Gherkin.Ast.TableCell(null, "a"),371                            new Gherkin.Ast.TableCell(null, "b"),372                            new Gherkin.Ast.TableCell(null, "c"),373                        })374                    }))))375                    .Verifiable();376            //act.377            await _sut.ExecuteScenarioOutlineAsync(featureInstance, scenarioName, exampleName, exampleRowIndex);378            //assert.379            _featureFileRepository.Verify();380            Assert.NotNull(featureInstance.ReceivedDataTable);381            Assert.Equal(3, featureInstance.ReceivedDataTable.Rows.Count());382            AssertDataTableCell(0, 0, "First argument");383            AssertDataTableCell(0, 1, "Second argument");384            AssertDataTableCell(0, 2, "Result");385            AssertDataTableCell(1, 0, "1");386            AssertDataTableCell(1, 1, "2");387            AssertDataTableCell(1, 2, "3");388            AssertDataTableCell(2, 0, "a");389            AssertDataTableCell(2, 1, "b");390            AssertDataTableCell(2, 2, "c");391            void AssertDataTableCell(int rowIndex, int cellIndex, string value)392            {393                Assert.True(featureInstance.ReceivedDataTable.Rows.Count() > rowIndex);394                Assert.NotNull(featureInstance.ReceivedDataTable.Rows.ElementAt(rowIndex));395                Assert.True(featureInstance.ReceivedDataTable.Rows.ElementAt(rowIndex).Cells.Count() > cellIndex);396                Assert.NotNull(featureInstance.ReceivedDataTable.Rows.ElementAt(rowIndex).Cells.ElementAt(cellIndex));397                Assert.Equal("First argument", featureInstance.ReceivedDataTable.Rows.ElementAt(0).Cells.ElementAt(0).Value);398            }399        }400        private sealed class FeatureWithDataTableScenarioStep : Feature401        {402            public Gherkin.Ast.DataTable ReceivedDataTable { get; private set; }403            public const string Steptext = @"Step text 1212121";404            [Given(Steptext)]405            public void When_DataTable_Is_Expected(Gherkin.Ast.DataTable dataTable)406            {407                ReceivedDataTable = dataTable;408            }409            public static Gherkin.Ast.GherkinDocument CreateGherkinDocument(410                string outlineName,411                Gherkin.Ast.StepArgument stepArgument = null)412            {413                return new Gherkin.Ast.GherkinDocument(414                    new Gherkin.Ast.Feature(new Gherkin.Ast.Tag[0], null, null, null, null, null, new Gherkin.Ast.ScenarioDefinition[]415                    {416                    new Gherkin.Ast.ScenarioOutline(417                        new Gherkin.Ast.Tag[0],418                        null,419                        null,420                        outlineName,421                        null,422                        new Gherkin.Ast.Step[]423                        {424                            new Gherkin.Ast.Step(null, "Given", Steptext, stepArgument)425                        },426                        new Gherkin.Ast.Examples[]427                        {428                            new Gherkin.Ast.Examples(null, null, null, "", null,429                                new Gherkin.Ast.TableRow(null,430                                    new Gherkin.Ast.TableCell[]431                                    {432                                        new Gherkin.Ast.TableCell(null, "a"),433                                        new Gherkin.Ast.TableCell(null, "b"),434                                        new Gherkin.Ast.TableCell(null, "sum"),435                                    }),436                                new Gherkin.Ast.TableRow[]437                                {438                                    new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]439                                    {440                                        new Gherkin.Ast.TableCell(null, "0"),441                                        new Gherkin.Ast.TableCell(null, "1"),442                                        new Gherkin.Ast.TableCell(null, "1")443                                    }),444                                    new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]445                                    {446                                        new Gherkin.Ast.TableCell(null, "1"),447                                        new Gherkin.Ast.TableCell(null, "9"),448                                        new Gherkin.Ast.TableCell(null, "10")449                                    })450                                }),451                            new Gherkin.Ast.Examples(null, null, null, "of bigger numbers", null,452                                new Gherkin.Ast.TableRow(null,453                                    new Gherkin.Ast.TableCell[]454                                    {455                                        new Gherkin.Ast.TableCell(null, "a"),456                                        new Gherkin.Ast.TableCell(null, "b"),457                                        new Gherkin.Ast.TableCell(null, "sum"),458                                    }),459                                new Gherkin.Ast.TableRow[]460                                {461                                    new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]462                                    {463                                        new Gherkin.Ast.TableCell(null, "99"),464                                        new Gherkin.Ast.TableCell(null, "1"),465                                        new Gherkin.Ast.TableCell(null, "100")466                                    }),467                                    new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]468                                    {469                                        new Gherkin.Ast.TableCell(null, "100"),470                                        new Gherkin.Ast.TableCell(null, "200"),471                                        new Gherkin.Ast.TableCell(null, "300")472                                    })473                                }),474                            new Gherkin.Ast.Examples(null, null, null, "of large numbers", null,475                                new Gherkin.Ast.TableRow(null,476                                    new Gherkin.Ast.TableCell[]477                                    {478                                        new Gherkin.Ast.TableCell(null, "a"),479                                        new Gherkin.Ast.TableCell(null, "b"),480                                        new Gherkin.Ast.TableCell(null, "sum"),481                                    }),482                                new Gherkin.Ast.TableRow[]483                                {484                                    new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]485                                    {486                                        new Gherkin.Ast.TableCell(null, "999"),487                                        new Gherkin.Ast.TableCell(null, "1"),488                                        new Gherkin.Ast.TableCell(null, "1000")489                                    }),490                                    new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]491                                    {492                                        new Gherkin.Ast.TableCell(null, "9999"),493                                        new Gherkin.Ast.TableCell(null, "1"),494                                        new Gherkin.Ast.TableCell(null, "10000")495                                    })496                                })497                        })498                    }),499                    new Gherkin.Ast.Comment[0]);500            }501        }502        [Theory]503        [InlineData("", 0)]504        [InlineData("", 1)]505        [InlineData("of bigger numbers", 0)]506        [InlineData("of bigger numbers", 1)]507        [InlineData("of large numbers", 0)]508        [InlineData("of large numbers", 1)]509        public async Task ExecuteScenarioOutlineAsync_Executes_ScenarioStep_With_DocString(510            string exampleName,511            int exampleRowIndex)512        {513            //arrange.514            var scenarioName = "scenario123";515            var featureInstance = new FeatureWithDocStringScenarioStep();516            var output = new Mock<ITestOutputHelper>();517            featureInstance.InternalOutput = output.Object;518            var docStringContent = "some content" + Environment.NewLine +519"+++" + Environment.NewLine +520"with multi lines" + Environment.NewLine +521"---" + Environment.NewLine +522"in it";523            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithDocStringScenarioStep)}.feature"))524                .Returns(new FeatureFile(FeatureWithDocStringScenarioStep.CreateGherkinDocument(scenarioName,525                    new Gherkin.Ast.DocString(null, null, docStringContent))))526                    .Verifiable();527            //act.528            await _sut.ExecuteScenarioOutlineAsync(featureInstance, scenarioName, exampleName, exampleRowIndex);529            //assert.530            _featureFileRepository.Verify();531            Assert.NotNull(featureInstance.ReceivedDocString);532            Assert.Equal(docStringContent, featureInstance.ReceivedDocString.Content);533        }534        private sealed class FeatureWithDocStringScenarioStep : Feature535        {536            public Gherkin.Ast.DocString ReceivedDocString { get; private set; }537            public const string Steptext = @"Step text 1212121";538            [Given(Steptext)]539            public void When_DocString_Is_Expected(Gherkin.Ast.DocString docString)540            {541                ReceivedDocString = docString;542            }543            public static Gherkin.Ast.GherkinDocument CreateGherkinDocument(544                string outlineName,545                Gherkin.Ast.StepArgument stepArgument = null)546            {547                return new Gherkin.Ast.GherkinDocument(548                    new Gherkin.Ast.Feature(new Gherkin.Ast.Tag[0], null, null, null, null, null, new Gherkin.Ast.ScenarioDefinition[]549                    {550                    new Gherkin.Ast.ScenarioOutline(551                        new Gherkin.Ast.Tag[0],552                        null,553                        null,554                        outlineName,555                        null,556                        new Gherkin.Ast.Step[]557                        {558                            new Gherkin.Ast.Step(null, "Given", Steptext, stepArgument)559                        },560                        new Gherkin.Ast.Examples[]561                        {562                            new Gherkin.Ast.Examples(null, null, null, "", null,...ScenarioExecutorTests.cs
Source:ScenarioExecutorTests.cs  
...10namespace UnitTests11{12    public sealed class ScenarioExecutorTests13    {14        private readonly Mock<IFeatureFileRepository> _featureFileRepository = new Mock<IFeatureFileRepository>();15        private readonly ScenarioExecutor _sut;16        public ScenarioExecutorTests()17        {18            _sut = new ScenarioExecutor(_featureFileRepository.Object);19        }20        [Fact]21        public async Task ExecuteScenario_Requires_FeatureInstance()22        {23            //act / assert.24            await Assert.ThrowsAsync<ArgumentNullException>(async () => await _sut.ExecuteScenarioAsync(null, "valid scenario name"));25        }26        [Theory]27        [InlineData(null)]28        [InlineData("")]29        [InlineData(" ")]30        [InlineData("                 ")]31        public async Task ExecuteScenario_Requires_ScenarioName(string scenarioName)32        {33            //arrange.34            var featureInstance = new UselessFeature();35            //act / assert.36            await Assert.ThrowsAsync<ArgumentNullException>(async () => await _sut.ExecuteScenarioAsync(featureInstance, scenarioName));37        }38        private sealed class UselessFeature : Feature { }		39        [Fact]40        public async Task ExecuteScenario_Executes_All_Scenario_Steps()41        {42            //arrange.43            var step1Text = "Given " + FeatureWithScenarioSteps.ScenarioStep1Text.Replace(@"(\d+)", "12", StringComparison.InvariantCultureIgnoreCase);44            var step2Text = "And " + FeatureWithScenarioSteps.ScenarioStep2Text.Replace(@"(\d+)", "15", StringComparison.InvariantCultureIgnoreCase);45            var step3Text = "When " + FeatureWithScenarioSteps.ScenarioStep3Text;46            var step4Text = "Then " + FeatureWithScenarioSteps.ScenarioStep4Text.Replace(@"(\d+)", "27", StringComparison.InvariantCultureIgnoreCase);47            var scenarioName = "scenario 12345";48            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithScenarioSteps)}.feature"))49                .Returns(new FeatureFile(CreateGherkinDocument(scenarioName,50                    new string[] 51                    {52                        step1Text,53                        step2Text,54                        step3Text,55                        step4Text56                    })))57                .Verifiable();58            var featureInstance = new FeatureWithScenarioSteps();59            var output = new Mock<ITestOutputHelper>();60            featureInstance.InternalOutput = output.Object;61            //act.62            await _sut.ExecuteScenarioAsync(featureInstance, scenarioName);63            //assert.64            _featureFileRepository.Verify();65            Assert.Equal(4, featureInstance.CallStack.Count);66            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep1), featureInstance.CallStack[0].Key);67            Assert.NotNull(featureInstance.CallStack[0].Value);68            Assert.Single(featureInstance.CallStack[0].Value);69            Assert.Equal(12, featureInstance.CallStack[0].Value[0]);70            output.Verify(o => o.WriteLine($"{step1Text}: PASSED"), Times.Once);71            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep2), featureInstance.CallStack[1].Key);72            Assert.NotNull(featureInstance.CallStack[1].Value);73            Assert.Single(featureInstance.CallStack[1].Value);74            Assert.Equal(15, featureInstance.CallStack[1].Value[0]);75            output.Verify(o => o.WriteLine($"{step2Text}: PASSED"), Times.Once);76            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep3), featureInstance.CallStack[2].Key);77            Assert.Null(featureInstance.CallStack[2].Value);78            output.Verify(o => o.WriteLine($"{step3Text}: PASSED"), Times.Once);79            Assert.Equal(nameof(FeatureWithScenarioSteps.ScenarioStep4), featureInstance.CallStack[3].Key);80            Assert.NotNull(featureInstance.CallStack[3].Value);81            Assert.Single(featureInstance.CallStack[3].Value);82            Assert.Equal(27, featureInstance.CallStack[3].Value[0]);83            output.Verify(o => o.WriteLine($"{step4Text}: PASSED"), Times.Once);84        }85        private static Gherkin.Ast.GherkinDocument CreateGherkinDocument(86            string scenario, 87            string[] steps,88            Gherkin.Ast.StepArgument stepArgument = null)89        {90            return new Gherkin.Ast.GherkinDocument(91                new Gherkin.Ast.Feature(new Gherkin.Ast.Tag[0], null, null, null, null, null, new Gherkin.Ast.ScenarioDefinition[] 92                {93                    new Gherkin.Ast.Scenario(94                        new Gherkin.Ast.Tag[0], 95                        null, 96                        null, 97                        scenario, 98                        null, 99                        steps.Select(s => 100                        {101                            var spaceIndex = s.IndexOf(' ');102                            return new Gherkin.Ast.Step(103                                null, 104                                s.Substring(0, spaceIndex).Trim(), 105                                s.Substring(spaceIndex).Trim(), 106                                stepArgument);107                        }).ToArray())108                }),109                new Gherkin.Ast.Comment[0]);110        }111        private sealed class FeatureWithScenarioSteps : Feature112        {113            public List<KeyValuePair<string, object[]>> CallStack { get; } = new List<KeyValuePair<string, object[]>>();114            [Given("Non matching given")]115            public void NonMatchingStep1_before()116            {117                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_before), null));118            }119            public const string ScenarioStep1Text = @"I chose (\d+) as first number";120            [Given(ScenarioStep1Text)]121            public void ScenarioStep1(int firstNumber)122            {123                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep1), new object[] { firstNumber }));124            }125            [Given("Non matching given")]126            public void NonMatchingStep1_after()127            {128                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_after), null));129            }130            [And("Non matching and")]131            public void NonMatchingStep2_before()132            {133                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_before), null));134            }135            public const string ScenarioStep2Text = @"I chose (\d+) as second number";136            [And(ScenarioStep2Text)]137            public void ScenarioStep2(int secondNumber)138            {139                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep2), new object[] { secondNumber }));140            }141            [And("Non matching and")]142            public void NonMatchingStep2_after()143            {144                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_after), null));145            }146            [When("Non matching when")]147            public void NonMatchingStep3_before()148            {149                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_before), null));150            }151            public const string ScenarioStep3Text = "I press add";152            [When(ScenarioStep3Text)]153            public void ScenarioStep3()154            {155                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep3), null));156            }157            [When("Non matching when")]158            public void NonMatchingStep3_after()159            {160                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_after), null));161            }162            [Then("Non matching then")]163            public void NonMatchingStep4_before()164            {165                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_before), null));166            }167            public const string ScenarioStep4Text = @"the result should be (\d+) on the screen";168            [Then(ScenarioStep4Text)]169            public void ScenarioStep4(int result)170            {171                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep4), new object[] { result }));172            }173            [Then("Non matching then")]174            public void NonMatchingStep4_after()175            {176                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_after), null));177            }178        }179        [Fact]180        public async Task ExecuteScenario_Executes_Successful_Scenario_Steps_And_Skips_The_Rest()181        {182            //arrange.183            var step1Text = "Given " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep1Text.Replace(@"(\d+)", "12", StringComparison.InvariantCultureIgnoreCase);184            var step2Text = "And " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep2Text.Replace(@"(\d+)", "15", StringComparison.InvariantCultureIgnoreCase);185            var step3Text = "When " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep3Text;186            var step4Text = "Then " + FeatureWithScenarioSteps_And_Throwing.ScenarioStep4Text.Replace(@"(\d+)", "27", StringComparison.InvariantCultureIgnoreCase);187            var scenarioName = "scenario 12345";188            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithScenarioSteps_And_Throwing)}.feature"))189                .Returns(new FeatureFile(CreateGherkinDocument(scenarioName,190                    new string[] 191                    {192                        step1Text,193                        step2Text,194                        step3Text,195                        step4Text196                    })))197                .Verifiable();198            var featureInstance = new FeatureWithScenarioSteps_And_Throwing();199            var output = new Mock<ITestOutputHelper>();200            featureInstance.InternalOutput = output.Object;201            //act.202            var exceptiion = await Assert.ThrowsAsync<TargetInvocationException>(async () => await _sut.ExecuteScenarioAsync(featureInstance, scenarioName));203            Assert.IsType<InvalidOperationException>(exceptiion.InnerException);204            //assert.205            _featureFileRepository.Verify();206            Assert.Equal(2, featureInstance.CallStack.Count);207            Assert.Equal(nameof(FeatureWithScenarioSteps_And_Throwing.ScenarioStep1), featureInstance.CallStack[0].Key);208            Assert.NotNull(featureInstance.CallStack[0].Value);209            Assert.Single(featureInstance.CallStack[0].Value);210            Assert.Equal(12, featureInstance.CallStack[0].Value[0]);211            output.Verify(o => o.WriteLine($"{step1Text}: PASSED"), Times.Once);212            Assert.Equal(nameof(FeatureWithScenarioSteps_And_Throwing.ScenarioStep2), featureInstance.CallStack[1].Key);213            Assert.NotNull(featureInstance.CallStack[1].Value);214            Assert.Single(featureInstance.CallStack[1].Value);215            Assert.Equal(15, featureInstance.CallStack[1].Value[0]);216            output.Verify(o => o.WriteLine($"{step2Text}: FAILED"), Times.Once);217            output.Verify(o => o.WriteLine($"{step3Text}: SKIPPED"), Times.Once);218            output.Verify(o => o.WriteLine($"{step4Text}: SKIPPED"), Times.Once);219        }220        private sealed class FeatureWithScenarioSteps_And_Throwing : Feature221        {222            public List<KeyValuePair<string, object[]>> CallStack { get; } = new List<KeyValuePair<string, object[]>>();223            [Given("Non matching given")]224            public void NonMatchingStep1_before()225            {226                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_before), null));227            }228            public const string ScenarioStep1Text = @"I chose (\d+) as first number";229            [Given(ScenarioStep1Text)]230            public void ScenarioStep1(int firstNumber)231            {232                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep1), new object[] { firstNumber }));233            }234            [Given("Non matching given")]235            public void NonMatchingStep1_after()236            {237                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_after), null));238            }239            [And("Non matching and")]240            public void NonMatchingStep2_before()241            {242                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_before), null));243            }244            public const string ScenarioStep2Text = @"I chose (\d+) as second number";245            [And(ScenarioStep2Text)]246            public void ScenarioStep2(int secondNumber)247            {248                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep2), new object[] { secondNumber }));249                throw new InvalidOperationException("Some exception to stop execution of next steps.");250            }251            [And("Non matching and")]252            public void NonMatchingStep2_after()253            {254                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_after), null));255            }256            [When("Non matching when")]257            public void NonMatchingStep3_before()258            {259                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_before), null));260            }261            public const string ScenarioStep3Text = "I press add";262            [When(ScenarioStep3Text)]263            public void ScenarioStep3()264            {265                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep3), null));266            }267            [When("Non matching when")]268            public void NonMatchingStep3_after()269            {270                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_after), null));271            }272            [Then("Non matching then")]273            public void NonMatchingStep4_before()274            {275                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_before), null));276            }277            public const string ScenarioStep4Text = @"the result should be (\d+) on the screen";278            [Then(ScenarioStep4Text)]279            public void ScenarioStep4(int result)280            {281                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep4), new object[] { result }));282            }283            [Then("Non matching then")]284            public void NonMatchingStep4_after()285            {286                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_after), null));287            }288        }289		[Fact]290		public async Task ExecuteScenario_Executes_Background_Steps_First()291		{292			var gherkinFeaure = new GherkinFeatureBuilder()293				.WithBackground(sb => sb294					.Given("given background", null)295					.When("when background", null)296					.Then("then background", null))297				.WithScenario("test scenario", sb => sb298					.Then("step one", null))299				.Build();300			var gherkinDocument = new Gherkin.Ast.GherkinDocument(gherkinFeaure, new Gherkin.Ast.Comment[0]);301			_featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithBackgroundSteps)}.feature"))302				.Returns(new FeatureFile(gherkinDocument))303				.Verifiable();304			var featureInstance = new FeatureWithBackgroundSteps();305			var output = new Mock<ITestOutputHelper>();306			featureInstance.InternalOutput = output.Object;307			//act.308			await _sut.ExecuteScenarioAsync(featureInstance, "test scenario");309            //assert.310            _featureFileRepository.Verify();311			Assert.Equal("abcd", featureInstance.OrderValidator);312			output.Verify(o => o.WriteLine($"Given given background: PASSED"), Times.Once);313			output.Verify(o => o.WriteLine($"When when background: PASSED"), Times.Once);314			output.Verify(o => o.WriteLine($"Then then background: PASSED"), Times.Once);315			output.Verify(o => o.WriteLine($"Then step one: PASSED"), Times.Once);316		}317		private sealed class FeatureWithBackgroundSteps : Feature318		{319			public string OrderValidator = String.Empty;320			[Given("given background")]321			public void GivenBackground()322			{323				OrderValidator += "a";324			}325			[When("when background")]326			public void WhenBackground()327			{328				OrderValidator += "b";329			}330			[Then("then background")]331			public void ThenBackground()332			{333				OrderValidator += "c";334			}335			[Then("step one")]336			public void ThenScenario()337			{338				OrderValidator += "d";339			}340		}341		[Fact]342        public async Task ExecuteScenario_Executes_ScenarioStep_With_DataTable()343        {344            //arrange.345            var scenarioName = "scenario123";346            var featureInstance = new FeatureWithDataTableScenarioStep();347            var output = new Mock<ITestOutputHelper>();348            featureInstance.InternalOutput = output.Object;349            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithDataTableScenarioStep)}.feature"))350                .Returns(new FeatureFile(CreateGherkinDocument(scenarioName,351                    new string[] 352                    {353                        "When " + FeatureWithDataTableScenarioStep.Steptext354                    },355                    new Gherkin.Ast.DataTable(new Gherkin.Ast.TableRow[]356                    {357                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]358                        {359                            new Gherkin.Ast.TableCell(null, "First argument"),360                            new Gherkin.Ast.TableCell(null, "Second argument"),361                            new Gherkin.Ast.TableCell(null, "Result"),362                        }),363                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]364                        {365                            new Gherkin.Ast.TableCell(null, "1"),366                            new Gherkin.Ast.TableCell(null, "2"),367                            new Gherkin.Ast.TableCell(null, "3"),368                        }),369                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]370                        {371                            new Gherkin.Ast.TableCell(null, "a"),372                            new Gherkin.Ast.TableCell(null, "b"),373                            new Gherkin.Ast.TableCell(null, "c"),374                        })375                    }))))376                .Verifiable();377            378            //act.379            await _sut.ExecuteScenarioAsync(featureInstance, scenarioName);380            //assert.381            _featureFileRepository.Verify();382            Assert.NotNull(featureInstance.ReceivedDataTable);383            Assert.Equal(3, featureInstance.ReceivedDataTable.Rows.Count());384            AssertDataTableCell(0, 0, "First argument");385            AssertDataTableCell(0, 1, "Second argument");386            AssertDataTableCell(0, 2, "Result");387            AssertDataTableCell(1, 0, "1");388            AssertDataTableCell(1, 1, "2");389            AssertDataTableCell(1, 2, "3");390            AssertDataTableCell(2, 0, "a");391            AssertDataTableCell(2, 1, "b");392            AssertDataTableCell(2, 2, "c");393            void AssertDataTableCell(int rowIndex, int cellIndex, string value)394            {395                Assert.True(featureInstance.ReceivedDataTable.Rows.Count() > rowIndex);396                Assert.NotNull(featureInstance.ReceivedDataTable.Rows.ElementAt(rowIndex));397                Assert.True(featureInstance.ReceivedDataTable.Rows.ElementAt(rowIndex).Cells.Count() > cellIndex);398                Assert.NotNull(featureInstance.ReceivedDataTable.Rows.ElementAt(rowIndex).Cells.ElementAt(cellIndex));399                Assert.Equal("First argument", featureInstance.ReceivedDataTable.Rows.ElementAt(0).Cells.ElementAt(0).Value);400            }401        }402        private sealed class FeatureWithDataTableScenarioStep : Feature403        {404            public Gherkin.Ast.DataTable ReceivedDataTable { get; private set; }405            public const string Steptext = "Some step text";406            [When(Steptext)]407            public void When_DataTable_Is_Expected(Gherkin.Ast.DataTable dataTable)408            {409                ReceivedDataTable = dataTable;410            }411        }412        [Fact]413        public async Task ExecuteScenario_Executes_ScenarioStep_With_DocString()414        {415            //arrange.416            var featureInstance = new FeatureWithDocStringScenarioStep();417            var output = new Mock<ITestOutputHelper>();418            featureInstance.InternalOutput = output.Object;419            var docStringContent = "some content" + Environment.NewLine +420"+++" + Environment.NewLine +421"with multi lines" + Environment.NewLine +422"---" + Environment.NewLine +423"in it";424            var scenarioName = "scenario 1231121";425            _featureFileRepository.Setup(r => r.GetByFilePath(nameof(FeatureWithDocStringScenarioStep) + ".feature"))426                .Returns(new FeatureFile(CreateGherkinDocument(scenarioName,427                    new string[] { "Given " + FeatureWithDocStringScenarioStep.StepWithDocStringText },428                    new Gherkin.Ast.DocString(null, null, docStringContent))))429                .Verifiable();430            //act.431            await _sut.ExecuteScenarioAsync(featureInstance, scenarioName);432            //assert.433            _featureFileRepository.Verify();434            Assert.NotNull(featureInstance.ReceivedDocString);435            Assert.Equal(docStringContent, featureInstance.ReceivedDocString.Content);436        }437        private sealed class FeatureWithDocStringScenarioStep : Feature438        {439            public Gherkin.Ast.DocString ReceivedDocString { get; private set; }440            public const string StepWithDocStringText = "Step with docstirng";441            [Given(StepWithDocStringText)]442            public void Step_With_DocString_Argument(Gherkin.Ast.DocString docString)443            {444                ReceivedDocString = docString;445            }446        }447        [Fact]448        public async Task ExecuteScenario_Executes_Scenario_With_Shared_StepMethod()449        {450            //arrange.451            const string scenarioName = "scenario 123";452            var featureInstance = new FeatureWithSharedStepMethod();453            var output = new Mock<ITestOutputHelper>();454            featureInstance.InternalOutput = output.Object;455            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithSharedStepMethod)}.feature"))456                .Returns(new FeatureFile(CreateGherkinDocument(scenarioName, new string[]457                {458                    "Given I chose 1 as first number",459                    "And I chose 2 as second number",460                    "And I chose 3 as third number",461                    "When I choose 4 as fourth number",462                    "And I choose 5 as fifth number",463                    "And I choose 6 as sixth number",464                    $"Then Result should be {1+2+3+4+5+6} on the screen"465                })));466            //act.467            await _sut.ExecuteScenarioAsync(featureInstance, scenarioName);468            //assert.469            Assert.Equal(7, featureInstance.CallStack.Count);470            Assert_Callback(0, nameof(FeatureWithSharedStepMethod.Selecting_numbers), 1);471            Assert_Callback(1, nameof(FeatureWithSharedStepMethod.Selecting_numbers), 2);472            Assert_Callback(2, nameof(FeatureWithSharedStepMethod.Selecting_numbers), 3);473            Assert_Callback(3, nameof(FeatureWithSharedStepMethod.Selecting_numbers), 4);474            Assert_Callback(4, nameof(FeatureWithSharedStepMethod.Selecting_numbers), 5);475            Assert_Callback(5, nameof(FeatureWithSharedStepMethod.Selecting_numbers), 6);476            Assert_Callback(6, nameof(FeatureWithSharedStepMethod.Result_should_be_x_on_the_screen), (1 + 2 + 3 + 4 + 5 + 6));477            void Assert_Callback(int index, string methodName, int value)478            {479                Assert.Equal(methodName, featureInstance.CallStack[index].Key);480                Assert.NotNull(featureInstance.CallStack[index].Value);481                Assert.Single(featureInstance.CallStack[index].Value);482                Assert.Equal(value, featureInstance.CallStack[index].Value[0]);483            }484        }485        private sealed class FeatureWithSharedStepMethod : Feature486        {487            public List<KeyValuePair<string, object[]>> CallStack { get; } = new List<KeyValuePair<string, object[]>>();488            [Given(@"I chose (\d+) as first number")]489            [And(@"I chose (\d+) as second number")]490            [And(@"I chose (\d+) as third number")]491            [When(@"I choose (\d+) as fourth number")]492            [And(@"I choose (\d+) as fifth number")]493            [And(@"I choose (\d+) as sixth number")]494            public void Selecting_numbers(int x)495            {496                CallStack.Add(new KeyValuePair<string, object[]>(nameof(Selecting_numbers), new object[] { x }));497            }498            [Then(@"Result should be (\d+) on the screen")]499            public void Result_should_be_x_on_the_screen(int x)500            {501                CallStack.Add(new KeyValuePair<string, object[]>(nameof(Result_should_be_x_on_the_screen), new object[] { x }));502            }503        }504        [Fact]505        public async Task ExecuteScenario_Executes_Scenario_With_Star_Notation()506        {507            //arrange.508            var gherkinFeature = new GherkinFeatureBuilder()509                .WithScenario("S", steps => steps.Star("I have some cukes", null))510                .Build();511512            _featureFileRepository.Setup(r => r.GetByFilePath($"{nameof(FeatureWithStarNotation)}.feature"))513                .Returns(new FeatureFile(new Gherkin.Ast.GherkinDocument(gherkinFeature, null)))514                .Verifiable();515516            var featureInstance = new FeatureWithStarNotation();517            var output = new Mock<ITestOutputHelper>();518            featureInstance.InternalOutput = output.Object;519520            //act.521            await _sut.ExecuteScenarioAsync(featureInstance, "S");522523            //assert.524            _featureFileRepository.Verify();525526            Assert.Single(featureInstance.CallStack);527            Assert.Equal(nameof(FeatureWithStarNotation.I_Have_Some_Cukes), featureInstance.CallStack[0].Key);528        }529        private sealed class FeatureWithStarNotation : Feature530        {531            public List<KeyValuePair<string, object[]>> CallStack { get; } = new List<KeyValuePair<string, object[]>>();532533            [Given("I have some cukes")]534            public void I_Have_Some_Cukes()535            {536                CallStack.Add(new KeyValuePair<string, object[]>(nameof(I_Have_Some_Cukes), null));537            }538        }539        [Fact]540        public async Task ExecuteScenario_DoesNotAllow_AsyncVoid_Steps()541        {542            //arrange.543            var feature = new FeatureWithAsyncVoidStep();544            var output = new Mock<ITestOutputHelper>();545            feature.InternalOutput = output.Object;546547            //act / assert.548            await Assert.ThrowsAsync<InvalidOperationException>(async () => await _sut.ExecuteScenarioAsync(feature, "S"));549        }550        private sealed class FeatureWithAsyncVoidStep : Feature551        {552            [Given("Any step text")]553            public async void StepWithAsyncVoid()554            {555                await Task.CompletedTask;556            }557        }558    }559}...StepMethodInfoTests.cs
Source:StepMethodInfoTests.cs  
...15        [Fact]16        public void Ctor_Initializes_Properties()17        {18            //arrange.19            var featureInstance = new FeatureForCtorTest();20            //act.21            var sut = StepMethodInfo.FromMethodInfo(featureInstance.GetType().GetMethod(nameof(FeatureForCtorTest.When_Something)), featureInstance);22            //assert.23            Assert.NotNull(sut);24            Assert.NotNull(sut.ScenarioStepPatterns);25            Assert.Single(sut.ScenarioStepPatterns);26            Assert.Equal(PatternKind.When, sut.ScenarioStepPatterns[0].Kind);27            Assert.Equal(FeatureForCtorTest.WhenStepText, sut.ScenarioStepPatterns[0].OriginalPattern);28        }29        private sealed class FeatureForCtorTest : Feature30        {31            public const string WhenStepText = "some text 123";32            [When(WhenStepText)]33            public void When_Something()34            {35            }36        }37        [Fact]38        public void Clone_Creates_Similar_Instance()39        {40            //arrange.41            var featureInstance = new FeatureForCtorTest();42            var sut = StepMethodInfo.FromMethodInfo(featureInstance.GetType().GetMethod(nameof(FeatureForCtorTest.When_Something)), featureInstance);43            //act.44            var clone = sut.Clone();45            //assert.46            Assert.NotNull(clone);47            Assert.True(clone.IsSameAs(sut));48        }49        [Fact]50        public void IsSameAs_Identifies_Similar_Instances()51        {52            //arrange.53            var featureInstance = new FeatureForCtorTest();54            var sut = StepMethodInfo.FromMethodInfo(featureInstance.GetType().GetMethod(nameof(FeatureForCtorTest.When_Something)), featureInstance);55            var clone = StepMethodInfo.FromMethodInfo(featureInstance.GetType().GetMethod(nameof(FeatureForCtorTest.When_Something)), featureInstance);56            //act.57            var same = sut.IsSameAs(clone) && clone.IsSameAs(sut);58            //assert.59            Assert.True(same);60        }61        [Fact]62        public void DigestScenarioStepValues_Expects_Exact_Number_Of_Groups_Not_Less()63        {64            //arrange.65            var featureInstance = new FeatureForApplyArgumentValues_LessThanNeededGroups();66            var sut = StepMethodInfo.FromMethodInfo(67                featureInstance.GetType().GetMethod(nameof(FeatureForApplyArgumentValues_LessThanNeededGroups.Method_With_Arguments)),68                featureInstance);69            var number = 123;70            var text = "Ana";71            var date = new DateTime(2018, 5, 23);72            var stepText = FeatureForApplyArgumentValues_LessThanNeededGroups.StepMethodText73                .Replace(@"(\d+)", $"{number}")74                .Replace(@"(\w+)", $"{text}");75            var step = new Gherkin.Ast.Step(null, "Then", stepText, null);76            //act / assert.77            Assert.Throws<InvalidOperationException>(() => sut.DigestScenarioStepValues(step));78        }79        private sealed class FeatureForApplyArgumentValues_LessThanNeededGroups : Feature80        {81            public const string StepMethodText = @"I should have (\d+) apples from (\w+) by 5/23/2018";82            [Then(StepMethodText)]83            public void Method_With_Arguments(int number, string text, DateTime date)84            { }85        }86        [Theory]87        [InlineData("Then")]88        [InlineData("*")]89        public void DigestScenarioStepValues_Sets_Primitive_Values(string keyword)90        {91            //arrange.92            var featureInstance = new FeatureForApplyArgumentValues();93            var sut = StepMethodInfo.FromMethodInfo(94                featureInstance.GetType().GetMethod(nameof(FeatureForApplyArgumentValues.Method_With_Arguments)),95                featureInstance);96            var number = 123;97            var text = "Ana";98            var date = new DateTime(2018, 5, 23);99            var stepText = FeatureForApplyArgumentValues.StepMethodText100                .Replace(@"(\d+)", $"{number}")101                .Replace(@"(\w+)", $"{text}")102                .Replace(@"([\d/]+)", $"{date.Month}/{date.Day}/{date.Year}");103            var step = new Gherkin.Ast.Step(null, keyword, stepText, null);104            //act.105            sut.DigestScenarioStepValues(step);106            //assert.107            var digestedText = sut.GetDigestedStepText();108            Assert.Equal(stepText, digestedText);109        }110        111        private sealed class FeatureForApplyArgumentValues : Feature112        {113            public const string StepMethodText = @"I should have (\d+) apples from (\w+) by ([\d/]+)";114            [Then(StepMethodText)]115            public void Method_With_Arguments(int number, string text, DateTime date)116            { }117        }118        [Fact]119        public async Task Execute_Invokes_StepMethod()120        {121            //arrange.122            var featureInstance = new FeatureForExecuteTest();123            var sut = StepMethodInfo.FromMethodInfo(featureInstance.GetType().GetMethod(nameof(FeatureForExecuteTest.Call_This_Method)), featureInstance);124            //act.125            await sut.ExecuteAsync();126            //assert.127            Assert.True(featureInstance.Called);128        }129        private sealed class FeatureForExecuteTest : Feature130        {131            public bool Called { get; private set; } = false;132            [And("Call this")]133            public void Call_This_Method()134            {135                Called = true;136            }137        }138        [Fact]139        public void GetDigestedStepText_Throws_Error_If_Not_Yet_Digested()140        {141            //arrange.142            var featureInstance = new Feature_For_GetDigestedStepTextTest();143            var sut = StepMethodInfo.FromMethodInfo(featureInstance.GetType().GetMethod(nameof(Feature_For_GetDigestedStepTextTest.When_Something_Method)), featureInstance);144            //act / assert.145            Assert.Throws<InvalidOperationException>(() => sut.GetDigestedStepText());146        }147        private sealed class Feature_For_GetDigestedStepTextTest : Feature148        {149            [When("something")]150            public void When_Something_Method() { }151        }152        [Fact]153        public void FromMethodInfo_Creates_StepMethodInfo_With_DataTable()154        {155            //arrange.156            var featureInstance = new FeatureWithDataTableScenarioStep();157            //act.158            var sut = StepMethodInfo.FromMethodInfo(159                featureInstance.GetType().GetMethod(nameof(FeatureWithDataTableScenarioStep.When_DataTable_Is_Expected)),160                featureInstance161                );162            //assert.163            Assert.NotNull(sut);164        }165        [Fact]166        public void DigestScenarioStepValues_Sets_DataTable_Value()167        {168            //arrange.169            var featureInstance = new FeatureWithDataTableScenarioStep();170            var sut = StepMethodInfo.FromMethodInfo(171                featureInstance.GetType().GetMethod(nameof(FeatureWithDataTableScenarioStep.When_DataTable_Is_Expected)),172                featureInstance173                );174            var step = new Gherkin.Ast.Step(175                null,176                "When",177                FeatureWithDataTableScenarioStep.Steptext,178                new Gherkin.Ast.DataTable(new Gherkin.Ast.TableRow[]179            {180                new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]181                {182                    new Gherkin.Ast.TableCell(null, "First argument"),183                    new Gherkin.Ast.TableCell(null, "Second argument"),184                    new Gherkin.Ast.TableCell(null, "Result"),185                }),186                new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]187                {188                    new Gherkin.Ast.TableCell(null, "1"),189                    new Gherkin.Ast.TableCell(null, "2"),190                    new Gherkin.Ast.TableCell(null, "3"),191                }),192                new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]193                {194                    new Gherkin.Ast.TableCell(null, "a"),195                    new Gherkin.Ast.TableCell(null, "b"),196                    new Gherkin.Ast.TableCell(null, "c"),197                })198            }));199            //act.200            sut.DigestScenarioStepValues(step);201            //assert.202            var digestedText = sut.GetDigestedStepText();203            Assert.Equal(FeatureWithDataTableScenarioStep.Steptext, digestedText);204        }205        private sealed class FeatureWithDataTableScenarioStep : Feature206        {207            public Gherkin.Ast.DataTable ReceivedDataTable { get; private set; }208            public const string Steptext = "Some step text";209            [When(Steptext)]210            public void When_DataTable_Is_Expected(Gherkin.Ast.DataTable dataTable)211            {212                ReceivedDataTable = dataTable;213            }214        }215        [Fact]216        public void FromMethodInfo_Creates_StepMethodInfo_With_DocString()217        {218            //arrange.219            var featureInstance = new FeatureWithDocStringScenarioStep();220            //act.221            var sut = StepMethodInfo.FromMethodInfo(222                featureInstance.GetType().GetMethod(nameof(FeatureWithDocStringScenarioStep.Step_With_DocString_Argument)),223                featureInstance224                );225            //assert.226            Assert.NotNull(sut);227        }228        private sealed class FeatureWithDocStringScenarioStep : Feature229        {230            public Gherkin.Ast.DocString ReceivedDocString { get; private set; }231            public const string StepWithDocStringText = "Step with docstirng";232            [Given(StepWithDocStringText)]233            public void Step_With_DocString_Argument(Gherkin.Ast.DocString docString)234            {235                ReceivedDocString = docString;236            }237        }238        [Fact]239        public void DigestScenarioStepValues_Sets_DocString_Value()240        {241            //arrange.242            var featureInstance = new FeatureWithDocStringScenarioStep();243            var sut = StepMethodInfo.FromMethodInfo(244                featureInstance.GetType().GetMethod(nameof(FeatureWithDocStringScenarioStep.Step_With_DocString_Argument)),245                featureInstance246                );247            var docStringContent = @"some content248+++249with multi lines250---251in it";252            var step = new Gherkin.Ast.Step(253                null,254                "Given",255                FeatureWithDocStringScenarioStep.StepWithDocStringText,256                new Gherkin.Ast.DocString(null, null, docStringContent));257            //act.258            sut.DigestScenarioStepValues(step);259            //assert.260            var digestedText = sut.GetDigestedStepText();261            Assert.Equal(FeatureWithDocStringScenarioStep.StepWithDocStringText, digestedText);262        }263        [Fact]264        public void FromMethodInfo_Creates_StepMethodInfo_With_Multiple_Patterns()265        {266            //arrange.267            var featureInstance = new FeatureWithMultipleStepPatterns();268            //act.269            var sut = StepMethodInfo.FromMethodInfo(270                featureInstance.GetType().GetMethod(nameof(FeatureWithMultipleStepPatterns.Step_With_Multiple_Patterns)),271                featureInstance);272            //assert.273            Assert.NotNull(sut);274            Assert.Equal(10, sut.ScenarioStepPatterns.Count);275            AssertPattern(0, PatternKind.Given, "something");276            AssertPattern(1, PatternKind.Given, "something else");277            AssertPattern(2, PatternKind.And, "something");278            AssertPattern(3, PatternKind.And, "something else");279            AssertPattern(4, PatternKind.When, "something");280            AssertPattern(5, PatternKind.When, "something else");281            AssertPattern(6, PatternKind.And, "something");282            AssertPattern(7, PatternKind.And, "something else");283            AssertPattern(8, PatternKind.But, "something");284            AssertPattern(9, PatternKind.But, "something else");285            void AssertPattern(int index, PatternKind patternKind, string pattern)286            {287                var thePattern = sut.ScenarioStepPatterns[index];288                Assert.NotNull(thePattern);289                Assert.Equal(patternKind, thePattern.Kind);290                Assert.Equal(pattern, thePattern.OriginalPattern);291            }292        }293        private sealed class FeatureWithMultipleStepPatterns : Feature294        {295            [Given("something")]296            [Given("something else")]297            [And("something")]298            [And("something else")]299            [When("something")]300            [When("something else")]301            [And("something")]302            [And("something else")]303            [But("something")]304            [But("something else")]305            public void Step_With_Multiple_Patterns()306            { }307        }308        [Fact]309        public void FromMethodInfo_DoesNotAllow_AsyncAvoid_Steps()310        {311            //arrange.312            var featureInstance = new FeatureWithAsyncVoidStep();313            var methodInfo = typeof(FeatureWithAsyncVoidStep).GetMethod(nameof(FeatureWithAsyncVoidStep.StepWithAsyncVoid));314315            //act / assert.316            Assert.Throws<InvalidOperationException>(() => StepMethodInfo.FromMethodInfo(methodInfo, featureInstance));317        }318        private sealed class FeatureWithAsyncVoidStep : Feature319        {320            [Given("Any step text")]321            public async void StepWithAsyncVoid()322            {323                await Task.CompletedTask;324            }325        }326        [Fact]327        public void GetMethodName_Returns_Wrapped_Method_Name()328        {329            //arrange.330            var featureInstance = new FeatureForMethodName();331            var sut = StepMethodInfo.FromMethodInfo(332                featureInstance.GetType().GetMethod(nameof(FeatureForMethodName.Step_Name_Must_Be_This)),333                featureInstance334                );335            //act.336            var methodName = sut.GetMethodName();337            //assert.338            Assert.Equal(nameof(FeatureForMethodName.Step_Name_Must_Be_This), methodName);339        }340        private sealed class FeatureForMethodName : Feature341        {342            [Given("something")]343            public void Step_Name_Must_Be_This()344            {345            }346        }347        [Theory]348        [InlineData("When")]349        [InlineData("*")]350        public void GetMatchingPattern_Finds_Match_For_Step(string keyword)351        {352            //arrange.353            var featureInstance = new FeatureForMatch();354            var sut = StepMethodInfo.FromMethodInfo(355                typeof(FeatureForMatch).GetMethod(nameof(FeatureForMatch.Method1)),356                featureInstance);357358            //act.359            var match = sut.GetMatchingPattern(new Gherkin.Ast.Step(null, keyword, "this matches", null));360361            //assert.362            Assert.NotNull(match);363            Assert.Equal(PatternKind.When, match.Kind);364            Assert.Equal("this matches", match.OriginalPattern);365        }366        [Fact]367        public void GetMatchingPattern_Finds_Nothing_When_No_Match()368        {369            //arrange.370            var featureInstance = new FeatureForMatch();371            var sut = StepMethodInfo.FromMethodInfo(372                typeof(FeatureForMatch).GetMethod(nameof(FeatureForMatch.Method1)),373                featureInstance);374375            //act.376            var match = sut.GetMatchingPattern(new Gherkin.Ast.Step(null, "When", "this does not matches", null));377378            //assert.379            Assert.Null(match);380        }381        [Theory]382        [InlineData("When")]383        [InlineData("*")]384        public void Match_IsPositive_For_Corresponding_Step(string keyword)385        {386            //arrange.387            var featureInstance = new FeatureForMatch();388            var sut = StepMethodInfo.FromMethodInfo(389                typeof(FeatureForMatch).GetMethod(nameof(FeatureForMatch.Method1)),390                featureInstance);391392            //act.393            var match = sut.Matches(new Gherkin.Ast.Step(null, keyword, "this matches", null));394395            //assert.396            Assert.True(match);397        }398399        [Fact]400        public void Match_IsNegative_For_Different_Step()401        {402            //arrange.403            var featureInstance = new FeatureForMatch();404            var sut = StepMethodInfo.FromMethodInfo(405                typeof(FeatureForMatch).GetMethod(nameof(FeatureForMatch.Method1)),406                featureInstance);407408            //act.409            var match = sut.Matches(new Gherkin.Ast.Step(null, "When", "this does not matches", null));410411            //assert.412            Assert.False(match);413        }414        private sealed class FeatureForMatch : Feature415        {416            [When("this matches")]417            public void Method1()418            {419            }420        }421    }422}...GherkinFeatureTests.cs
Source:GherkinFeatureTests.cs  
...3using Xunit;4using Xunit.Gherkin.Quick;5namespace UnitTests6{7    public sealed class GherkinFeatureTests8    {9        public static object[][] DataFor_Feature_And_Scenario_Null_Arguments10        {11            get12            {13                return new object[][] 14                {15                    new object[]{ new Gherkin.Ast.Feature(null, null, null, null, null, null, null), null },16                    new object[]{ null, "scenario name" }17                };18            }19        }20        [Theory]21        [MemberData(nameof(DataFor_Feature_And_Scenario_Null_Arguments))]22        public void GetScenarioTags_Requires_Arguments(23            Gherkin.Ast.Feature feature,24            string scenarioName25            )26        {27            //act / assert.28            Assert.Throws<ArgumentNullException>(() => feature.GetScenarioTags(scenarioName));29        }30        [Fact]31        public void GetScenarioTags_Retrieves_Tags_Of_Feature_And_Scenario_Combined()32        {33            //arrange.34            var featureTags = new Gherkin.Ast.Tag[] 35            {36                new Gherkin.Ast.Tag(null, "featuretag-1"),37                new Gherkin.Ast.Tag(null, "featuretag-2")38            };39            var scenarioTags = new Gherkin.Ast.Tag[] 40            {41                new Gherkin.Ast.Tag(null, "scenarioTag-1"),42                new Gherkin.Ast.Tag(null, "scenarioTag-2"),43                new Gherkin.Ast.Tag(null, "scenarioTag-3")44            };45            var scenarioName = "scenario name 123";46            var feature = new Gherkin.Ast.Feature(47                featureTags, null, null, null, null, null,48                new Gherkin.Ast.ScenarioDefinition[] 49                {50                    new Gherkin.Ast.Scenario(scenarioTags, null, null, scenarioName, null, null)51                });52            //act.53            var scenarioTagNames = feature.GetScenarioTags(scenarioName);54            //assert.55            Assert.NotNull(scenarioTagNames);56            var expectedTagNames = featureTags.Union(scenarioTags).Select(t => t.Name);57            Assert.Equal(expectedTagNames, scenarioTagNames);58        }59        60        [Theory]61        [MemberData(nameof(DataFor_Feature_And_Scenario_Null_Arguments))]62        public void IsScenarioIgnored_Requires_Arguments(63            Gherkin.Ast.Feature feature,64            string scenarioName65            )66        {67            //act / assert.68            Assert.Throws<ArgumentNullException>(() => feature.IsScenarioIgnored(scenarioName));69        }70        [Fact]71        public void IsScenarioIgnored_Does_Not_Treat_Ignored_If_No_Ignore_Tag()72        {73            //arrange.74            var featureTags = new Gherkin.Ast.Tag[]75            {76                new Gherkin.Ast.Tag(null, "featuretag-1"),77                new Gherkin.Ast.Tag(null, "featuretag-2")78            };79            var scenarioTags = new Gherkin.Ast.Tag[]80            {81                new Gherkin.Ast.Tag(null, "scenarioTag-1"),82                new Gherkin.Ast.Tag(null, "scenarioTag-2"),83                new Gherkin.Ast.Tag(null, "scenarioTag-3")84            };85            var scenarioName = "scenario name 123";86            var feature = new Gherkin.Ast.Feature(87                featureTags, null, null, null, null, null,88                new Gherkin.Ast.ScenarioDefinition[]89                {90                    new Gherkin.Ast.Scenario(scenarioTags, null, null, scenarioName, null, null)91                });92            //act.93            var isIgnored = feature.IsScenarioIgnored(scenarioName);94            //assert.95            Assert.False(isIgnored);96        }97        [Fact]98        public void IsScenarioIgnored_Treats_Ignored_If_Feature_Is_Ignored()99        {100            //arrange.101            var featureTags = new Gherkin.Ast.Tag[]102            {103                new Gherkin.Ast.Tag(null, "featuretag-1"),104                new Gherkin.Ast.Tag(null, GherkinFeatureExtensions.IgnoreTag)105            };106            var scenarioTags = new Gherkin.Ast.Tag[]107            {108                new Gherkin.Ast.Tag(null, "scenarioTag-1"),109                new Gherkin.Ast.Tag(null, "scenarioTag-2"),110                new Gherkin.Ast.Tag(null, "scenarioTag-3")111            };112            var scenarioName = "scenario name 123";113            var feature = new Gherkin.Ast.Feature(114                featureTags, null, null, null, null, null,115                new Gherkin.Ast.ScenarioDefinition[]116                {117                    new Gherkin.Ast.Scenario(scenarioTags, null, null, scenarioName, null, null)118                });119            //act.120            var isIgnored = feature.IsScenarioIgnored(scenarioName);121            //assert.122            Assert.True(isIgnored);123        }124        [Fact]125        public void IsScenarioIgnored_Treats_Ignored_If_Scenario_Is_Ignored()126        {127            //arrange.128            var featureTags = new Gherkin.Ast.Tag[]129            {130                new Gherkin.Ast.Tag(null, "featuretag-1"),131                new Gherkin.Ast.Tag(null, "featuretag-2")132            };133            var scenarioTags = new Gherkin.Ast.Tag[]134            {135                new Gherkin.Ast.Tag(null, "scenarioTag-1"),136                new Gherkin.Ast.Tag(null, GherkinFeatureExtensions.IgnoreTag),137                new Gherkin.Ast.Tag(null, "scenarioTag-3")138            };139            var scenarioName = "scenario name 123";140            var feature = new Gherkin.Ast.Feature(141                featureTags, null, null, null, null, null,142                new Gherkin.Ast.ScenarioDefinition[]143                {144                    new Gherkin.Ast.Scenario(scenarioTags, null, null, scenarioName, null, null)145                });146            //act.147            var isIgnored = feature.IsScenarioIgnored(scenarioName);148            //assert.149            Assert.True(isIgnored);150        }151        public static object[][] DataFor_Feature_And_ScenarioOutline_And_Examples_Null_Arguments152        {153            get154            {155                return new object[][]156                {157                    new object[]{ null, "scenario outline name", "examples name" },158                    new object[]{ new Gherkin.Ast.Feature(null, null, null, null, null, null, null), null, "examples name" },159                    new object[]{ new Gherkin.Ast.Feature(null, null, null, null, null, null, null), "scenario outline name", null }160                };161            }162        }163        [Theory]164        [MemberData(nameof(DataFor_Feature_And_ScenarioOutline_And_Examples_Null_Arguments))]165        public void GetExamplesTags_Requires_Arguments(166            Gherkin.Ast.Feature feature,167            string scenarioOutlineName,168            string examplesName169            )170        {171            //act / assert.172            Assert.Throws<ArgumentNullException>(() => feature.GetExamplesTags(173                scenarioOutlineName,174                examplesName));175        }176        [Fact]177        public void GetExamplesTags_Retrieves_Tags_Of_Feature_And_OutLine_And_Examples_Combined()178        {179            //arrange.180            var featureTags = new Gherkin.Ast.Tag[]181            {182                new Gherkin.Ast.Tag(null, "featuretag-1"),183                new Gherkin.Ast.Tag(null, "featuretag-2")184            };185            var outlineTags = new Gherkin.Ast.Tag[]186            {187                new Gherkin.Ast.Tag(null, "outlinetag-1"),188                new Gherkin.Ast.Tag(null, "outlinetag-2"),189                new Gherkin.Ast.Tag(null, "outlinetag-3")190            };191            var examplesTags = new Gherkin.Ast.Tag[]192            {193                new Gherkin.Ast.Tag(null, "examplestag-1"),194                new Gherkin.Ast.Tag(null, "examplestag-2"),195                new Gherkin.Ast.Tag(null, "examplestag-2"),196                new Gherkin.Ast.Tag(null, "examplestag-3")197            };198            var scenarioOutlineName = "scenario name 123";199            var examplesName = "examples name 123";200            var feature = new Gherkin.Ast.Feature(201                featureTags, null, null, null, null, null,202                new Gherkin.Ast.ScenarioDefinition[]203                {204                    new Gherkin.Ast.ScenarioOutline(outlineTags, null, null, scenarioOutlineName, null, null,205                    new Gherkin.Ast.Examples[]206                    {207                        new Gherkin.Ast.Examples(examplesTags, null, null, examplesName, null, null, null)208                    })209                });210            //act.211            var examplesTagNames = feature.GetExamplesTags(scenarioOutlineName, examplesName);212            //assert.213            Assert.NotNull(examplesTagNames);214            var expectedTagNames = featureTags.Union(outlineTags).Union(examplesTags).Select(t => t.Name);215            Assert.Equal(expectedTagNames, examplesTagNames);216        }217        [Theory]218        [MemberData(nameof(DataFor_Feature_And_ScenarioOutline_And_Examples_Null_Arguments))]219        public void IsExamplesIgnored_Requires_Arguments(220            Gherkin.Ast.Feature feature,221            string scenarioOutlineName,222            string examplesName223            )224        {225            //act / assert.226            Assert.Throws<ArgumentNullException>(() => feature.IsExamplesIgnored(scenarioOutlineName, examplesName));227        }228        [Fact]229        public void IsExamplesIgnored_Does_Not_Treat_Ignored_If_No_Ignore_Tag()230        {231            //arrange.232            var featureTags = new Gherkin.Ast.Tag[]233            {234                new Gherkin.Ast.Tag(null, "featuretag-1"),235                new Gherkin.Ast.Tag(null, "featuretag-2")236            };237            var outlineTags = new Gherkin.Ast.Tag[]238            {239                new Gherkin.Ast.Tag(null, "outlinetag-1"),240                new Gherkin.Ast.Tag(null, "outlinetag-2"),241                new Gherkin.Ast.Tag(null, "outlinetag-3")242            };243            var examplesTags = new Gherkin.Ast.Tag[]244            {245                new Gherkin.Ast.Tag(null, "examplestag-1"),246                new Gherkin.Ast.Tag(null, "examplestag-2"),247                new Gherkin.Ast.Tag(null, "examplestag-2"),248                new Gherkin.Ast.Tag(null, "examplestag-3")249            };250            var scenarioOutlineName = "scenario name 123";251            var examplesName = "examples name 123";252            var feature = new Gherkin.Ast.Feature(253                featureTags, null, null, null, null, null,254                new Gherkin.Ast.ScenarioDefinition[]255                {256                    new Gherkin.Ast.ScenarioOutline(outlineTags, null, null, scenarioOutlineName, null, null,257                    new Gherkin.Ast.Examples[]258                    {259                        new Gherkin.Ast.Examples(examplesTags, null, null, examplesName, null, null, null)260                    })261                });262            //act.263            var isIgnored = feature.IsExamplesIgnored(scenarioOutlineName, examplesName);264            //assert.265            Assert.False(isIgnored);266        }267        [Fact]268        public void IsExamplesIgnored_Treats_Ignored_If_Feature_Is_Ignored()269        {270            //arrange.271            var featureTags = new Gherkin.Ast.Tag[]272            {273                new Gherkin.Ast.Tag(null, "featuretag-1"),274                new Gherkin.Ast.Tag(null, GherkinFeatureExtensions.IgnoreTag)275            };276            var outlineTags = new Gherkin.Ast.Tag[]277            {278                new Gherkin.Ast.Tag(null, "outlinetag-1"),279                new Gherkin.Ast.Tag(null, "outlinetag-2"),280                new Gherkin.Ast.Tag(null, "outlinetag-3")281            };282            var examplesTags = new Gherkin.Ast.Tag[]283            {284                new Gherkin.Ast.Tag(null, "examplestag-1"),285                new Gherkin.Ast.Tag(null, "examplestag-2"),286                new Gherkin.Ast.Tag(null, "examplestag-2"),287                new Gherkin.Ast.Tag(null, "examplestag-3")288            };289            var scenarioOutlineName = "scenario name 123";290            var examplesName = "examples name 123";291            var feature = new Gherkin.Ast.Feature(292                featureTags, null, null, null, null, null,293                new Gherkin.Ast.ScenarioDefinition[]294                {295                    new Gherkin.Ast.ScenarioOutline(outlineTags, null, null, scenarioOutlineName, null, null,296                    new Gherkin.Ast.Examples[]297                    {298                        new Gherkin.Ast.Examples(examplesTags, null, null, examplesName, null, null, null)299                    })300                });301            //act.302            var isIgnored = feature.IsExamplesIgnored(scenarioOutlineName, examplesName);303            //assert.304            Assert.True(isIgnored);305        }306        [Fact]307        public void IsExamplesIgnored_Treats_Ignored_If_ScenarioOutline_Is_Ignored()308        {309            //arrange.310            var featureTags = new Gherkin.Ast.Tag[]311            {312                new Gherkin.Ast.Tag(null, "featuretag-1"),313                new Gherkin.Ast.Tag(null, "featuretag-1")314            };315            var outlineTags = new Gherkin.Ast.Tag[]316            {317                new Gherkin.Ast.Tag(null, "outlinetag-1"),318                new Gherkin.Ast.Tag(null, GherkinFeatureExtensions.IgnoreTag),319                new Gherkin.Ast.Tag(null, "outlinetag-3")320            };321            var examplesTags = new Gherkin.Ast.Tag[]322            {323                new Gherkin.Ast.Tag(null, "examplestag-1"),324                new Gherkin.Ast.Tag(null, "examplestag-2"),325                new Gherkin.Ast.Tag(null, "examplestag-2"),326                new Gherkin.Ast.Tag(null, "examplestag-3")327            };328            var scenarioOutlineName = "scenario name 123";329            var examplesName = "examples name 123";330            var feature = new Gherkin.Ast.Feature(331                featureTags, null, null, null, null, null,332                new Gherkin.Ast.ScenarioDefinition[]333                {334                    new Gherkin.Ast.ScenarioOutline(outlineTags, null, null, scenarioOutlineName, null, null,335                    new Gherkin.Ast.Examples[]336                    {337                        new Gherkin.Ast.Examples(examplesTags, null, null, examplesName, null, null, null)338                    })339                });340            //act.341            var isIgnored = feature.IsExamplesIgnored(scenarioOutlineName, examplesName);342            //assert.343            Assert.True(isIgnored);344        }345        [Fact]346        public void IsExamplesIgnored_Treats_Ignored_If_Examples_Is_Ignored()347        {348            //arrange.349            var featureTags = new Gherkin.Ast.Tag[]350            {351                new Gherkin.Ast.Tag(null, "featuretag-1"),352                new Gherkin.Ast.Tag(null, "featuretag-2")353            };354            var outlineTags = new Gherkin.Ast.Tag[]355            {356                new Gherkin.Ast.Tag(null, "outlinetag-1"),357                new Gherkin.Ast.Tag(null, "outlinetag-2"),358                new Gherkin.Ast.Tag(null, "outlinetag-3")359            };360            var examplesTags = new Gherkin.Ast.Tag[]361            {362                new Gherkin.Ast.Tag(null, "examplestag-1"),363                new Gherkin.Ast.Tag(null, "examplestag-2"),364                new Gherkin.Ast.Tag(null, GherkinFeatureExtensions.IgnoreTag),365                new Gherkin.Ast.Tag(null, "examplestag-3")366            };367            var scenarioOutlineName = "scenario name 123";368            var examplesName = "examples name 123";369            var feature = new Gherkin.Ast.Feature(370                featureTags, null, null, null, null, null,371                new Gherkin.Ast.ScenarioDefinition[]372                {373                    new Gherkin.Ast.ScenarioOutline(outlineTags, null, null, scenarioOutlineName, null, null,374                    new Gherkin.Ast.Examples[]375                    {376                        new Gherkin.Ast.Examples(examplesTags, null, null, examplesName, null, null, null)377                    })378                });379            //act.380            var isIgnored = feature.IsExamplesIgnored(scenarioOutlineName, examplesName);381            //assert.382            Assert.True(isIgnored);383        }...FeatureClassTests.cs
Source:FeatureClassTests.cs  
...5using Xunit;6using Xunit.Gherkin.Quick;7namespace UnitTests8{9    public sealed class FeatureClassTests10    {11        [Fact]12        public void FromFeatureInstance_Creates_FeatureClass_With_Default_FilePath_If_No_Attribute()13        {14            //arrange.15            var featureInstance = new FeatureWithoutFilePath();16            //act.17            var sut = FeatureClass.FromFeatureInstance(featureInstance);18            //assert.19            Assert.NotNull(sut);20            Assert.Equal($"{nameof(FeatureWithoutFilePath)}.feature", sut.FeatureFilePath);21        }22        private sealed class FeatureWithoutFilePath : Feature23        {24        }25        [Fact]26        public void FromFeatureInstance_Creates_FeatureClass_With_FilePath_From_Attribute()27        {28            //arrange.29            var featureInstance = new FeatureWithFilePath();30            //act.31            var sut = FeatureClass.FromFeatureInstance(featureInstance);32            //assert.33            Assert.NotNull(sut);34            Assert.Equal(FeatureWithFilePath.PathFor_FeatureWithFilePath, sut.FeatureFilePath);35        }36        [FeatureFile(PathFor_FeatureWithFilePath)]37        private sealed class FeatureWithFilePath : Feature38        {39            public const string PathFor_FeatureWithFilePath = "some file path const 123";40        }41        [Fact]42        public void FromFeatureInstance_DoesNotAllow_AsyncVoid_Steps()43        {44            var featureInstance = new FeatureWithAsyncVoidStep();4546            //act / assert.47            Assert.Throws<InvalidOperationException>(() => FeatureClass.FromFeatureInstance(featureInstance));48        }49        private sealed class FeatureWithAsyncVoidStep : Feature50        {51            [Given("Any step text")]52            public async void StepWithAsyncVoid()53            {54                await Task.CompletedTask;55            }56        }57        [Fact]58        public void ExtractScenario_Extracts_Scenario_Without_Background()59        {60            //arrange.61            var scenarioName = "some scenario name 123";62            var featureInstance = new FeatureWithMatchingScenarioStepsToExtract();63            var sut = FeatureClass.FromFeatureInstance(featureInstance);64            var gherkinScenario = CreateGherkinDocument(scenarioName,65                new string[]66                {67                    "Given " + FeatureWithMatchingScenarioStepsToExtract.ScenarioStep1Text.Replace(@"(\d+)", "12", StringComparison.InvariantCultureIgnoreCase),68                    "And " + FeatureWithMatchingScenarioStepsToExtract.ScenarioStep2Text.Replace(@"(\d+)", "15", StringComparison.InvariantCultureIgnoreCase),69                    "When " + FeatureWithMatchingScenarioStepsToExtract.ScenarioStep3Text,70                    "Then " + FeatureWithMatchingScenarioStepsToExtract.ScenarioStep4Text.Replace(@"(\d+)", "27", StringComparison.InvariantCultureIgnoreCase)71                }).Feature.Children.First() as Gherkin.Ast.Scenario;72            //act.73            var scenario = sut.ExtractScenario(gherkinScenario);74            //assert.75            Assert.NotNull(scenario);76        }		77        private static Gherkin.Ast.GherkinDocument CreateGherkinDocument(78            string scenario,79            string[] steps,80            Gherkin.Ast.StepArgument stepArgument = null,81            string[] backgroundSteps = null)82        {83            var definitions = new List<global::Gherkin.Ast.ScenarioDefinition>84            {85                new Gherkin.Ast.Scenario(86                        new Gherkin.Ast.Tag[0],87                        null,88                        null,89                        scenario,90                        null,91                        steps.Select(s =>92                        {93                            var spaceIndex = s.IndexOf(' ');94                            return new Gherkin.Ast.Step(95                                null,96                                s.Substring(0, spaceIndex).Trim(),97                                s.Substring(spaceIndex).Trim(),98                                stepArgument);99                        }).ToArray())100            };101            if(backgroundSteps != null)102            {103                definitions.Add(104                    new Gherkin.Ast.Background(105                        null,106                        null,107                        "background",108                        null,109                        backgroundSteps.Select(s =>110                        {111                            var spaceIndex = s.IndexOf(' ');112                            return new Gherkin.Ast.Step(113                                null,114                                s.Substring(0, spaceIndex).Trim(),115                                s.Substring(spaceIndex).Trim(),116                                stepArgument);117                        }).ToArray()));118            }119            return new Gherkin.Ast.GherkinDocument(120                new Gherkin.Ast.Feature(new Gherkin.Ast.Tag[0], null, null, null, null, null, definitions.ToArray()),121                new Gherkin.Ast.Comment[0]);122        }123        private sealed class FeatureWithMatchingScenarioStepsToExtract : Feature124        {125            public List<KeyValuePair<string, object[]>> CallStack { get; } = new List<KeyValuePair<string, object[]>>();126            [Given("a background step")]127            public void GivenBackground()128            {129                CallStack.Add(new KeyValuePair<string, object[]>(nameof(GivenBackground), null));130            }131            [Given("Non matching given")]132            public void NonMatchingStep1_before()133            {134                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_before), null));135            }136            public const string ScenarioStep1Text = @"I chose (\d+) as first number";137            [Given(ScenarioStep1Text)]138            public void ScenarioStep1(int firstNumber)139            {140                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep1), new object[] { firstNumber }));141            }142            [Given("Non matching given")]143            public void NonMatchingStep1_after()144            {145                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep1_after), null));146            }147            [And("Non matching and")]148            public void NonMatchingStep2_before()149            {150                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_before), null));151            }152            public const string ScenarioStep2Text = @"I chose (\d+) as second number";153            [And(ScenarioStep2Text)]154            public void ScenarioStep2(int secondNumber)155            {156                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep2), new object[] { secondNumber }));157            }158            [And("Non matching and")]159            public void NonMatchingStep2_after()160            {161                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep2_after), null));162            }163            [When("Non matching when")]164            public void NonMatchingStep3_before()165            {166                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_before), null));167            }168            public const string ScenarioStep3Text = "I press add";169            [When(ScenarioStep3Text)]170            public void ScenarioStep3()171            {172                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep3), null));173            }174            [When("Non matching when")]175            public void NonMatchingStep3_after()176            {177                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep3_after), null));178            }179            [Then("Non matching then")]180            public void NonMatchingStep4_before()181            {182                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_before), null));183            }184            public const string ScenarioStep4Text = @"the result should be (\d+) on the screen";185            [Then(ScenarioStep4Text)]186            public void ScenarioStep4(int result)187            {188                CallStack.Add(new KeyValuePair<string, object[]>(nameof(ScenarioStep4), new object[] { result }));189            }190            [Then("Non matching then")]191            public void NonMatchingStep4_after()192            {193                CallStack.Add(new KeyValuePair<string, object[]>(nameof(NonMatchingStep4_after), null));194            }195        }196        [Fact]197        public void ExtractScnario_Extracts_Scenario_With_DataTable()198        {199            //arrange.200            var scenarioName = "scenario213";201            var featureInstance = new FeatureWithDataTableScenarioStep();202            var sut = FeatureClass.FromFeatureInstance(featureInstance);203            var gherknScenario = CreateGherkinDocument(scenarioName,204                    new string[]205                    {206                        "When " + FeatureWithDataTableScenarioStep.Steptext207                    },208                    new Gherkin.Ast.DataTable(new Gherkin.Ast.TableRow[]209                    {210                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]211                        {212                            new Gherkin.Ast.TableCell(null, "First argument"),213                            new Gherkin.Ast.TableCell(null, "Second argument"),214                            new Gherkin.Ast.TableCell(null, "Result"),215                        }),216                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]217                        {218                            new Gherkin.Ast.TableCell(null, "1"),219                            new Gherkin.Ast.TableCell(null, "2"),220                            new Gherkin.Ast.TableCell(null, "3"),221                        }),222                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]223                        {224                            new Gherkin.Ast.TableCell(null, "a"),225                            new Gherkin.Ast.TableCell(null, "b"),226                            new Gherkin.Ast.TableCell(null, "c"),227                        })228                    })).Feature.Children.First() as Gherkin.Ast.Scenario;229            //act.230            var scenario = sut.ExtractScenario(gherknScenario);231            //assert.232            Assert.NotNull(scenario);233        }234        private sealed class FeatureWithDataTableScenarioStep : Feature235        {236            public Gherkin.Ast.DataTable ReceivedDataTable { get; private set; }237            public const string Steptext = "Some step text";238            [When(Steptext)]239            public void When_DataTable_Is_Expected(Gherkin.Ast.DataTable dataTable)240            {241                ReceivedDataTable = dataTable;242            }243        }244        [Fact]245        public void ExtractScenario_Extracts_Scenario_With_DocString()246        {247            //arrange.248            var featureInstance = new FeatureWithDocStringScenarioStep();249            var sut = FeatureClass.FromFeatureInstance(featureInstance);250            var scenarioName = "scenario-121kh2";251            var docStringContent = @"some content252    +++253    with multi lines254    ---255    in it";256            var gherkinScenario = CreateGherkinDocument(scenarioName,257                    new string[] { "Given " + FeatureWithDocStringScenarioStep.StepWithDocStringText },258                    new Gherkin.Ast.DocString(null, null, docStringContent))259                    .Feature.Children.First() as Gherkin.Ast.Scenario;260            //act.261            var scenario = sut.ExtractScenario(gherkinScenario);262            //assert.263            Assert.NotNull(scenario);264        }265        private sealed class FeatureWithDocStringScenarioStep : Feature266        {267            public Gherkin.Ast.DocString ReceivedDocString { get; private set; }268            public const string StepWithDocStringText = "Step with docstirng";269            [Given(StepWithDocStringText)]270            public void Step_With_DocString_Argument(Gherkin.Ast.DocString docString)271            {272                ReceivedDocString = docString;273            }274        }275        [Fact]276        public void ExtractScenario_Extracts_Steps_With_Multiple_Patterns()277        {278            //arrange.279            var sut = FeatureClass.FromFeatureInstance(new FeatureWithMultipleStepPatterns());280            //act.281            var scenario = sut.ExtractScenario(CreateGherkinDocument("scenario 123", new string[]282            {283                "Given something else"284            }).Feature.Children.OfType<Gherkin.Ast.Scenario>().First());285            //assert.286            Assert.NotNull(scenario);287        }288        private sealed class FeatureWithMultipleStepPatterns : Feature289        {290            [Given("something")]291            [Given("something else")]292            [And("something")]293            [And("something else")]294            [When("something")]295            [When("something else")]296            [And("something")]297            [And("something else")]298            [But("something")]299            [But("something else")]300            public void Step_With_Multiple_Patterns()301            { }302        }...CompatibleAstConverter.cs
Source:CompatibleAstConverter.cs  
...5using TechTalk.SpecFlow.Parser.SyntaxElements;6using Background = TechTalk.SpecFlow.Parser.SyntaxElements.Background;7using Comment = TechTalk.SpecFlow.Parser.SyntaxElements.Comment;8using Examples = TechTalk.SpecFlow.Parser.SyntaxElements.Examples;9using Feature = TechTalk.SpecFlow.Parser.SyntaxElements.Feature;10using Scenario = TechTalk.SpecFlow.Parser.SyntaxElements.Scenario;11using ScenarioOutline = TechTalk.SpecFlow.Parser.SyntaxElements.ScenarioOutline;12using Tag = TechTalk.SpecFlow.Parser.SyntaxElements.Tag;13namespace TechTalk.SpecFlow.Parser.Compatibility14{15    public class CompatibleAstConverter16    {17        public static Feature ConvertToCompatibleFeature(SpecFlowDocument specFlowDocument)18        {19            var specFlowFeature = specFlowDocument.SpecFlowFeature;20            return new Feature(specFlowFeature.Keyword, specFlowFeature.Name, 21                ConvertToCompatibleTags(specFlowFeature.Tags),22                specFlowFeature.Description, 23                ConvertToCompatibleBackground(specFlowFeature.Background), 24                ConvertToCompatibleScenarios(specFlowFeature.ScenarioDefinitions), 25                ConvertToCompatibleComments(specFlowDocument.Comments))26            {27                FilePosition = ConvertToCompatibleFilePosition(specFlowFeature.Location),28                Language = specFlowFeature.Language,29                SourceFile = specFlowDocument.SourceFilePath30            };31        }32        private static Comment[] ConvertToCompatibleComments(IEnumerable<global::Gherkin.Ast.Comment> comments)33        {34            return comments.Select(ConvertToCompatibleComment).Where(c => c != null).ToArray();35        }36        private static Comment ConvertToCompatibleComment(global::Gherkin.Ast.Comment c)37        {38            var trimmedText = c.Text.TrimStart('#', ' ', '\t');39            if (trimmedText.Length == 0)40                return null;41            return new Comment(trimmedText, ConvertToCompatibleFilePosition(c.Location, c.Text.Length - trimmedText.Length));42        }...FeatureFileTests.cs
Source:FeatureFileTests.cs  
2using Xunit;3using Xunit.Gherkin.Quick;4namespace UnitTests5{6    public sealed class FeatureFileTests7    {8        [Fact]9        public void Ctor_Initializes_Properties()10        {11            //arrange.12            var gherkinDocument = new Gherkin.Ast.GherkinDocument(null, null);13            //act.14            var sut = new FeatureFile(gherkinDocument);15            //assert.16            Assert.Same(gherkinDocument, sut.GherkinDocument);17        }18        [Fact]19        public void GetScenario_Retrieves_If_Found()20        {21            //arrange.22            var scenarioName = "name exists";23            var sut = new FeatureFile(CreateGherkinDocumentWithScenario(scenarioName));24            //act.25            var scenario = sut.GetScenario(scenarioName);26            //assert.27            Assert.NotNull(scenario);28            Assert.Same(sut.GherkinDocument.Feature.Children.First(), scenario);29        }30        [Fact]31        public void GetScenario_Gives_Null_If_Not_Found()32        {33            //arrange.34            var sut = new FeatureFile(CreateGherkinDocumentWithScenario("existing"));35            //act.36            var scenario = sut.GetScenario("non-existing");37            //assert.38            Assert.Null(scenario);39        }40        [Fact]41        public void GetScenarioOutline_Retrieves_If_Found()42        {43            //arrange.44            var scenarioName = "name exists";45            var sut = new FeatureFile(CreateGherkinDocumentWithScenarioOutline(scenarioName));46            //act.47            var scenario = sut.GetScenarioOutline(scenarioName);48            //assert.49            Assert.NotNull(scenario);50            Assert.Same(sut.GherkinDocument.Feature.Children.First(), scenario);51        }52        [Fact]53        public void GetScenarioOutline_Gives_Null_If_Not_Found()54        {55            //arrange.56            var sut = new FeatureFile(CreateGherkinDocumentWithScenarioOutline("existing"));57            //act.58            var scenario = sut.GetScenarioOutline("non-existing");59            //assert.60            Assert.Null(scenario);61        }62        [Fact]63        public void GetBackground_Retrieves_If_Present()64        {65            var sut = new FeatureFile(CreateGherkinDocumentWithBackground());66            var background = sut.GetBackground();67            Assert.NotNull(background);68        }69        [Fact]70        public void GetBackground_Gives_Null_If_Not_Present()71        {72            var sut = new FeatureFile(CreateGherkinDocumentWithScenario("test"));73            var background = sut.GetBackground();74            Assert.Null(background);75        }76        private static Gherkin.Ast.GherkinDocument CreateGherkinDocumentWithScenario(77            string scenario,78            Gherkin.Ast.StepArgument stepArgument = null)79        {80            return new Gherkin.Ast.GherkinDocument(81                new Gherkin.Ast.Feature(new Gherkin.Ast.Tag[0], null, null, null, null, null, new Gherkin.Ast.ScenarioDefinition[]82                {83                    new Gherkin.Ast.Scenario(84                        new Gherkin.Ast.Tag[0],85                        null,86                        null,87                        scenario,88                        null,89                        new Gherkin.Ast.Step[]{ })90                }),91                new Gherkin.Ast.Comment[0]);92        }93        private static Gherkin.Ast.GherkinDocument CreateGherkinDocumentWithBackground()94        {95            return new Gherkin.Ast.GherkinDocument(96                new Gherkin.Ast.Feature(new Gherkin.Ast.Tag[0], null, null, null, null, null, new Gherkin.Ast.ScenarioDefinition[]97                {98                    new Gherkin.Ast.Background(99                        null,100                        null,101                        null,102                        null,103                        new Gherkin.Ast.Step[]{ })104                }),105                new Gherkin.Ast.Comment[0]);106        }107        private static Gherkin.Ast.GherkinDocument CreateGherkinDocumentWithScenarioOutline(108            string scenario,109            Gherkin.Ast.StepArgument stepArgument = null)110        {111            return new Gherkin.Ast.GherkinDocument(112                new Gherkin.Ast.Feature(new Gherkin.Ast.Tag[0], null, null, null, null, null, new Gherkin.Ast.ScenarioDefinition[]113                {114                    new Gherkin.Ast.ScenarioOutline(115                        new Gherkin.Ast.Tag[0],116                        null,117                        null,118                        scenario,119                        null,120                        new Gherkin.Ast.Step[]{ },121                        new Gherkin.Ast.Examples[]{ })122                }),123                new Gherkin.Ast.Comment[0]);124        }125    }126}...GherkinFeatureExtensions.cs
Source:GherkinFeatureExtensions.cs  
2using System.Collections.Generic;3using System.Linq;4namespace Xunit.Gherkin.Quick5{6    internal static class GherkinFeatureExtensions7    {8        public static List<string> GetScenarioTags(9            this global::Gherkin.Ast.Feature feature,10            string scenarioName)11        {12            if (feature == null)13                throw new ArgumentNullException(nameof(feature));14            if (string.IsNullOrWhiteSpace(scenarioName))15                throw new ArgumentNullException(nameof(scenarioName));16            var scenario = feature17                .Children18                .OfType<global::Gherkin.Ast.Scenario>()19                .FirstOrDefault(s => s.Name == scenarioName);20            if (scenario == null)21                throw new InvalidOperationException($"Cannot find scenario `{scenarioName}` under feature `{feature.Name}`.");22            var scenarioTags = feature.Tags23                ?.Union(scenario.Tags ?? new List<global::Gherkin.Ast.Tag>())24                ?.Select(t => t.Name)25                ?.ToList();26            return scenarioTags ?? new List<string>();27        }28        public const string IgnoreTag = "@ignore";29        public static bool IsScenarioIgnored(30            this global::Gherkin.Ast.Feature feature,31            string scenarioName)32        {33            var scenarioTags = feature.GetScenarioTags(scenarioName);34            return scenarioTags.Contains(IgnoreTag);35        }36        public static List<string> GetExamplesTags(37            this global::Gherkin.Ast.Feature feature,38            string scenarioOutlineName,39            string examplesName)40        {41            if (feature == null)42                throw new ArgumentNullException(nameof(feature));43            if (string.IsNullOrWhiteSpace(scenarioOutlineName))44                throw new ArgumentNullException(nameof(scenarioOutlineName));45            46            var scenarioOutline = feature.Children.OfType<global::Gherkin.Ast.ScenarioOutline>()47                .FirstOrDefault(o => o.Name == scenarioOutlineName);48            if (scenarioOutline == null)49                throw new InvalidOperationException($"Cannot find scenario outline `{scenarioOutlineName}` under feature `{feature.Name}`.");50            var examples = scenarioOutline.Examples.FirstOrDefault(e => e.Name == examplesName);51            if (examples == null)52                throw new InvalidOperationException($"Cannot find examples `{examplesName}` under scenario outline `{scenarioOutlineName}` and feature `{feature.Name}`.");53            var examplesTags = feature.Tags54                ?.Union(scenarioOutline.Tags ?? new List<global::Gherkin.Ast.Tag>())55                ?.Union(examples.Tags ?? new List<global::Gherkin.Ast.Tag>())56                ?.Select(t => t.Name)57                ?.ToList();58            return examplesTags ?? new List<string>();59        }60        public static bool IsExamplesIgnored(61            this global::Gherkin.Ast.Feature feature,62            string scenarioOutlineName,63            string examplesName)64        {65            var examplesTags = feature.GetExamplesTags(scenarioOutlineName, examplesName);66            return examplesTags.Contains(IgnoreTag);67        }68    }69}...Feature
Using AI Code Generation
1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;6using Gherkin.Ast;7using Gherkin;8using System.IO;9using System.Text.RegularExpressions;10{11    {12        static void Main(string[] args)13        {14            string featureFilePath = @"C:\Users\user\Desktop\FeatureFile.feature";15            string featureFileContent = File.ReadAllText(featureFilePath);16            var parser = new Parser();17            Feature feature = parser.Parse(featureFileContent);18            Console.WriteLine("Feature Title: " + feature.Name);19            Console.WriteLine("Feature Description: " + feature.Description);20            Console.WriteLine("Feature Tags: " + feature.Tags);21            Console.WriteLine("Number of scenarios in the feature file: " + feature.Children.Count);22            foreach (var scenario in feature.Children)23            {24                Console.WriteLine("Scenario Name: " + scenario.Name);25                Console.WriteLine("Scenario Tags: " + scenario.Tags);26                Console.WriteLine("Scenario Description: " + scenario.Description);27                foreach (var step in scenario.Steps)28                {29                    Console.WriteLine("Step Keyword: " + step.Keyword);30                    Console.WriteLine("Step Text: " + step.Text);31                    Console.WriteLine("Step Argument: " + step.Argument);32                    Console.WriteLine("Step DataTable: " + step.DataTable);33                    Console.WriteLine("Step DocString: " + step.DocString);34                }35            }36            Console.ReadLine();37        }38    }39}40using System;41using System.Collections.Generic;42using System.Linq;43using System.Text;44using System.Threading.Tasks;45using Gherkin.Ast;46using Gherkin;47using System.IO;48using System.Text.RegularExpressions;49{50    {51        static void Main(string[] args)52        {53            string featureFilePath = @"C:\Users\user\Desktop\FeatureFile.feature";Feature
Using AI Code Generation
1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;6using TechTalk.SpecFlow;7{8    {9        [Given(@"I have entered (.*) into the calculator")]10        public void GivenIHaveEnteredIntoTheCalculator(int p0)11        {12            ScenarioContext.Current.Pending();13        }14        [When(@"I press add")]15        public void WhenIPressAdd()16        {17            ScenarioContext.Current.Pending();18        }19        [Then(@"the result should be (.*) on the screen")]20        public void ThenTheResultShouldBeOnTheScreen(int p0)21        {22            ScenarioContext.Current.Pending();23        }24    }25}26using System;27using System.Collections.Generic;28using System.Linq;29using System.Text;30using System.Threading.Tasks;31using TechTalk.SpecFlow;32{33    {34        [Given(@"I have entered (.*) into the calculator")]35        public void GivenIHaveEnteredIntoTheCalculator(int p0)36        {37            ScenarioContext.Current.Pending();38        }39        [When(@"I press add")]40        public void WhenIPressAdd()41        {42            ScenarioContext.Current.Pending();43        }44        [Then(@"the result should be (.*) on the screen")]45        public void ThenTheResultShouldBeOnTheScreen(int p0)46        {47            ScenarioContext.Current.Pending();48        }49    }50}51using System;52using System.Collections.Generic;53using System.Linq;54using System.Text;55using System.Threading.Tasks;56using TechTalk.SpecFlow;57{58    {59        [Given(@"I have entered (.*) into the calculator")]60        public void GivenIHaveEnteredIntoTheCalculator(int p0)61        {62            ScenarioContext.Current.Pending();63        }64        [When(@"I press add")]65        public void WhenIPressAdd()66        {67            ScenarioContext.Current.Pending();68        }69        [Then(@"the result should be (.*) on the screen")]70        public void ThenTheResultShouldBeOnTheScreen(int p0)71        {72            ScenarioContext.Current.Pending();73        }74    }75}Feature
Using AI Code Generation
1using Gherkin.Ast;2using System;3using System.IO;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8    {9        static void Main(string[] args)10        {11            string path = @"C:\Users\test\Documents\Visual Studio 2015\Projects\GherkinTest\GherkinTest\1.feature";12            var feature = new Feature(path);13            var featureName = feature.Name;14            var background = feature.Background;15            var featureDescription = feature.Description;16            var featureTags = feature.Tags;17            var featureLanguage = feature.Language;18            var featureLocation = feature.Location;19            var featureKeyword = feature.Keyword;20            var featureChildren = feature.Children;21            var featureComments = feature.Comments;22        }23    }24}25using Gherkin.Ast;26using System;27using System.IO;28using System.Linq;29using System.Text;30using System.Threading.Tasks;31{32    {33        static void Main(string[] args)34        {35            string path = @"C:\Users\test\Documents\Visual Studio 2015\Projects\GherkinTest\GherkinTest\1.feature";36            var feature = new Feature(path);37            var background = feature.Background;38            var backgroundName = background.Name;39            var backgroundDescription = background.Description;40            var backgroundTags = background.Tags;41            var backgroundLocation = background.Location;42            var backgroundKeyword = background.Keyword;43            var backgroundChildren = background.Children;44            var backgroundComments = background.Comments;45        }46    }47}48using Gherkin.Ast;49using System;50using System.IO;51using System.Linq;52using System.Text;53using System.Threading.Tasks;54{55    {56        static void Main(string[] args)57        {58            string path = @"C:\Users\test\Documents\Visual Studio 2015\Projects\GherkinTest\GherkinTest\1.feature";59            var feature = new Feature(path);60            var featureChildren = feature.Children;61            var scenario = featureChildren[0] as Scenario;62            var scenarioName = scenario.Name;Feature
Using AI Code Generation
1using (var reader = new StreamReader(@"C:\Users\Public\TestFolder\Gherkin\1.feature"))2{3    var parser = new Parser();4    var feature = parser.Parse(reader);5    var builder = new StringBuilder();6    builder.AppendLine("Feature: " + feature.Name);7    builder.AppendLine("Scenario: " + feature.ScenarioDefinitions[0].Name);8    var scenario = feature.ScenarioDefinitions[0] as Gherkin.Ast.Scenario;9    foreach (var step in scenario.Steps)10    {11        builder.AppendLine("Step: " + step.Text);12    }13    Console.WriteLine(builder.ToString());14}15using (var reader = new StreamReader(@"C:\Users\Public\TestFolder\Gherkin\1.feature"))16{17    var parser = new Parser();18    var feature = parser.Parse(reader);19    var builder = new StringBuilder();20    builder.AppendLine("Feature: " + feature.Name);21    builder.AppendLine("Scenario: " + feature.ScenarioDefinitions[0].Name);22    var scenario = feature.ScenarioDefinitions[0] as Gherkin.Parser.Scenario;23    foreach (var step in scenario.Steps)24    {25        builder.AppendLine("Step: " + step.Text);26    }27    Console.WriteLine(builder.ToString());28}29using (var reader = new StreamReader(@"C:\Users\Public\TestFolder\Gherkin\1.feature"))30{31    var parser = new Parser();32    var feature = parser.Parse(reader);33    var builder = new StringBuilder();34    builder.AppendLine("Feature: " + feature.Name);35    builder.AppendLine("Scenario: " + feature.ScenarioDefinitions[0].Name);36    var scenario = feature.ScenarioDefinitions[0] as Gherkin.Parser.Scenario;37    foreach (var step in scenario.Steps)38    {39        builder.AppendLine("Step: " + step.Text);40    }41    Console.WriteLine(builder.ToString());42}43using (var reader = new StreamReader(@"C:\Users\Public\TestFolder\Gherkin\1.feature"))44{45    var parser = new Parser();46    var feature = parser.Parse(reader);47    var builder = new StringBuilder();48    builder.AppendLine("Feature: " + feature.Name);49    builder.AppendLine("ScenarioLearn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
