Best Gherkin-dotnet code snippet using Gherkin.Ast.Scenario.Scenario
ScenarioOutlineExecutorTests.cs
Source:ScenarioOutlineExecutorTests.cs  
...8using Xunit.Abstractions;9using Xunit.Gherkin.Quick;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,563                                new Gherkin.Ast.TableRow(null,564                                    new Gherkin.Ast.TableCell[]...ScenarioExecutorTests.cs
Source:ScenarioExecutorTests.cs  
...8using Xunit.Abstractions;9using Xunit.Gherkin.Quick;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}...GherkinFeatureTests.cs
Source:GherkinFeatureTests.cs  
...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        }384    }385}...FeatureClassTests.cs
Source:FeatureClassTests.cs  
...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")]...GherkinScenarioOutlineTests.cs
Source:GherkinScenarioOutlineTests.cs  
...4using Xunit;5using Xunit.Gherkin.Quick;6namespace UnitTests7{8    public sealed class GherkinScenarioOutlineTests9    {10        [Theory]11        [InlineData("non-existing example", 0)]12        [InlineData("existing example", 1)]13        public void ApplyExampleRow_Throws_Error_When_Example_Not_Found(14            string exampleName,15            int exampleRowIndex16            )17        {18            //arrange.19            var sut = new Gherkin.Ast.ScenarioOutline(20                null,21                null,22                null,23                "outline123",24                null,25                new Gherkin.Ast.Step[] { },26                new Gherkin.Ast.Examples[] 27                {28                    new Gherkin.Ast.Examples(29                        null,30                        null,31                        null,32                        "existing example",33                        null,34                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]{ }),35                        new Gherkin.Ast.TableRow[]36                        {37                            new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]{ })38                        })39                });40            //act / assert.41            Assert.Throws<InvalidOperationException>(() => sut.ApplyExampleRow(exampleName, exampleRowIndex));42        }43        [Fact]44        public void ApplyExampleRow_Digests_Row_Values_Into_Scenario()45        {46            //arrange.47            var sut = new Gherkin.Ast.ScenarioOutline(48                null,49                null,50                null,51                "outline123",52                null,53                new Gherkin.Ast.Step[] 54                {55                    new Gherkin.Ast.Step(null, "Given", "I chose <a> as first number", null),56                    new Gherkin.Ast.Step(null, "And", "I chose <b> as second number", null),57                    new Gherkin.Ast.Step(null, "When", "I press add", null),58                    new Gherkin.Ast.Step(null, "Then", "the result should be <sum> on the screen", null),59                },60                new Gherkin.Ast.Examples[]61                {62                    new Gherkin.Ast.Examples(63                        null,64                        null,65                        null,66                        "existing example",67                        null,68                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]69                        {70                            new Gherkin.Ast.TableCell(null, "a"),71                            new Gherkin.Ast.TableCell(null, "b"),72                            new Gherkin.Ast.TableCell(null, "sum")73                        }),74                        new Gherkin.Ast.TableRow[]75                        {76                            new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]77                            {78                                new Gherkin.Ast.TableCell(null, "1"),79                                new Gherkin.Ast.TableCell(null, "2"),80                                new Gherkin.Ast.TableCell(null, "3")81                            })82                        })83                });84            //act.85            var scenario = sut.ApplyExampleRow("existing example", 0);86            //assert.87            Assert.NotNull(scenario);88            Assert.Equal(sut.Name, scenario.Name);89            Assert.Equal(sut.Steps.Count(), scenario.Steps.Count());90            Assert.Equal(4, scenario.Steps.Count());91            var sutSteps = sut.Steps.ToList();92            var scenarioSteps = scenario.Steps.ToList();93            ValidateStep(scenarioSteps[0], "Given", "I chose 1 as first number", sutSteps[0]);94            ValidateStep(scenarioSteps[1], "And", "I chose 2 as second number", sutSteps[1]);95            ValidateStep(scenarioSteps[2], "When", "I press add", sutSteps[2]);96            ValidateStep(scenarioSteps[3], "Then", "the result should be 3 on the screen", sutSteps[3]);97            void ValidateStep(Gherkin.Ast.Step step, string keyword, string text,98                Gherkin.Ast.Step other)99            {100                Assert.NotSame(other, step);101                Assert.Equal(keyword, step.Keyword);102                Assert.Equal(text, step.Text);103            }104        }105        [Fact]106        public void ApplyExampleRow_Digests_Row_Values_Into_Scenario_With_Multiple_Placeholders_Per_Step()107        {108            //arrange.109            var sut = new Gherkin.Ast.ScenarioOutline(110                null,111                null,112                null,113                "outline123",114                null,115                new Gherkin.Ast.Step[]116                {117                    new Gherkin.Ast.Step(null, "Given", "I chose <a> as first number and <b> as second number", null),118                    new Gherkin.Ast.Step(null, "When", "I press add", null),119                    new Gherkin.Ast.Step(null, "Then", "the result should be <sum> on the screen", null),120                },121                new Gherkin.Ast.Examples[]122                {123                    new Gherkin.Ast.Examples(124                        null,125                        null,126                        null,127                        "existing example",128                        null,129                        new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]130                        {131                            new Gherkin.Ast.TableCell(null, "a"),132                            new Gherkin.Ast.TableCell(null, "b"),133                            new Gherkin.Ast.TableCell(null, "sum")134                        }),135                        new Gherkin.Ast.TableRow[]136                        {137                            new Gherkin.Ast.TableRow(null, new Gherkin.Ast.TableCell[]138                            {139                                new Gherkin.Ast.TableCell(null, "1"),140                                new Gherkin.Ast.TableCell(null, "2"),141                                new Gherkin.Ast.TableCell(null, "3")142                            })143                        })144                });145            //act.146            var scenario = sut.ApplyExampleRow("existing example", 0);147            //assert.148            Assert.NotNull(scenario);149            Assert.Equal(sut.Name, scenario.Name);150            Assert.Equal(sut.Steps.Count(), scenario.Steps.Count());151            Assert.Equal(3, scenario.Steps.Count());152            var sutSteps = sut.Steps.ToList();153            var scenarioSteps = scenario.Steps.ToList();154            ValidateStep(scenarioSteps[0], "Given", "I chose 1 as first number and 2 as second number", sutSteps[0]);155            ValidateStep(scenarioSteps[1], "When", "I press add", sutSteps[1]);156            ValidateStep(scenarioSteps[2], "Then", "the result should be 3 on the screen", sutSteps[2]);157            void ValidateStep(Gherkin.Ast.Step step, string keyword, string text,158                Gherkin.Ast.Step other)159            {160                Assert.NotSame(other, step);161                Assert.Equal(keyword, step.Keyword);162                Assert.Equal(text, step.Text);163            }164        }165        [Fact]166        public void ApplyExampleRow_Digests_Row_Values_Into_Scenario_With_DataTable_In_Step()167        {168            //arrange.169            var sut = new Gherkin.Ast.ScenarioOutline(170                null,171                null,172                null,173                "outline123",174                null,175                new Gherkin.Ast.Step[]176                {177                    new Gherkin.Ast.Step(null, "Given", "I pass a datatable with tokens", new DataTable(new []178                    {179                        new TableRow(null, new[] { new TableCell(null, "Column1"), new TableCell(null, "Column2") }),180                        new TableRow(null, new[] { new TableCell(null, "<a>"), new TableCell(null, "data with <b> in the middle") }),181                        new TableRow(null, new[] { new TableCell(null, "<b>"), new TableCell(null, "<a>") })182                    })),183                    new Gherkin.Ast.Step(null, "When", "I apply a sample row", null),...FeatureFileTests.cs
Source:FeatureFileTests.cs  
...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  
...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(...GherkinScenarioDefinitionTests.cs
Source:GherkinScenarioDefinitionTests.cs  
...4using Xunit;5using Xunit.Gherkin.Quick;6namespace UnitTests7{8    public class GherkinScenarioTests9    {10        [Fact]11        public void ApplyBackground_WithNoBackground_ThrowsArgumentNullException()12        {13            var scenario = CreateTestScenario();14            Assert.Throws<ArgumentNullException>(() => scenario.ApplyBackground(null));15        }16        [Fact]17        public void ApplyBackground_WithBackground_PrependsBackgroundSteps()18        {            19            var scenario = CreateTestScenario();20            var backgroundSteps = new Gherkin.Ast.Step[] { new Gherkin.Ast.Step(null, null, "background", null) };21            var background = new Gherkin.Ast.Background(null, null, null, null, backgroundSteps);22            var modified = scenario.ApplyBackground(background);23            24            Assert.Equal(scenario.Location, modified.Location);25            Assert.Equal(scenario.Keyword, modified.Keyword);26            Assert.Equal(scenario.Name, modified.Name);27            Assert.Equal(scenario.Description, modified.Description);28            29            Assert.Equal(2, modified.Steps.Count());30            Assert.Equal("background", modified.Steps.ElementAt(0).Text);31            Assert.Equal("step", modified.Steps.ElementAt(1).Text);32        }        33        private static Gherkin.Ast.Scenario CreateTestScenario()34        {35            var tags = new Gherkin.Ast.Tag[] { new Gherkin.Ast.Tag(null, "test") };36            var location = new Gherkin.Ast.Location(1, 1);37            var steps = new Gherkin.Ast.Step[] { new Gherkin.Ast.Step(null, null, "step", null) };38            return new Gherkin.Ast.Scenario(tags, location, "keyword", "name", "description", steps);            39        }40    }41}...Scenario
Using AI Code Generation
1using Gherkin.Ast;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8    {9        static void Main(string[] args)10        {11            var feature = new Feature("Feature", "Feature Description", new List<Tag>(), null, new List<ScenarioDefinition>() {12                new Scenario("Scenario", "Scenario Description", new List<Tag>(), null, new List<Step>() {13                    new Step("Given", "I am a step", 0, null, null)14                }, null)15            }, null);16            var scenario = feature.Scenarios.First() as Scenario;17            Console.WriteLine(scenario.Name);18            Console.WriteLine(scenario.Description);19            Console.WriteLine(scenario.Steps.First().Keyword);20            Console.WriteLine(sceScenario
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}Scenario
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;8{9    {10        static void Main(string[] args)11        {12            Gherkin.Ast.Feature objFeature = new Gherkin.Ast.Feature();13            Parser objParser = new Parser();14            objFeature = objParser.Parse(@"C:\Users\Public\Documents\GherkinTest\Feature1.feature").Feature;15            Gherkin.Ast.Scenario objScenario = new Gherkin.Ast.Scenario();16            objScenario = objFeature.Scenario;17            Console.WriteLine(objScenario);18            Console.ReadLine();19        }20    }21}22using System;23using System.Collections.Generic;24using System.Linq;25using System.Text;26using System.Threading.Tasks;27using Gherkin.Ast;28using Gherkin;29{30    {31        static void Main(string[] args)32        {Learn 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!!
