From 6a773a278422f14d4f428a4ac87f7e870beaf9bf Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 08:59:50 +0100 Subject: [PATCH 01/14] upgrade .net framework move to github actions fix parallel tests failing --- .github/workflows/build.yml | 18 ++++++++++ .gitignore | 1 + src/NuGet.config | 9 ----- .../TestStack.BDDfy.Samples.csproj | 32 ++++++----------- .../Configuration/ProcessorPipelineTests.cs | 1 + .../Configuration/StepExecutorTests.cs | 1 + .../Configuration/TestRunnerTests.cs | 4 ++- .../Exceptions/ExceptionThrowingTest.cs | 6 ++-- .../ExclusiveAccessToConfiguratorFixture.cs | 9 +++++ .../FluentScanner/ComplexStepsTests.cs | 2 +- .../TestStack.BDDfy.Tests.csproj | 35 ++++++------------- src/TestStack.BDDfy.sln | 5 ++- .../Configuration/Processors.cs | 11 +++--- src/TestStack.BDDfy/TestStack.BDDfy.csproj | 31 ++-------------- 14 files changed, 66 insertions(+), 99 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 src/NuGet.config create mode 100644 src/TestStack.BDDfy.Tests/ExclusiveAccessToConfiguratorFixture.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..8159dc69 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,18 @@ +name: Build and Test +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build project + run: dotnet build --configuration Release + + - name: Run tests + run: dotnet test --configuration Release \ No newline at end of file diff --git a/.gitignore b/.gitignore index afcc04ff..a9f4811c 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ tools/Cake/ tools/GitReleaseNotes/ tools/gitversion.commandline/ artifacts/ +*.code-workspace diff --git a/src/NuGet.config b/src/NuGet.config deleted file mode 100644 index 5e4d98d7..00000000 --- a/src/NuGet.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj index 95c86b17..cf437956 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj +++ b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj @@ -1,11 +1,10 @@ - + - netcoreapp2.0 + net8.0 TestStack.BDDfy.Samples TestStack.BDDfy.Samples true - win10-x64 false false false @@ -16,24 +15,13 @@ - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - - - - - - - $(DefineConstants);Approvals;Culture;NSubstitute - - - - - - - diff --git a/src/TestStack.BDDfy.Tests/Configuration/ProcessorPipelineTests.cs b/src/TestStack.BDDfy.Tests/Configuration/ProcessorPipelineTests.cs index 56db7bfc..3ca8a1ab 100644 --- a/src/TestStack.BDDfy.Tests/Configuration/ProcessorPipelineTests.cs +++ b/src/TestStack.BDDfy.Tests/Configuration/ProcessorPipelineTests.cs @@ -7,6 +7,7 @@ namespace TestStack.BDDfy.Tests.Configuration { + [Collection("ExclusiveAccessToConfigurator")] public class ProcessorPipelineTests { [Fact] diff --git a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs b/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs index 27369c30..3d2cc778 100644 --- a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs +++ b/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs @@ -5,6 +5,7 @@ namespace TestStack.BDDfy.Tests.Configuration { + [Collection("ExclusiveAccessToConfigurator")] public class StepExecutorTests { private class TestStepExecutor : StepExecutor diff --git a/src/TestStack.BDDfy.Tests/Configuration/TestRunnerTests.cs b/src/TestStack.BDDfy.Tests/Configuration/TestRunnerTests.cs index 0dd9b950..f89aece7 100644 --- a/src/TestStack.BDDfy.Tests/Configuration/TestRunnerTests.cs +++ b/src/TestStack.BDDfy.Tests/Configuration/TestRunnerTests.cs @@ -1,12 +1,12 @@ using System; using System.Linq; -using NUnit.Framework; using Shouldly; using TestStack.BDDfy.Configuration; using Xunit; namespace TestStack.BDDfy.Tests.Configuration { + [Collection("ExclusiveAccessToConfigurator")] public class TestRunnerTests { public class ScenarioWithFailingThen @@ -104,6 +104,8 @@ public void FailingThenDoesNotStopThePipelineWithReflectiveAPI() [Fact] public void FailingThenDoesNotStopThePipelineWithFluentAPI() { + Configurator.Processors.TestRunner.StopExecutionOnFailingThen = false; + var testRun = new ScenarioWithFailingThen() .Given(x => x.PassingGiven()) .When(x => x.PassingWhen()) diff --git a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs index a9fb85a4..1ca455cd 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs @@ -6,9 +6,9 @@ namespace TestStack.BDDfy.Tests.Exceptions { public class ExceptionThrowingTest where T : Exception, new() { - private static bool _givenShouldThrow; - private static bool _whenShouldThrow; - private static bool _thenShouldThrow; + private bool _givenShouldThrow; + private bool _whenShouldThrow; + private bool _thenShouldThrow; Scenario _scenario; void Given() diff --git a/src/TestStack.BDDfy.Tests/ExclusiveAccessToConfiguratorFixture.cs b/src/TestStack.BDDfy.Tests/ExclusiveAccessToConfiguratorFixture.cs new file mode 100644 index 00000000..2c9f5f33 --- /dev/null +++ b/src/TestStack.BDDfy.Tests/ExclusiveAccessToConfiguratorFixture.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace TestStack.BDDfy.Tests +{ + [CollectionDefinition("ExclusiveAccessToConfigurator", DisableParallelization = true)] + public class ExclusiveAccessToConfiguratorFixture + { + } +} \ No newline at end of file diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs index a8734c85..366df222 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs @@ -13,7 +13,7 @@ public class ComplexStepsTests [Fact] public void ShouldBeAbleToChainComplexTestWithFluentApi() { - this.Given(_ => count.ShouldBe(0)) + this.Given(_ => count.ShouldBe(0, "count should start with 0")) .When(() => count++.ShouldBe(0), "When I do something") .Given(() => count++.ShouldBe(1), "Given I am doing things in different order") .Then(() => count++.ShouldBe(2), "Then they should run in defined order") diff --git a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj index 1e7ea562..89600ae2 100644 --- a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj +++ b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj @@ -1,11 +1,10 @@ - + - netcoreapp2.0 + net8.0 TestStack.BDDfy.Tests TestStack.BDDfy.Tests true - win10-x64 false false false @@ -19,26 +18,14 @@ - - - - - - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - - - - - - - $(DefineConstants);Approvals;Culture - - - - - - - diff --git a/src/TestStack.BDDfy.sln b/src/TestStack.BDDfy.sln index 3c795515..5ab648ed 100644 --- a/src/TestStack.BDDfy.sln +++ b/src/TestStack.BDDfy.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2002 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11018.127 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8F515887-AAB5-4873-8BE9-5AB10685EBCB}" ProjectSection(SolutionItems) = preProject @@ -15,7 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\GitVersion.yml = ..\GitVersion.yml ..\license.txt = ..\license.txt ..\logo.png = ..\logo.png - NuGet.config = NuGet.config ..\readme.md = ..\readme.md EndProjectSection EndProject diff --git a/src/TestStack.BDDfy/Configuration/Processors.cs b/src/TestStack.BDDfy/Configuration/Processors.cs index 66db3dce..f0dd03df 100644 --- a/src/TestStack.BDDfy/Configuration/Processors.cs +++ b/src/TestStack.BDDfy/Configuration/Processors.cs @@ -32,16 +32,13 @@ IEnumerable _GetProcessors(Story story) } } - private readonly TestRunnerFactory _testRunnerFactory = new TestRunnerFactory(() => new TestRunner()); - public TestRunnerFactory TestRunner { get { return _testRunnerFactory; } } + public TestRunnerFactory TestRunner { get; } = new(() => new TestRunner()); - private readonly ProcessorFactory _consoleReportFactory = new ProcessorFactory(() => new ConsoleReporter()); - public ProcessorFactory ConsoleReport { get { return _consoleReportFactory; } } + public ProcessorFactory ConsoleReport { get; } = new(() => new ConsoleReporter()); - private readonly ProcessorFactory _storyCacheFactory = new ProcessorFactory(() => new StoryCache()); - public ProcessorFactory StoryCache { get { return _storyCacheFactory; } } + public ProcessorFactory StoryCache { get; } = new(() => new StoryCache()); - readonly List> _addedProcessors = new List>(); + readonly List> _addedProcessors = []; public Processors Add(Func processorFactory) { diff --git a/src/TestStack.BDDfy/TestStack.BDDfy.csproj b/src/TestStack.BDDfy/TestStack.BDDfy.csproj index afe46749..90af7d26 100644 --- a/src/TestStack.BDDfy/TestStack.BDDfy.csproj +++ b/src/TestStack.BDDfy/TestStack.BDDfy.csproj @@ -1,11 +1,9 @@ - + - netcoreapp2.0;net40;netstandard1.5 + net8.0 TestStack.BDDfy TestStack.BDDfy - $(PackageTargetFallback);dnxcore50 - 1.6.0 false false false @@ -19,29 +17,4 @@ - - - - - - - - - - $(DefineConstants);APPDOMAIN;STACKTRACE - - - - - - - - - - - - - - - From 28aad5fd93355d3b0ddb2c3fb7ad644ad5ae1d81 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 09:07:19 +0100 Subject: [PATCH 02/14] fix path for building solution --- .github/workflows/build.yml | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8159dc69..380fbb06 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,8 +11,34 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.0.x' + - name: Build project + working-directory: src run: dotnet build --configuration Release - - name: Run tests - run: dotnet test --configuration Release \ No newline at end of file + - name: Run tests with coverage + working-directory: src + run: dotnet test --configuration Release --collect:"XPlat Code Coverage" --results-directory ./coverage + + - name: Generate coverage report + uses: danielpalme/ReportGenerator-GitHub-Action@5.2.0 + with: + reports: 'coverage/**/coverage.cobertura.xml' + targetdir: 'coverage-report' + reporttypes: 'Html;Cobertura' + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + files: ./coverage/**/coverage.cobertura.xml + fail_ci_if_error: false + + - name: Publish coverage report as artifact + uses: actions/upload-artifact@v3 + with: + name: coverage-report + path: coverage-report/ \ No newline at end of file From 348b9c4d7ceed0302e7c15c83af8d0944884bc87 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 09:13:02 +0100 Subject: [PATCH 03/14] update outdated actions for workflow steps --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 380fbb06..c9fc17a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,10 +9,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v5 with: dotnet-version: '8.0.x' @@ -25,20 +25,20 @@ jobs: run: dotnet test --configuration Release --collect:"XPlat Code Coverage" --results-directory ./coverage - name: Generate coverage report - uses: danielpalme/ReportGenerator-GitHub-Action@5.2.0 + uses: danielpalme/ReportGenerator-GitHub-Action@5.4.16 with: reports: 'coverage/**/coverage.cobertura.xml' targetdir: 'coverage-report' reporttypes: 'Html;Cobertura' - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v5 with: files: ./coverage/**/coverage.cobertura.xml fail_ci_if_error: false - name: Publish coverage report as artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-report path: coverage-report/ \ No newline at end of file From 7a47e7e5d44fa75d0bc8ea1c66b3ac9c94e98db2 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 09:28:42 +0100 Subject: [PATCH 04/14] add exclusive access to configurator for overlapping tests --- src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs | 1 + .../Scanner/FluentScanner/ComplexStepsTests.cs | 1 + tools/packages.config | 4 ---- 3 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 tools/packages.config diff --git a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs index 29f11fce..3215f5d8 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs @@ -7,6 +7,7 @@ namespace TestStack.BDDfy.Tests.Reporters.Html { + [Collection("ExclusiveAccessToConfigurator")] public class HtmlReporterTests { private TestableHtmlReporter _sut; diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs index 366df222..e97b5c23 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ComplexStepsTests.cs @@ -6,6 +6,7 @@ namespace TestStack.BDDfy.Tests.Scanner.FluentScanner { + [Collection("ExclusiveAccessToConfigurator")] public class ComplexStepsTests { private int count; diff --git a/tools/packages.config b/tools/packages.config deleted file mode 100644 index 94fad2bd..00000000 --- a/tools/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - From d21ecff8877282647289b7d1bf8248a83f813b93 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 11:10:25 +0100 Subject: [PATCH 05/14] fix the way path is generated so that it is consistent across linux and windows --- .../Reporters/Html/HtmlReporterTests.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs index 3215f5d8..bfa0b4ca 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using NSubstitute; using Shouldly; using TestStack.BDDfy.Reporters; @@ -7,7 +8,6 @@ namespace TestStack.BDDfy.Tests.Reporters.Html { - [Collection("ExclusiveAccessToConfigurator")] public class HtmlReporterTests { private TestableHtmlReporter _sut; @@ -48,7 +48,8 @@ public void ShouldPrintErrorInReportIfProcessingFails() [Fact] public void ShouldLoadCustomStyleSheetIfOneExists() { - const string customStylesheetFilePath = OutputPath + @"\BDDfyCustom.css"; + var customStylesheetFilePath = Path.Combine(OutputPath, "BDDfyCustom.css"); + _sut.Configuration.OutputPath.Returns(OutputPath); _sut.FileReader.Exists(customStylesheetFilePath).Returns(true); _sut.FileReader.Read(customStylesheetFilePath).Returns(CustomStylesheet); @@ -62,7 +63,7 @@ public void ShouldLoadCustomStyleSheetIfOneExists() [Fact] public void ShouldNotLoadCustomStyleSheetIfNoneExist() { - const string customStylesheet = OutputPath + @"\BDDfyCustom.css"; + var customStylesheet = Path.Combine(OutputPath, "BDDfyCustom.css"); _sut.Configuration.OutputPath.Returns(OutputPath); _sut.FileReader.Exists(customStylesheet).Returns(false); @@ -75,7 +76,7 @@ public void ShouldNotLoadCustomStyleSheetIfNoneExist() [Fact] public void ShouldLoadCustomJavascriptIfOneExists() { - const string javaScriptFilePath = OutputPath + @"\BDDfyCustom.js"; + var javaScriptFilePath = Path.Combine(OutputPath, "BDDfyCustom.js"); _sut.Configuration.OutputPath.Returns(OutputPath); _sut.FileReader.Exists(javaScriptFilePath).Returns(true); _sut.FileReader.Read(javaScriptFilePath).Returns(CustomJavascript); @@ -89,7 +90,7 @@ public void ShouldLoadCustomJavascriptIfOneExists() [Fact] public void ShouldNotLoadCustomJavascriptIfNoneExist() { - const string customJavascript = OutputPath + @"\BDDfyCustom.js"; + var customJavascript = Path.Combine(OutputPath, "BDDfyCustom.js"); _sut.Configuration.OutputPath.Returns(OutputPath); _sut.FileReader.Exists(customJavascript).Returns(false); From e0f794a6cf1b8ddc2543885440981360ae6e2a06 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 11:15:52 +0100 Subject: [PATCH 06/14] fix coverage report output path --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9fc17a9..8e318fa5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: - name: Run tests with coverage working-directory: src - run: dotnet test --configuration Release --collect:"XPlat Code Coverage" --results-directory ./coverage + run: dotnet test --configuration Release --collect:"XPlat Code Coverage" --results-directory ../coverage - name: Generate coverage report uses: danielpalme/ReportGenerator-GitHub-Action@5.4.16 From a7528ac869f638e8b44e37e50977ea0572452da6 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 11:24:14 +0100 Subject: [PATCH 07/14] add coverage collector remove all the build warnings --- .gitignore | 1 + src/.editorconfig | 4 + .../AssemblySetupFixture.cs | 74 +++----- .../Atm/AccountHolderWithdrawsCash.cs | 18 +- .../TestStack.BDDfy.Samples/Atm/Atm.cs | 21 +-- .../BuyingTrainFares/Money.cs | 9 +- .../CanRunAsyncSteps.cs | 6 +- .../CanWorkWithoutAStory.cs | 6 +- .../CustomTextReporter.cs | 6 +- .../TestStack.BDDfy.Samples.csproj | 4 + .../TicTacToe/TicTacToe.cs | 12 +- .../TicTacToe/WinnerGame.cs | 18 +- .../Arguments/ArgumentsProvidedForGiven.cs | 6 +- ...MultipleArgumentsProvidedForTheSameStep.cs | 2 +- .../Configuration/StepExecutorTests.cs | 2 +- .../Disposer/DisposingScenarios.cs | 15 +- .../Processors/TestRunnerTests.cs | 2 +- .../WhenBuildingReportDiagnostics.cs | 14 +- .../Reporters/ReportTestData.cs | 86 +++++----- .../FluentScanner/BDDfyUsingFluentApi.cs | 18 +- .../ExpressionExtensionsTests.cs | 2 +- .../Scanner/FluentScanner/StepTitleTests.cs | 2 +- .../WhenStepsReturnTheirText.cs | 12 +- .../TestStack.BDDfy.Tests.csproj | 4 + src/TestStack.BDDfy.sln | 3 +- .../Configuration/BatchProcessors.cs | 10 +- .../Configuration/Configurator.cs | 6 +- src/TestStack.BDDfy/Configuration/Scanners.cs | 6 +- src/TestStack.BDDfy/Engine.cs | 9 +- .../Processors/AsyncTestSyncContext.cs | 2 +- .../Processors/ExceptionProcessor.cs | 11 +- .../Processors/ScenarioExecutor.cs | 9 +- .../Processors/UnusedExampleException.cs | 7 +- src/TestStack.BDDfy/Properties/Annotations.cs | 161 +++++------------- .../Diagnostics/DiagnosticsReportBuilder.cs | 9 +- .../Diagnostics/DiagnosticsReporter.cs | 12 +- .../Reporters/FileReportModel.cs | 15 +- .../Reporters/Html/HtmlReportModel.cs | 10 +- .../Reporters/Html/HtmlReportResources.cs | 8 +- .../Reporters/Html/HtmlReportTag.cs | 12 +- .../Reporters/Html/HtmlReporter.cs | 27 ++- .../MarkDown/MarkDownReportBuilder.cs | 2 +- .../Reporters/MarkDown/MarkDownReporter.cs | 12 +- .../Reporters/Serializers/JsonFormatter.cs | 20 +-- src/TestStack.BDDfy/Reporters/TextReporter.cs | 4 +- .../Scanners/DefaultScanner.cs | 15 +- .../ScenarioScanners/FluentScenarioScanner.cs | 12 +- .../ReflectiveScenarioScanner.cs | 12 +- .../Scanners/StepScanners/Examples/Example.cs | 9 +- .../StepScanners/Examples/ExampleAction.cs | 12 +- .../StepScanners/Examples/ExampleTable.cs | 11 +- .../StepScanners/Examples/ExampleValue.cs | 15 +- .../Examples/UnassignableExampleException.cs | 8 +- .../ExecutableAttribute.cs | 15 +- .../GwtAttributes/AndGivenAttribute.cs | 3 +- .../GwtAttributes/AndWhenAttribute.cs | 3 +- .../GwtAttributes/ButGivenAttribute.cs | 7 +- .../GwtAttributes/ButWhenAttribute.cs | 7 +- .../GwtAttributes/GivenAttribute.cs | 3 +- .../GwtAttributes/WhenAttribute.cs | 3 +- .../StepScanners/Fluent/FluentScanner.cs | 2 +- .../MethodName/MethodNameMatcher.cs | 18 +- .../StepScanners/RunStepWithArgsAttribute.cs | 9 +- src/TestStack.BDDfy/Scanners/StoryMetadata.cs | 32 +--- src/TestStack.BDDfy/TestContext.cs | 4 +- src/testEnvironments.json | 10 ++ 66 files changed, 312 insertions(+), 597 deletions(-) create mode 100644 src/.editorconfig create mode 100644 src/testEnvironments.json diff --git a/.gitignore b/.gitignore index a9f4811c..ad4aa3cb 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ tools/GitReleaseNotes/ tools/gitversion.commandline/ artifacts/ *.code-workspace +**/coverage diff --git a/src/.editorconfig b/src/.editorconfig new file mode 100644 index 00000000..dd2b5504 --- /dev/null +++ b/src/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# Default severity for analyzer diagnostics with category 'Style' +dotnet_analyzer_diagnostic.category-Style.severity = none diff --git a/src/Samples/TestStack.BDDfy.Samples/AssemblySetupFixture.cs b/src/Samples/TestStack.BDDfy.Samples/AssemblySetupFixture.cs index 5e375cf7..8c3c8d61 100644 --- a/src/Samples/TestStack.BDDfy.Samples/AssemblySetupFixture.cs +++ b/src/Samples/TestStack.BDDfy.Samples/AssemblySetupFixture.cs @@ -33,55 +33,36 @@ public AssemblySetupFixture() } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public class AssemblyFixtureAttribute : Attribute + public class AssemblyFixtureAttribute(Type fixtureType): Attribute { - public AssemblyFixtureAttribute(Type fixtureType) - { - FixtureType = fixtureType; - } - - public Type FixtureType { get; private set; } + public Type FixtureType { get; private set; } = fixtureType; } - public class XunitTestFrameworkWithAssemblyFixture : XunitTestFramework + public class XunitTestFrameworkWithAssemblyFixture(IMessageSink messageSink): XunitTestFramework(messageSink) { - public XunitTestFrameworkWithAssemblyFixture(IMessageSink messageSink) - : base(messageSink) - { } - protected override ITestFrameworkExecutor CreateExecutor(AssemblyName assemblyName) => new XunitTestFrameworkExecutorWithAssemblyFixture(assemblyName, SourceInformationProvider, DiagnosticMessageSink); } - public class XunitTestFrameworkExecutorWithAssemblyFixture : XunitTestFrameworkExecutor + public class XunitTestFrameworkExecutorWithAssemblyFixture(AssemblyName assemblyName, + ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink): XunitTestFrameworkExecutor(assemblyName, sourceInformationProvider, diagnosticMessageSink) { - public XunitTestFrameworkExecutorWithAssemblyFixture(AssemblyName assemblyName, - ISourceInformationProvider sourceInformationProvider, IMessageSink diagnosticMessageSink) - : base(assemblyName, sourceInformationProvider, diagnosticMessageSink) - { - } - protected override async void RunTestCases(IEnumerable testCases, IMessageSink executionMessageSink, ITestFrameworkExecutionOptions executionOptions) { - using ( - var assemblyRunner = new XunitTestAssemblyRunnerWithAssemblyFixture(TestAssembly, testCases, - DiagnosticMessageSink, executionMessageSink, executionOptions)) - await assemblyRunner.RunAsync(); + using var assemblyRunner = new XunitTestAssemblyRunnerWithAssemblyFixture(TestAssembly, testCases, + DiagnosticMessageSink, executionMessageSink, executionOptions); + await assemblyRunner.RunAsync(); } } - public class XunitTestAssemblyRunnerWithAssemblyFixture : XunitTestAssemblyRunner + public class XunitTestAssemblyRunnerWithAssemblyFixture(ITestAssembly testAssembly, + IEnumerable testCases, + IMessageSink diagnosticMessageSink, + IMessageSink executionMessageSink, + ITestFrameworkExecutionOptions executionOptions): XunitTestAssemblyRunner(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions) { - readonly Dictionary assemblyFixtureMappings = new Dictionary(); - - public XunitTestAssemblyRunnerWithAssemblyFixture(ITestAssembly testAssembly, - IEnumerable testCases, - IMessageSink diagnosticMessageSink, - IMessageSink executionMessageSink, - ITestFrameworkExecutionOptions executionOptions) - : base(testAssembly, testCases, diagnosticMessageSink, executionMessageSink, executionOptions) - { } + readonly Dictionary assemblyFixtureMappings = new(); protected override async Task AfterTestAssemblyStartingAsync() { @@ -118,24 +99,17 @@ protected override Task RunTestCollectionAsync(IMessageBus messageBu => new XunitTestCollectionRunnerWithAssemblyFixture(assemblyFixtureMappings, testCollection, testCases, DiagnosticMessageSink, messageBus, TestCaseOrderer, new ExceptionAggregator(Aggregator), cancellationTokenSource).RunAsync(); } - public class XunitTestCollectionRunnerWithAssemblyFixture : XunitTestCollectionRunner + public class XunitTestCollectionRunnerWithAssemblyFixture(Dictionary assemblyFixtureMappings, + ITestCollection testCollection, + IEnumerable testCases, + IMessageSink diagnosticMessageSink, + IMessageBus messageBus, + ITestCaseOrderer testCaseOrderer, + ExceptionAggregator aggregator, + CancellationTokenSource cancellationTokenSource): XunitTestCollectionRunner(testCollection, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource) { - readonly Dictionary assemblyFixtureMappings; - readonly IMessageSink diagnosticMessageSink; - - public XunitTestCollectionRunnerWithAssemblyFixture(Dictionary assemblyFixtureMappings, - ITestCollection testCollection, - IEnumerable testCases, - IMessageSink diagnosticMessageSink, - IMessageBus messageBus, - ITestCaseOrderer testCaseOrderer, - ExceptionAggregator aggregator, - CancellationTokenSource cancellationTokenSource) - : base(testCollection, testCases, diagnosticMessageSink, messageBus, testCaseOrderer, aggregator, cancellationTokenSource) - { - this.assemblyFixtureMappings = assemblyFixtureMappings; - this.diagnosticMessageSink = diagnosticMessageSink; - } + readonly Dictionary assemblyFixtureMappings = assemblyFixtureMappings; + readonly IMessageSink diagnosticMessageSink = diagnosticMessageSink; protected override Task RunTestClassAsync(ITestClass testClass, IReflectionTypeInfo @class, IEnumerable testCases) { diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs index 894b012e..a31fb495 100644 --- a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs +++ b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs @@ -19,47 +19,47 @@ public class AccountHolderWithdrawsCash private Card _card; private Atm _atm; - public void Given_the_Account_Balance_is(int balance) + internal void Given_the_Account_Balance_is(int balance) { _card = new Card(true, balance); } - public void Given_the_Card_is_disabled() + internal void Given_the_Card_is_disabled() { _card = new Card(false, 100); _atm = new Atm(100); } - public void And_the_Card_is_valid() + internal void And_the_Card_is_valid() { } - public void And_the_machine_contains(int atmBalance) + internal void And_the_machine_contains(int atmBalance) { _atm = new Atm(atmBalance); } - public void When_the_Account_Holder_requests(int moneyRequest) + internal void When_the_Account_Holder_requests(int moneyRequest) { _atm.RequestMoney(_card, moneyRequest); } - public void The_ATM_should_dispense(int dispensedMoney) + internal void The_ATM_should_dispense(int dispensedMoney) { _atm.DispenseValue.ShouldBe(dispensedMoney); } - public void And_the_Account_Balance_should_be(int balance) + internal void And_the_Account_Balance_should_be(int balance) { _card.AccountBalance.ShouldBe(balance); } - public void Then_Card_is_retained(bool cardIsRetained) + internal void Then_Card_is_retained(bool cardIsRetained) { _atm.CardIsRetained.ShouldBe(cardIsRetained); } - void And_the_ATM_should_say_the_Card_has_been_retained() + internal void And_the_ATM_should_say_the_Card_has_been_retained() { _atm.Message.ShouldBe(DisplayMessage.CardIsRetained); } diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/Atm.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/Atm.cs index cfc509e9..ede74525 100644 --- a/src/Samples/TestStack.BDDfy.Samples/Atm/Atm.cs +++ b/src/Samples/TestStack.BDDfy.Samples/Atm/Atm.cs @@ -1,13 +1,8 @@ namespace TestStack.BDDfy.Samples.Atm { - public class Atm + public class Atm(int existingCash) { - public int ExistingCash { get; private set; } - - public Atm(int existingCash) - { - ExistingCash = existingCash; - } + public int ExistingCash { get; private set; } = existingCash; public void RequestMoney(Card card, int request) { @@ -35,16 +30,10 @@ public void RequestMoney(Card card, int request) public DisplayMessage Message { get; private set; } } - public class Card + public class Card(bool enabled, int accountBalance) { - public int AccountBalance { get; set; } - private readonly bool _enabled; - - public Card(bool enabled, int accountBalance) - { - AccountBalance = accountBalance; - _enabled = enabled; - } + public int AccountBalance { get; set; } = accountBalance; + private readonly bool _enabled = enabled; public bool Enabled { diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs index 2ec30b57..b032fa3d 100644 --- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs +++ b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs @@ -2,14 +2,9 @@ namespace TestStack.BDDfy.Samples.BuyingTrainFares { - class Money + class Money(decimal amount) { - public Money(decimal amount) - { - Amount = amount; - } - - public decimal Amount { get; set; } + public decimal Amount { get; set; } = amount; protected bool Equals(Money other) { diff --git a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs index 4efbdb8f..1025b3a3 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs @@ -9,17 +9,17 @@ public class CanRunAsyncSteps { private Sut _sut; - public async void GivenSomeAsyncSetup() + internal async void GivenSomeAsyncSetup() { _sut = await CreateSut(); } - public void ThenBddfyHasWaitedForThatSetupToCompleteBeforeContinuing() + internal void ThenBddfyHasWaitedForThatSetupToCompleteBeforeContinuing() { _sut.ShouldNotBe(null); } - public async Task AndThenBddfyShouldCaptureExceptionsThrownInAsyncMethod() + internal async Task AndThenBddfyShouldCaptureExceptionsThrownInAsyncMethod() { await Task.Yield(); throw new Exception("Exception in async void method!!"); diff --git a/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs b/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs index e2194be2..ac41d335 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs @@ -4,15 +4,15 @@ namespace TestStack.BDDfy.Samples { public class CanWorkWithoutAStory { - public void Given_no_story_is_provided() + internal void Given_no_story_is_provided() { } - public void When_we_BDDfy_the_class() + internal void When_we_BDDfy_the_class() { } - public void Then_the_namespace_is_used_in_the_report() + internal void Then_the_namespace_is_used_in_the_report() { } diff --git a/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs b/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs index 152d28d1..5293448a 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs @@ -18,10 +18,8 @@ private static string OutputDirectory { get { - string codeBase = typeof(CustomTextReporter).GetTypeInfo().Assembly.CodeBase; - var uri = new UriBuilder(codeBase); - string path = Uri.UnescapeDataString(uri.Path); - return System.IO.Path.GetDirectoryName(path); + string codeBase = typeof(CustomTextReporter).GetTypeInfo().Assembly.Location; + return System.IO.Path.GetDirectoryName(codeBase); } } diff --git a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj index cf437956..5709e62e 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj +++ b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj @@ -15,6 +15,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs index ff6759f2..726295a3 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs +++ b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/TicTacToe.cs @@ -10,16 +10,10 @@ namespace TestStack.BDDfy.Samples.TicTacToe SoThat = "So that I can waste some time!")] public class TicTacToe : NewGame { - class Cell + class Cell(int row, int col) { - public Cell(int row, int col) - { - Row = row; - Col = col; - } - - public int Row { get; set; } - public int Col { get; set; } + public int Row { get; set; } = row; + public int Col { get; set; } = col; public override string ToString() { diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs index 452865be..43e363eb 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs +++ b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/WinnerGame.cs @@ -4,20 +4,12 @@ namespace TestStack.BDDfy.Samples.TicTacToe { - public class WinnerGame : GameUnderTest + public class WinnerGame(string[] firstRow, string[] secondRow, string[] thirdRow, string expectedWinner): GameUnderTest { - private readonly string[] _firstRow; - private readonly string[] _secondRow; - private readonly string[] _thirdRow; - private readonly string _expectedWinner; - - public WinnerGame(string[] firstRow, string[] secondRow, string[] thirdRow, string expectedWinner) - { - _firstRow = firstRow; - _secondRow = secondRow; - _thirdRow = thirdRow; - _expectedWinner = expectedWinner; - } + private readonly string[] _firstRow = firstRow; + private readonly string[] _secondRow = secondRow; + private readonly string[] _thirdRow = thirdRow; + private readonly string _expectedWinner = expectedWinner; // Note: This method returns IEnumerable // this is done to allow the method to return its title. diff --git a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs index 94814322..cc6bb5a8 100644 --- a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs +++ b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs @@ -6,9 +6,9 @@ namespace TestStack.BDDfy.Tests.Arguments { public class ArgumentsProvidedForGiven { - private readonly List _andGivenInput1 = new List(); - private List _andGivenInput2 = new List(); - private List _andGivenInput3 = new List(); + private readonly List _andGivenInput1 = new(); + private List _andGivenInput2 = new(); + private List _andGivenInput3 = new(); private int _givenInput3; private int _givenInput2; diff --git a/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs b/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs index ffcae947..893b13c9 100644 --- a/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs +++ b/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs @@ -6,7 +6,7 @@ namespace TestStack.BDDfy.Tests.Arguments { public class MultipleArgumentsProvidedForTheSameStep { - private readonly List _inputs = new List(); + private readonly List _inputs = new(); [RunStepWithArgs(1)] [RunStepWithArgs(2)] diff --git a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs b/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs index 3d2cc778..8d9e1916 100644 --- a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs +++ b/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs @@ -10,7 +10,7 @@ public class StepExecutorTests { private class TestStepExecutor : StepExecutor { - readonly StringBuilder _builder = new StringBuilder(); + readonly StringBuilder _builder = new(); public string Results { diff --git a/src/TestStack.BDDfy.Tests/Disposer/DisposingScenarios.cs b/src/TestStack.BDDfy.Tests/Disposer/DisposingScenarios.cs index ca061630..a47ad897 100644 --- a/src/TestStack.BDDfy.Tests/Disposer/DisposingScenarios.cs +++ b/src/TestStack.BDDfy.Tests/Disposer/DisposingScenarios.cs @@ -9,18 +9,11 @@ namespace TestStack.BDDfy.Tests.Disposer { public class DisposingScenarios { - class DisposableScenario : IDisposable + class DisposableScenario(ThrowingMethods throwingMethods): IDisposable { - private readonly bool _givenThrows; - private readonly bool _whenThrows; - private readonly bool _thenThrows; - - public DisposableScenario(ThrowingMethods throwingMethods) - { - _givenThrows = (throwingMethods & ThrowingMethods.Given) > 0; - _whenThrows = (throwingMethods & ThrowingMethods.When) > 0; - _thenThrows = (throwingMethods & ThrowingMethods.Then) > 0; - } + private readonly bool _givenThrows = (throwingMethods & ThrowingMethods.Given) > 0; + private readonly bool _whenThrows = (throwingMethods & ThrowingMethods.When) > 0; + private readonly bool _thenThrows = (throwingMethods & ThrowingMethods.Then) > 0; public void Given() { diff --git a/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs b/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs index 3fa7a968..85b32b7f 100644 --- a/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs +++ b/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs @@ -23,7 +23,7 @@ public void InitializesScenarioWithExampleBeforeRunning() var sut = new TestRunner(); Func action = o => actualValue = ExampleValue; - var steps = new List { new Step(action, new StepTitle("A Step"), true, ExecutionOrder.Initialize, true, new List()) }; + var steps = new List { new(action, new StepTitle("A Step"), true, ExecutionOrder.Initialize, true, new List()) }; var scenarioWithExample = new Scenario("id", this, steps, "Scenario Text", exampleTable, new List()); var story = new Story(new StoryMetadata(typeof(TestRunnerTests), new StoryNarrativeAttribute()), scenarioWithExample); diff --git a/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs b/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs index 6fb24422..0f82ef98 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs @@ -13,38 +13,38 @@ public class WhenBuildingReportDiagnostics private IEnumerable _stories; private IList _result; - public void GivenADiagnosticsReportBuilder() + internal void GivenADiagnosticsReportBuilder() { _sut = new DiagnosticsReportBuilder(); } - public void AndGivenTwoStoriesEachWithTwoScenariosWithThreeStepsOfFiveMilliseconds() + internal void AndGivenTwoStoriesEachWithTwoScenariosWithThreeStepsOfFiveMilliseconds() { _stories = new ReportTestData().CreateTwoStoriesEachWithOneFailingScenarioAndOnePassingScenarioWithThreeStepsOfFiveMilliseconds(); } - public void WhenTheDiagnosticDataIsCalculated() + internal void WhenTheDiagnosticDataIsCalculated() { _result = _sut.GetDiagnosticData(new FileReportModel(_stories.ToReportModel())); } - public void ThenTwoStoriesShouldBeReturned() + internal void ThenTwoStoriesShouldBeReturned() { _result.Count.ShouldBe(2); } - public void AndThenEachStoryShouldHaveDurationOf30Milliseconds() + internal void AndThenEachStoryShouldHaveDurationOf30Milliseconds() { _result.ToList().ForEach(story => story.Duration.ShouldBe(30)); } - public void AndThenEachScenarioShouldHaveDurationOf10Milliseconds() + internal void AndThenEachScenarioShouldHaveDurationOf10Milliseconds() { _result[0].Scenarios.ForEach(scenario => scenario.Duration.ShouldBe(15)); _result[1].Scenarios.ForEach(scenario => scenario.Duration.ShouldBe(15)); } - public void AndThenEachStepShouldHaveDurationOf5Milliseconds() + internal void AndThenEachStepShouldHaveDurationOf5Milliseconds() { _result[0].Scenarios.ForEach(scenario => scenario.Steps.ForEach(step => step.Duration.ShouldBe(5))); _result[1].Scenarios.ForEach(scenario => scenario.Steps.ForEach(step => step.Duration.ShouldBe(5))); diff --git a/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs b/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs index 9b772d63..d6da41d4 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs @@ -15,8 +15,8 @@ public IEnumerable CreateTwoStoriesEachWithOneFailingScenarioAndOnePassin var storyMetadata2 = new StoryMetadata(typeof(GoldAccountHolderStory), "As an account holder", "I want to withdraw cash", "So that I can get money when the bank is closed", "Account holder withdraws cash"); var stories = new List { - new Story(storyMetadata1, GetScenarios(false, false)), - new Story(storyMetadata2, GetScenarios(true, false)) + new(storyMetadata1, GetScenarios(false, false)), + new(storyMetadata2, GetScenarios(true, false)) }; return stories; @@ -31,9 +31,9 @@ public IEnumerable CreateMixContainingEachTypeOfOutcome() var stories = new List { - new Story(storyMetadata1, GetOneOfEachScenarioResult()), - new Story(storyMetadata2, GetOneOfEachScenarioResult()), - new Story(testThatReportWorksWithNoStory, GetOneOfEachScenarioResult()) + new(storyMetadata1, GetOneOfEachScenarioResult()), + new(storyMetadata2, GetOneOfEachScenarioResult()), + new(testThatReportWorksWithNoStory, GetOneOfEachScenarioResult()) }; return stories; @@ -49,16 +49,16 @@ public IEnumerable CreateMixContainingEachTypeOfOutcomeWithOneScenarioPer var stories = new List { - new Story(storyMetadata1, new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario [for Happiness]", new List())), - new Story(storyMetadata1, new Scenario(typeof(SadPathScenario), GetFailingExecutionSteps(), "Sad Path Scenario [for Happiness]", new List())), - new Story(storyMetadata1, new Scenario(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario [for Happiness]", new List())), - new Story(storyMetadata1, new Scenario(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario [for Happiness]", new List())), - new Story(testThatReportWorksWithNoStory, new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario [with no story]", new List())), - new Story(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetFailingExecutionSteps(), "Sad Path Scenario [with no story]", new List())), - new Story(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario [with no story]", new List())), - new Story(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario [with no story]", new List())), - new Story(storyMetadata2, GetScenarios(true, true)), - new Story(storyMetadata3, GetScenarios(false, true)), + new(storyMetadata1, new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario [for Happiness]", new List())), + new(storyMetadata1, new Scenario(typeof(SadPathScenario), GetFailingExecutionSteps(), "Sad Path Scenario [for Happiness]", new List())), + new(storyMetadata1, new Scenario(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario [for Happiness]", new List())), + new(storyMetadata1, new Scenario(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario [for Happiness]", new List())), + new(testThatReportWorksWithNoStory, new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario [with no story]", new List())), + new(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetFailingExecutionSteps(), "Sad Path Scenario [with no story]", new List())), + new(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario [with no story]", new List())), + new(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario [with no story]", new List())), + new(storyMetadata2, GetScenarios(true, true)), + new(storyMetadata3, GetScenarios(false, true)), }; return stories; @@ -70,8 +70,8 @@ public IEnumerable CreateTwoStoriesEachWithOneFailingScenarioAndOnePassin var storyMetadata2 = new StoryMetadata(typeof(GoldAccountHolderStory), "As an account holder", "I want to withdraw cash", "So that I can get money when the bank is closed", "Account holder withdraws cash"); var stories = new List { - new Story(storyMetadata1, GetScenarios(false, true)), - new Story(storyMetadata2, GetScenarios(true, true)) + new(storyMetadata1, GetScenarios(false, true)), + new(storyMetadata2, GetScenarios(true, true)) }; return stories; @@ -118,15 +118,15 @@ private Scenario[] GetScenarios(bool includeFailingScenario, bool includeExample } return new List { - new Scenario(exampleId, typeof(ExampleScenario), GetExampleExecutionSteps(), "Example Scenario", exampleTable.ElementAt(0), new List()), - new Scenario(exampleId, typeof(ExampleScenario), exampleExecutionSteps, "Example Scenario", exampleTable.ElementAt(1), new List()) + new(exampleId, typeof(ExampleScenario), GetExampleExecutionSteps(), "Example Scenario", exampleTable.ElementAt(0), new List()), + new(exampleId, typeof(ExampleScenario), exampleExecutionSteps, "Example Scenario", exampleTable.ElementAt(1), new List()) }.ToArray(); } return new List { - new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", new List()), - new Scenario(typeof(SadPathScenario), sadExecutionSteps, "Sad Path Scenario", new List()) + new(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", new List()), + new(typeof(SadPathScenario), sadExecutionSteps, "Sad Path Scenario", new List()) }.ToArray(); } @@ -134,10 +134,10 @@ private Scenario[] GetOneOfEachScenarioResult() { var scenarios = new List { - new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", new List()), - new Scenario(typeof(SadPathScenario), GetSadExecutionSteps(), "Sad Path Scenario", new List()), - new Scenario(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario", new List()), - new Scenario(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario", new List()) + new(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", new List()), + new(typeof(SadPathScenario), GetSadExecutionSteps(), "Sad Path Scenario", new List()), + new(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario", new List()), + new(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario", new List()) }; // override specific step results - ideally this class could be refactored to provide objectmother/builder interface @@ -162,9 +162,9 @@ private List GetHappyExecutionSteps() { var steps = new List { - new Step(null, new StepTitle("Given a positive account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, - new Step(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, - new Step(null, new StepTitle("Then money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Given a positive account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Then money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, }; return steps; } @@ -173,9 +173,9 @@ private List GetExampleExecutionSteps() { var steps = new List { - new Step(null, new StepTitle("Given a account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, - new Step(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, - new Step(null, new StepTitle("Then money dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Given a account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Then money dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, }; return steps; } @@ -184,9 +184,9 @@ private List GetSadExecutionSteps() { var steps = new List { - new Step(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, - new Step(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, - new Step(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, }; return steps; } @@ -195,9 +195,9 @@ private List GetFailingExecutionSteps() { var steps = new List { - new Step(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()), - new Step(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()), - new Step(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()), + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()), + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()), + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()), }; SetAllStepResults(steps, Result.Passed); @@ -220,9 +220,9 @@ private List GetInconclusiveExecutionSteps() { var steps = new List { - new Step(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, - new Step(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, - new Step(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, }; SetAllStepResults(steps, Result.Passed); @@ -237,9 +237,9 @@ private List GetNotImplementedExecutionSteps() { var steps = new List { - new Step(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, - new Step(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, - new Step(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, new List()) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, }; SetAllStepResults(steps, Result.Passed); diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs index db0551b6..bfc913ca 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs @@ -36,51 +36,51 @@ public class BDDfyUsingFluentApi private SomeEnumForTesting _enumInput; private Action _action; - public void GivenAnAction(Action actionInput) + internal void GivenAnAction(Action actionInput) { _action = actionInput; } - public void ThenCallingTheActionThrows() where T : Exception + internal void ThenCallingTheActionThrows() where T : Exception { Should.Throw(() => _action()); } - public void GivenPrimitiveInputs(string input1, int input2) + internal void GivenPrimitiveInputs(string input1, int input2) { _primitiveInput1 = input1; _primitiveInput2 = input2; } - public void GivenEnumInputs(SomeEnumForTesting input) + internal void GivenEnumInputs(SomeEnumForTesting input) { _enumInput = input; } - public void GivenArrayInputs(string[] input1, int[] input2) + internal void GivenArrayInputs(string[] input1, int[] input2) { _arrayInput1 = input1; _arrayInput2 = input2; } - public void GivenEnumerableInputs(IEnumerable input1, IEnumerable input2) + internal void GivenEnumerableInputs(IEnumerable input1, IEnumerable input2) { _arrayInput1 = input1.ToArray(); _arrayInput2 = input2.ToArray(); } - public void ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(string expectedInput1, int expectedInput2) + internal void ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(string expectedInput1, int expectedInput2) { _primitiveInput1.ShouldBe(expectedInput1); _primitiveInput2.ShouldBe(expectedInput2); } - public void ThenEnumArgumentIsPassedInProperlyAndStoredOnTheSameObjectInstance(SomeEnumForTesting expectedInput) + internal void ThenEnumArgumentIsPassedInProperlyAndStoredOnTheSameObjectInstance(SomeEnumForTesting expectedInput) { _enumInput.ShouldBe(expectedInput); } - public void ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(IEnumerable expectedInput1, IEnumerable expectedInput2) + internal void ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(IEnumerable expectedInput1, IEnumerable expectedInput2) { _arrayInput1.ShouldBe(expectedInput1); _arrayInput2.ShouldBe(expectedInput2); diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs index 7c06cbfb..988d7966 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs @@ -130,7 +130,7 @@ string GetInput2(string someInput) return someInput + " Input 2"; } - ContainerType container = new ContainerType(); + ContainerType container = new(); [Fact] public void NoArguments() diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs index e566beea..cd637327 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs @@ -11,7 +11,7 @@ public class StepTitleTests [Fact] public void MethodCallInStepTitle() { - FooClass something = new FooClass(); + FooClass something = new(); var story = this .Given(_ => GivenWeMutateSomeState()) .When(_ => something.Sub.SomethingHappens()) diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs index 184c3bec..96901c6c 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs @@ -7,16 +7,10 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { public class WhenStepsReturnTheirText { - class TestClassWithStepsReturningTheirText + class TestClassWithStepsReturningTheirText(int input1, string input2) { - private readonly int _input1; - private readonly string _input2; - - public TestClassWithStepsReturningTheirText(int input1, string input2) - { - _input1 = input1; - _input2 = input2; - } + private readonly int _input1 = input1; + private readonly string _input2 = input2; IEnumerable Given() { diff --git a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj index 89600ae2..830248df 100644 --- a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj +++ b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj @@ -18,6 +18,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/TestStack.BDDfy.sln b/src/TestStack.BDDfy.sln index 5ab648ed..c4e3d65e 100644 --- a/src/TestStack.BDDfy.sln +++ b/src/TestStack.BDDfy.sln @@ -1,9 +1,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.0.11018.127 d18.0 +VisualStudioVersion = 18.0.11018.127 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8F515887-AAB5-4873-8BE9-5AB10685EBCB}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig ..\.gitattributes = ..\.gitattributes ..\.gitignore = ..\.gitignore ..\appveyor.deploy.yml = ..\appveyor.deploy.yml diff --git a/src/TestStack.BDDfy/Configuration/BatchProcessors.cs b/src/TestStack.BDDfy/Configuration/BatchProcessors.cs index e4550599..b90000cf 100644 --- a/src/TestStack.BDDfy/Configuration/BatchProcessors.cs +++ b/src/TestStack.BDDfy/Configuration/BatchProcessors.cs @@ -33,19 +33,19 @@ IEnumerable _GetProcessors() } } - private readonly BatchProcessorFactory _htmlReportFactory = new BatchProcessorFactory(() => new HtmlReporter(new DefaultHtmlReportConfiguration())); + private readonly BatchProcessorFactory _htmlReportFactory = new(() => new HtmlReporter(new DefaultHtmlReportConfiguration())); public BatchProcessorFactory HtmlReport { get { return _htmlReportFactory; } } - private readonly BatchProcessorFactory _htmlMetroReportFactory = new BatchProcessorFactory(() => new HtmlReporter(new DefaultHtmlReportConfiguration(), new MetroReportBuilder()), false); + private readonly BatchProcessorFactory _htmlMetroReportFactory = new(() => new HtmlReporter(new DefaultHtmlReportConfiguration(), new MetroReportBuilder()), false); public BatchProcessorFactory HtmlMetroReport { get { return _htmlMetroReportFactory; } } - private readonly BatchProcessorFactory _markDownFactory = new BatchProcessorFactory(() => new MarkDownReporter(), false); + private readonly BatchProcessorFactory _markDownFactory = new(() => new MarkDownReporter(), false); public BatchProcessorFactory MarkDownReport { get { return _markDownFactory; } } - private readonly BatchProcessorFactory _diagnosticsFactory = new BatchProcessorFactory(() => new DiagnosticsReporter(), false); + private readonly BatchProcessorFactory _diagnosticsFactory = new(() => new DiagnosticsReporter(), false); public BatchProcessorFactory DiagnosticsReport { get { return _diagnosticsFactory; } } - readonly List _addedProcessors = new List(); + readonly List _addedProcessors = new(); public BatchProcessors Add(IBatchProcessor processor) { diff --git a/src/TestStack.BDDfy/Configuration/Configurator.cs b/src/TestStack.BDDfy/Configuration/Configurator.cs index e647c492..42018936 100644 --- a/src/TestStack.BDDfy/Configuration/Configurator.cs +++ b/src/TestStack.BDDfy/Configuration/Configurator.cs @@ -9,19 +9,19 @@ static Configurator() public static bool AsyncVoidSupportEnabled { get; set; } - private static readonly Processors ProcessorsFactory = new Processors(); + private static readonly Processors ProcessorsFactory = new(); public static Processors Processors { get { return ProcessorsFactory; } } - private static readonly BatchProcessors BatchProcessorFactory = new BatchProcessors(); + private static readonly BatchProcessors BatchProcessorFactory = new(); public static BatchProcessors BatchProcessors { get { return BatchProcessorFactory; } } - private static readonly Scanners ScannersFactory = new Scanners(); + private static readonly Scanners ScannersFactory = new(); public static Scanners Scanners { get { return ScannersFactory; } diff --git a/src/TestStack.BDDfy/Configuration/Scanners.cs b/src/TestStack.BDDfy/Configuration/Scanners.cs index acf73f2a..ce1b5a2c 100644 --- a/src/TestStack.BDDfy/Configuration/Scanners.cs +++ b/src/TestStack.BDDfy/Configuration/Scanners.cs @@ -5,13 +5,13 @@ namespace TestStack.BDDfy.Configuration { public class Scanners { - private readonly StepScannerFactory _executableAttributeScanner = new StepScannerFactory(() => new ExecutableAttributeStepScanner()); + private readonly StepScannerFactory _executableAttributeScanner = new(() => new ExecutableAttributeStepScanner()); public StepScannerFactory ExecutableAttributeScanner { get { return _executableAttributeScanner; } } - private readonly StepScannerFactory _methodNameStepScanner = new StepScannerFactory(() => new DefaultMethodNameStepScanner()); + private readonly StepScannerFactory _methodNameStepScanner = new(() => new DefaultMethodNameStepScanner()); public StepScannerFactory DefaultMethodNameStepScanner { get { return _methodNameStepScanner; } } - private readonly List> _addedStepScanners = new List>(); + private readonly List> _addedStepScanners = new(); public Scanners Add(Func stepScannerFactory) { _addedStepScanners.Add(stepScannerFactory); diff --git a/src/TestStack.BDDfy/Engine.cs b/src/TestStack.BDDfy/Engine.cs index 3b115259..d29d4cf8 100644 --- a/src/TestStack.BDDfy/Engine.cs +++ b/src/TestStack.BDDfy/Engine.cs @@ -4,9 +4,9 @@ namespace TestStack.BDDfy { - public class Engine + public class Engine(IScanner scanner) { - private readonly IScanner _scanner; + private readonly IScanner _scanner = scanner; static Engine() { @@ -27,11 +27,6 @@ static void InvokeBatchProcessors() } } - public Engine(IScanner scanner) - { - _scanner = scanner; - } - public Story Run() { Story = _scanner.Scan(); diff --git a/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs b/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs index 0452c7eb..ecdbfe62 100644 --- a/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs +++ b/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs @@ -8,7 +8,7 @@ namespace TestStack.BDDfy /// internal class AsyncTestSyncContext : SynchronizationContext { - readonly ManualResetEvent _event = new ManualResetEvent(initialState: true); + readonly ManualResetEvent _event = new(initialState: true); Exception _exception; int _operationCount; diff --git a/src/TestStack.BDDfy/Processors/ExceptionProcessor.cs b/src/TestStack.BDDfy/Processors/ExceptionProcessor.cs index 04768278..1df3d22a 100644 --- a/src/TestStack.BDDfy/Processors/ExceptionProcessor.cs +++ b/src/TestStack.BDDfy/Processors/ExceptionProcessor.cs @@ -5,13 +5,13 @@ namespace TestStack.BDDfy.Processors { - public class ExceptionProcessor : IProcessor + public class ExceptionProcessor(Action assertInconclusive): IProcessor { - private readonly Action _assertInconclusive; + private readonly Action _assertInconclusive = assertInconclusive; private static readonly Action BestGuessInconclusiveAssertion; static readonly List ExcludedAssemblies = - new List(new[] { "System", "mscorlib", "TestStack.BDDfy", "TestDriven", "JetBrains.ReSharper" }); + new(new[] { "System", "mscorlib", "TestStack.BDDfy", "TestDriven", "JetBrains.ReSharper" }); static ExceptionProcessor() { @@ -66,11 +66,6 @@ public ExceptionProcessor() : this(BestGuessInconclusiveAssertion) { } - public ExceptionProcessor(Action assertInconclusive) - { - _assertInconclusive = assertInconclusive; - } - public ProcessType ProcessType { get { return ProcessType.ProcessExceptions; } diff --git a/src/TestStack.BDDfy/Processors/ScenarioExecutor.cs b/src/TestStack.BDDfy/Processors/ScenarioExecutor.cs index 5bd17acf..d69fb4f5 100644 --- a/src/TestStack.BDDfy/Processors/ScenarioExecutor.cs +++ b/src/TestStack.BDDfy/Processors/ScenarioExecutor.cs @@ -5,14 +5,9 @@ namespace TestStack.BDDfy.Processors { - public class ScenarioExecutor + public class ScenarioExecutor(Scenario scenario) { - private readonly Scenario _scenario; - - public ScenarioExecutor(Scenario scenario) - { - _scenario = scenario; - } + private readonly Scenario _scenario = scenario; public void InitializeScenario() { diff --git a/src/TestStack.BDDfy/Processors/UnusedExampleException.cs b/src/TestStack.BDDfy/Processors/UnusedExampleException.cs index 5ead5d0a..4661af29 100644 --- a/src/TestStack.BDDfy/Processors/UnusedExampleException.cs +++ b/src/TestStack.BDDfy/Processors/UnusedExampleException.cs @@ -7,12 +7,9 @@ namespace TestStack.BDDfy.Processors #else [System.Runtime.Serialization.Serializable] #endif - public class UnusedExampleException : Exception - { - public UnusedExampleException(ExampleValue unusedValue) : - base(string.Format("Example Column '{0}' is unused, all examples should be consumed by the test (have you misspelt a field or property?)\r\n\r\n" + public class UnusedExampleException(ExampleValue unusedValue): Exception(string.Format("Example Column '{0}' is unused, all examples should be consumed by the test (have you misspelt a field or property?)\r\n\r\n" + "If this is not the case, raise an issue at https://github.com/TestStack/TestStack.BDDfy/issues.", unusedValue.Header)) - { } + { #if NET40 protected UnusedExampleException( diff --git a/src/TestStack.BDDfy/Properties/Annotations.cs b/src/TestStack.BDDfy/Properties/Annotations.cs index d1cc1f32..027dcdcf 100644 --- a/src/TestStack.BDDfy/Properties/Annotations.cs +++ b/src/TestStack.BDDfy/Properties/Annotations.cs @@ -42,34 +42,29 @@ public sealed class CanBeNullAttribute : Attribute { } AttributeTargets.Field, AllowMultiple = false, Inherited = true)] public sealed class NotNullAttribute : Attribute { } - /// - /// Indicates that the marked method builds string by format pattern and (optional) arguments. - /// Parameter, which contains format string, should be given in constructor. The format string - /// should be in -like form - /// - /// - /// [StringFormatMethod("message")] - /// public void ShowError(string message, params object[] args) { /* do something */ } - /// public void Foo() { - /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string - /// } - /// - [AttributeUsage( - AttributeTargets.Constructor | AttributeTargets.Method, - AllowMultiple = false, Inherited = true)] - public sealed class StringFormatMethodAttribute : Attribute - { + /// + /// Indicates that the marked method builds string by format pattern and (optional) arguments. + /// Parameter, which contains format string, should be given in constructor. The format string + /// should be in -like form + /// + /// + /// [StringFormatMethod("message")] + /// public void ShowError(string message, params object[] args) { /* do something */ } + /// public void Foo() { + /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string + /// } + /// /// /// Specifies which parameter of an annotated method should be treated as format-string /// - public StringFormatMethodAttribute(string formatParameterName) - { - FormatParameterName = formatParameterName; + [AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Method, + AllowMultiple = false, Inherited = true)] + public sealed class StringFormatMethodAttribute(string formatParameterName): Attribute + { + public string FormatParameterName { get; private set; } = formatParameterName; } - public string FormatParameterName { get; private set; } - } - /// /// Indicates that the function argument should be string literal and match one /// of the parameters of the caller function. For example, ReSharper annotates @@ -175,21 +170,15 @@ public NotifyPropertyChangedInvocatorAttribute(string parameterName) /// /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] - public sealed class ContractAnnotationAttribute : Attribute + public sealed class ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates): Attribute { public ContractAnnotationAttribute([NotNull] string contract) : this(contract, false) { } - public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates) - { - Contract = contract; - ForceFullStates = forceFullStates; + public string Contract { get; private set; } = contract; + public bool ForceFullStates { get; private set; } = forceFullStates; } - public string Contract { get; private set; } - public bool ForceFullStates { get; private set; } - } - /// /// Indicates that marked element should be localized or not /// @@ -200,16 +189,12 @@ public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStat /// } /// [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] - public sealed class LocalizationRequiredAttribute : Attribute + public sealed class LocalizationRequiredAttribute(bool required): Attribute { public LocalizationRequiredAttribute() : this(true) { } - public LocalizationRequiredAttribute(bool required) - { - Required = required; - } - public bool Required { get; private set; } - } + public bool Required { get; private set; } = required; + } /// /// Indicates that the value of the marked type (or its derivatives) @@ -247,23 +232,19 @@ public sealed class CannotApplyEqualityOperatorAttribute : Attribute { } /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] [BaseTypeRequired(typeof(Attribute))] - public sealed class BaseTypeRequiredAttribute : Attribute + public sealed class BaseTypeRequiredAttribute([NotNull] Type baseType): Attribute { - public BaseTypeRequiredAttribute([NotNull] Type baseType) - { - BaseType = baseType; + [NotNull] public Type BaseType { get; private set; } = baseType; } - [NotNull] public Type BaseType { get; private set; } - } - /// /// Indicates that the marked symbol is used implicitly /// (e.g. via reflection, in external library), so this symbol /// will not be marked as unused (as well as by other usage inspections) /// [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)] - public sealed class UsedImplicitlyAttribute : Attribute + public sealed class UsedImplicitlyAttribute( + ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags): Attribute { public UsedImplicitlyAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } @@ -274,24 +255,18 @@ public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } - public UsedImplicitlyAttribute( - ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; + public ImplicitUseKindFlags UseKindFlags { get; private set; } = useKindFlags; + public ImplicitUseTargetFlags TargetFlags { get; private set; } = targetFlags; } - public ImplicitUseKindFlags UseKindFlags { get; private set; } - public ImplicitUseTargetFlags TargetFlags { get; private set; } - } - /// /// Should be used on attributes and causes ReSharper /// to not mark symbols marked with such attributes as unused /// (as well as by other usage inspections) /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] - public sealed class MeansImplicitUseAttribute : Attribute + public sealed class MeansImplicitUseAttribute( + ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags): Attribute { public MeansImplicitUseAttribute() : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { } @@ -302,16 +277,9 @@ public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags) public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags) : this(ImplicitUseKindFlags.Default, targetFlags) { } - public MeansImplicitUseAttribute( - ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) - { - UseKindFlags = useKindFlags; - TargetFlags = targetFlags; + [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; } = useKindFlags; + [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; } = targetFlags; } - - [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; } - [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; } - } [Flags] public enum ImplicitUseKindFlags @@ -403,51 +371,13 @@ public PathReferenceAttribute([PathReference] string basePath) [NotNull] public string BasePath { get; private set; } } - // ASP.NET MVC attributes - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute - { - public AspMvcAreaMasterLocationFormatAttribute(string format) { } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute - { - public AspMvcAreaPartialViewLocationFormatAttribute(string format) { } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute - { - public AspMvcAreaViewLocationFormatAttribute(string format) { } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class AspMvcMasterLocationFormatAttribute : Attribute - { - public AspMvcMasterLocationFormatAttribute(string format) { } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute - { - public AspMvcPartialViewLocationFormatAttribute(string format) { } - } - - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class AspMvcViewLocationFormatAttribute : Attribute - { - public AspMvcViewLocationFormatAttribute(string format) { } - } - - /// - /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter - /// is an MVC action. If applied to a method, the MVC action name is calculated - /// implicitly from the context. Use this attribute for custom wrappers similar to - /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String) - /// - [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] + /// + /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter + /// is an MVC action. If applied to a method, the MVC action name is calculated + /// implicitly from the context. Use this attribute for custom wrappers similar to + /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String) + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)] public sealed class AspMvcActionAttribute : Attribute { public AspMvcActionAttribute() { } @@ -592,16 +522,11 @@ public HtmlElementAttributesAttribute([NotNull] string name) [AttributeUsage( AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, Inherited = true)] - public sealed class HtmlAttributeValueAttribute : Attribute + public sealed class HtmlAttributeValueAttribute([NotNull] string name): Attribute { - public HtmlAttributeValueAttribute([NotNull] string name) - { - Name = name; + [NotNull] public string Name { get; private set; } = name; } - [NotNull] public string Name { get; private set; } - } - // Razor attributes /// diff --git a/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReportBuilder.cs b/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReportBuilder.cs index a1c0304c..765f34ad 100644 --- a/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReportBuilder.cs +++ b/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReportBuilder.cs @@ -4,17 +4,12 @@ namespace TestStack.BDDfy.Reporters.Diagnostics { - public class DiagnosticsReportBuilder : IReportBuilder + public class DiagnosticsReportBuilder(ISerializer serializer): IReportBuilder { - private readonly ISerializer _serializer; + private readonly ISerializer _serializer = serializer; public DiagnosticsReportBuilder() : this(new JsonSerializer()) { } - public DiagnosticsReportBuilder(ISerializer serializer) - { - _serializer = serializer; - } - public string CreateReport(FileReportModel model) { var graph = GetDiagnosticData(model); diff --git a/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReporter.cs b/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReporter.cs index dd2a79e9..1b4646b3 100644 --- a/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReporter.cs +++ b/src/TestStack.BDDfy/Reporters/Diagnostics/DiagnosticsReporter.cs @@ -4,19 +4,13 @@ namespace TestStack.BDDfy.Reporters.Diagnostics { - public class DiagnosticsReporter : IBatchProcessor + public class DiagnosticsReporter(IReportBuilder builder, IReportWriter writer): IBatchProcessor { - private readonly IReportBuilder _builder; - private readonly IReportWriter _writer; + private readonly IReportBuilder _builder = builder; + private readonly IReportWriter _writer = writer; public DiagnosticsReporter() : this(new DiagnosticsReportBuilder(), new FileWriter()) { } - public DiagnosticsReporter(IReportBuilder builder, IReportWriter writer) - { - _builder = builder; - _writer = writer; - } - public void Process(IEnumerable stories) { var viewModel = new FileReportModel(stories.ToReportModel()); diff --git a/src/TestStack.BDDfy/Reporters/FileReportModel.cs b/src/TestStack.BDDfy/Reporters/FileReportModel.cs index 151efed0..8b50e30c 100644 --- a/src/TestStack.BDDfy/Reporters/FileReportModel.cs +++ b/src/TestStack.BDDfy/Reporters/FileReportModel.cs @@ -4,18 +4,11 @@ namespace TestStack.BDDfy.Reporters { - public class FileReportModel + public class FileReportModel(ReportModel reportModel) { - public FileReportModel(ReportModel reportModel) - { - _stories = reportModel.Stories; - Summary = new FileReportSummaryModel(reportModel); - RunDate = DateTime.Now; - } - - readonly IEnumerable _stories; - public FileReportSummaryModel Summary { get; private set; } - public DateTime RunDate { get; set; } + readonly IEnumerable _stories = reportModel.Stories; + public FileReportSummaryModel Summary { get; private set; } = new FileReportSummaryModel(reportModel); + public DateTime RunDate { get; set; } = DateTime.Now; public IEnumerable Stories { diff --git a/src/TestStack.BDDfy/Reporters/Html/HtmlReportModel.cs b/src/TestStack.BDDfy/Reporters/Html/HtmlReportModel.cs index d62d8822..3efc1375 100644 --- a/src/TestStack.BDDfy/Reporters/Html/HtmlReportModel.cs +++ b/src/TestStack.BDDfy/Reporters/Html/HtmlReportModel.cs @@ -2,14 +2,8 @@ namespace TestStack.BDDfy.Reporters.Html { - public class HtmlReportModel : FileReportModel + public class HtmlReportModel(IHtmlReportConfiguration configuration, ReportModel reportModel): FileReportModel(reportModel) { - public HtmlReportModel(IHtmlReportConfiguration configuration, ReportModel reportModel) - : base(reportModel) - { - Configuration = configuration; - } - public HtmlReportModel(ReportModel reportModel) :this(new DefaultHtmlReportConfiguration(), reportModel) { @@ -18,6 +12,6 @@ public HtmlReportModel(ReportModel reportModel) public string CustomStylesheet { get; set; } public string CustomJavascript { get; set; } - public IHtmlReportConfiguration Configuration { get; private set; } + public IHtmlReportConfiguration Configuration { get; private set; } = configuration; } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Reporters/Html/HtmlReportResources.cs b/src/TestStack.BDDfy/Reporters/Html/HtmlReportResources.cs index 62efea43..fae85f62 100644 --- a/src/TestStack.BDDfy/Reporters/Html/HtmlReportResources.cs +++ b/src/TestStack.BDDfy/Reporters/Html/HtmlReportResources.cs @@ -24,11 +24,9 @@ static string Read(string resourceName) { var assembly = typeof(HtmlReportResources).Assembly(); - using (var stream = assembly.GetManifestResourceStream(resourceName)) - using (var reader = new StreamReader(stream)) - { - return reader.ReadToEnd(); - } + using var stream = assembly.GetManifestResourceStream(resourceName); + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Reporters/Html/HtmlReportTag.cs b/src/TestStack.BDDfy/Reporters/Html/HtmlReportTag.cs index 2a69d0ac..7db33295 100644 --- a/src/TestStack.BDDfy/Reporters/Html/HtmlReportTag.cs +++ b/src/TestStack.BDDfy/Reporters/Html/HtmlReportTag.cs @@ -2,16 +2,10 @@ namespace TestStack.BDDfy.Reporters.Html { - class HtmlReportTag : IDisposable + class HtmlReportTag(HtmlTag tag, Action closeTagAction): IDisposable { - private readonly HtmlTag _tagName; - private readonly Action _closeTagAction; - - public HtmlReportTag(HtmlTag tag, Action closeTagAction) - { - _tagName = tag; - _closeTagAction = closeTagAction; - } + private readonly HtmlTag _tagName = tag; + private readonly Action _closeTagAction = closeTagAction; public void Dispose() { diff --git a/src/TestStack.BDDfy/Reporters/Html/HtmlReporter.cs b/src/TestStack.BDDfy/Reporters/Html/HtmlReporter.cs index 7f11c95d..01202756 100644 --- a/src/TestStack.BDDfy/Reporters/Html/HtmlReporter.cs +++ b/src/TestStack.BDDfy/Reporters/Html/HtmlReporter.cs @@ -7,12 +7,16 @@ namespace TestStack.BDDfy.Reporters.Html { - public class HtmlReporter : IBatchProcessor + public class HtmlReporter( + IHtmlReportConfiguration configuration, + IReportBuilder reportBuilder, + IReportWriter writer, + IFileReader reader): IBatchProcessor { - public IReportBuilder ReportBuilder { get; set; } - private readonly IReportWriter _writer; - private readonly IFileReader _fileReader; - readonly IHtmlReportConfiguration _configuration; + public IReportBuilder ReportBuilder { get; set; } = reportBuilder; + private readonly IReportWriter _writer = writer; + private readonly IFileReader _fileReader = reader; + readonly IHtmlReportConfiguration _configuration = configuration; public HtmlReportModel Model { get; private set; } public HtmlReporter(IHtmlReportConfiguration configuration) @@ -30,18 +34,6 @@ public HtmlReporter(IHtmlReportConfiguration configuration, IReportBuilder htmlR { } - public HtmlReporter( - IHtmlReportConfiguration configuration, - IReportBuilder reportBuilder, - IReportWriter writer, - IFileReader reader) - { - _configuration = configuration; - ReportBuilder = reportBuilder; - _writer = writer; - _fileReader = reader; - } - public void Process(IEnumerable stories) { var allowedStories = stories.Where(s => _configuration.RunsOn(s)).ToList(); @@ -69,6 +61,7 @@ void WriteOutHtmlReport(ReportModel reportModel) private void LoadCustomScripts() { var customStylesheet = Path.Combine(_configuration.OutputPath, "BDDfyCustom.css"); + if (_fileReader.Exists(customStylesheet)) Model.CustomStylesheet = _fileReader.Read(customStylesheet); diff --git a/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReportBuilder.cs b/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReportBuilder.cs index 4d1105bc..e8433c5d 100644 --- a/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReportBuilder.cs +++ b/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReportBuilder.cs @@ -8,7 +8,7 @@ namespace TestStack.BDDfy.Reporters.MarkDown { public class MarkDownReportBuilder : IReportBuilder { - private readonly List _exceptions = new List(); + private readonly List _exceptions = new(); public string CreateReport(FileReportModel model) { diff --git a/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReporter.cs b/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReporter.cs index aaa31445..180ef22d 100644 --- a/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReporter.cs +++ b/src/TestStack.BDDfy/Reporters/MarkDown/MarkDownReporter.cs @@ -8,19 +8,13 @@ namespace TestStack.BDDfy.Reporters.MarkDown /// This is a custom reporter that shows you how easily you can create a custom report. /// Just implement IBatchProcessor and you are done /// - public class MarkDownReporter : IBatchProcessor + public class MarkDownReporter(IReportBuilder builder, IReportWriter writer): IBatchProcessor { - private readonly IReportBuilder _builder; - private readonly IReportWriter _writer; + private readonly IReportBuilder _builder = builder; + private readonly IReportWriter _writer = writer; public MarkDownReporter() : this(new MarkDownReportBuilder(), new FileWriter()) { } - public MarkDownReporter(IReportBuilder builder, IReportWriter writer) - { - _builder = builder; - _writer = writer; - } - public void Process(IEnumerable stories) { var viewModel = new FileReportModel(stories.ToReportModel()); diff --git a/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs b/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs index da7c30cc..2fa425f7 100644 --- a/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs +++ b/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs @@ -6,8 +6,8 @@ namespace TestStack.BDDfy.Reporters.Serializers public class JsonFormatter { StringWalker _walker; - IndentWriter _writer = new IndentWriter(); - StringBuilder _currentLine = new StringBuilder(); + IndentWriter _writer = new(); + StringBuilder _currentLine = new(); bool _quoted; public JsonFormatter(string json) @@ -102,7 +102,7 @@ private void WriteCurrentLine() public class IndentWriter { - StringBuilder _sb = new StringBuilder(); + StringBuilder _sb = new(); int _indent; public void Indent() @@ -123,7 +123,7 @@ public void WriteLine(string line) private string CreateIndent() { - StringBuilder indentString = new StringBuilder(); + StringBuilder indentString = new(); for (int i = 0; i < _indent; i++) indentString.Append(" "); return indentString.ToString(); @@ -135,16 +135,10 @@ public override string ToString() } } - public class StringWalker + public class StringWalker(string s) { - string _s; - public int Index { get; set; } - - public StringWalker(string s) - { - _s = s; - Index = -1; - } + string _s = s; + public int Index { get; set; } = -1; public bool MoveNext() { diff --git a/src/TestStack.BDDfy/Reporters/TextReporter.cs b/src/TestStack.BDDfy/Reporters/TextReporter.cs index 3a7781f1..0650b57a 100644 --- a/src/TestStack.BDDfy/Reporters/TextReporter.cs +++ b/src/TestStack.BDDfy/Reporters/TextReporter.cs @@ -8,8 +8,8 @@ namespace TestStack.BDDfy.Reporters { public class TextReporter : IProcessor { - private readonly List _exceptions = new List(); - private readonly StringBuilder _text = new StringBuilder(); + private readonly List _exceptions = new(); + private readonly StringBuilder _text = new(); private int _longestStepSentence; public void Process(Story story) diff --git a/src/TestStack.BDDfy/Scanners/DefaultScanner.cs b/src/TestStack.BDDfy/Scanners/DefaultScanner.cs index 43f5c735..ec039963 100644 --- a/src/TestStack.BDDfy/Scanners/DefaultScanner.cs +++ b/src/TestStack.BDDfy/Scanners/DefaultScanner.cs @@ -4,18 +4,11 @@ namespace TestStack.BDDfy { - public class DefaultScanner : IScanner + public class DefaultScanner(ITestContext testContext, IScenarioScanner scenarioScanner, Type explicitStoryType = null): IScanner { - private readonly ITestContext _testContext; - private readonly Type _explicitStoryType; - private readonly IScenarioScanner _scenarioScanner; - - public DefaultScanner(ITestContext testContext, IScenarioScanner scenarioScanner, Type explicitStoryType = null) - { - _testContext = testContext; - _explicitStoryType = explicitStoryType; - _scenarioScanner = scenarioScanner; - } + private readonly ITestContext _testContext = testContext; + private readonly Type _explicitStoryType = explicitStoryType; + private readonly IScenarioScanner _scenarioScanner = scenarioScanner; public Story Scan() { diff --git a/src/TestStack.BDDfy/Scanners/ScenarioScanners/FluentScenarioScanner.cs b/src/TestStack.BDDfy/Scanners/ScenarioScanners/FluentScenarioScanner.cs index ddfe44a1..0d1021b2 100644 --- a/src/TestStack.BDDfy/Scanners/ScenarioScanners/FluentScenarioScanner.cs +++ b/src/TestStack.BDDfy/Scanners/ScenarioScanners/FluentScenarioScanner.cs @@ -4,16 +4,10 @@ namespace TestStack.BDDfy { - public class FluentScenarioScanner : IScenarioScanner + public class FluentScenarioScanner(List steps, string title): IScenarioScanner { - private readonly string _title; - private readonly List _steps; - - public FluentScenarioScanner(List steps, string title) - { - _title = title; - _steps = steps; - } + private readonly string _title = title; + private readonly List _steps = steps; public IEnumerable Scan(ITestContext testContext) { diff --git a/src/TestStack.BDDfy/Scanners/ScenarioScanners/ReflectiveScenarioScanner.cs b/src/TestStack.BDDfy/Scanners/ScenarioScanners/ReflectiveScenarioScanner.cs index 22e86d8b..ef419166 100644 --- a/src/TestStack.BDDfy/Scanners/ScenarioScanners/ReflectiveScenarioScanner.cs +++ b/src/TestStack.BDDfy/Scanners/ScenarioScanners/ReflectiveScenarioScanner.cs @@ -6,22 +6,16 @@ namespace TestStack.BDDfy { - public class ReflectiveScenarioScanner : IScenarioScanner + public class ReflectiveScenarioScanner(string scenarioTitle, params IStepScanner[] stepScanners): IScenarioScanner { - private readonly IEnumerable _stepScanners; - private readonly string _scenarioTitle; + private readonly IEnumerable _stepScanners = stepScanners; + private readonly string _scenarioTitle = scenarioTitle; public ReflectiveScenarioScanner(params IStepScanner[] stepScanners) : this(null, stepScanners) { } - public ReflectiveScenarioScanner(string scenarioTitle, params IStepScanner[] stepScanners) - { - _stepScanners = stepScanners; - _scenarioTitle = scenarioTitle; - } - public virtual IEnumerable Scan(ITestContext testContext) { Type scenarioType; diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs index a24665c6..b5241d54 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs @@ -4,14 +4,9 @@ namespace TestStack.BDDfy { - public class Example + public class Example(params ExampleValue[] items) { - private readonly ExampleValue[] _items; - - public Example(params ExampleValue[] items) - { - _items = items; - } + private readonly ExampleValue[] _items = items; public string[] Headers { get { return Values.Select(i => i.Header).ToArray(); } } diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleAction.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleAction.cs index 6e7d8813..88d58889 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleAction.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleAction.cs @@ -5,17 +5,11 @@ namespace TestStack.BDDfy /// /// Allows examples to contain actions which can be performed /// - public class ExampleAction + public class ExampleAction(string stepTitle, Action action) { - private readonly string _stepTitle; + private readonly string _stepTitle = stepTitle; - public ExampleAction(string stepTitle, Action action) - { - Action = action; - _stepTitle = stepTitle; - } - - public Action Action { get; private set; } + public Action Action { get; private set; } = action; public override string ToString() { diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs index 52820db4..2345b493 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs @@ -6,16 +6,11 @@ namespace TestStack.BDDfy { - public class ExampleTable : ICollection + public class ExampleTable(params string[] headers): ICollection { - private readonly List _rows = new List(); + private readonly List _rows = new(); - public ExampleTable(params string[] headers) - { - Headers = headers; - } - - public string[] Headers { get; private set; } + public string[] Headers { get; private set; } = headers; public int Count { get { return _rows.Count; } } diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs index a0d581c0..b4eb2fee 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs @@ -2,19 +2,12 @@ namespace TestStack.BDDfy { - public class ExampleValue + public class ExampleValue(string header, object underlyingValue, Func getRowIndex) { - private readonly object _underlyingValue; - private readonly Func _getRowIndex; + private readonly object _underlyingValue = underlyingValue; + private readonly Func _getRowIndex = getRowIndex; - public ExampleValue(string header, object underlyingValue, Func getRowIndex) - { - Header = header; - _underlyingValue = underlyingValue; - _getRowIndex = getRowIndex; - } - - public string Header { get; private set; } + public string Header { get; private set; } = header; public bool MatchesName(string name) { diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/UnassignableExampleException.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/UnassignableExampleException.cs index 21901bda..e1909791 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/UnassignableExampleException.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/UnassignableExampleException.cs @@ -7,12 +7,8 @@ namespace TestStack.BDDfy #else [System.Runtime.Serialization.Serializable] #endif - public class UnassignableExampleException : Exception + public class UnassignableExampleException(string message, Exception inner, ExampleValue exampleValue): Exception(message, inner) { - public UnassignableExampleException(string message, Exception inner, ExampleValue exampleValue) : base(message, inner) - { - ExampleValue = exampleValue; - } #if NET40 protected UnassignableExampleException( @@ -22,6 +18,6 @@ protected UnassignableExampleException( } #endif - public ExampleValue ExampleValue { get; private set; } + public ExampleValue ExampleValue { get; private set; } = exampleValue; } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/ExecutableAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/ExecutableAttribute.cs index 5393e0b5..d7e03dc0 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/ExecutableAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/ExecutableAttribute.cs @@ -3,19 +3,12 @@ namespace TestStack.BDDfy { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - public class ExecutableAttribute : Attribute + public class ExecutableAttribute(ExecutionOrder order, string stepTitle): Attribute { - public ExecutableAttribute(ExecutionOrder order, string stepTitle) - { - ExecutionOrder = order; - StepTitle = stepTitle; - ShouldReport = true; - } - - public ExecutionOrder ExecutionOrder { get; private set; } + public ExecutionOrder ExecutionOrder { get; private set; } = order; public bool Asserts { get; set; } - public string StepTitle { get; set; } + public string StepTitle { get; set; } = stepTitle; public int Order { get; set; } - public bool ShouldReport { get; set; } + public bool ShouldReport { get; set; } = true; } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndGivenAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndGivenAttribute.cs index a1f034d1..d0dac77a 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndGivenAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndGivenAttribute.cs @@ -1,8 +1,7 @@ namespace TestStack.BDDfy { - public class AndGivenAttribute : ExecutableAttribute + public class AndGivenAttribute(string stepTitle): ExecutableAttribute(ExecutionOrder.ConsecutiveSetupState, stepTitle) { public AndGivenAttribute() : this(null) { } - public AndGivenAttribute(string stepTitle) : base(ExecutionOrder.ConsecutiveSetupState, stepTitle) { } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndWhenAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndWhenAttribute.cs index 9956eada..bccd0abd 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndWhenAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/AndWhenAttribute.cs @@ -1,8 +1,7 @@ namespace TestStack.BDDfy { - public class AndWhenAttribute : ExecutableAttribute + public class AndWhenAttribute(string stepTitle): ExecutableAttribute(ExecutionOrder.ConsecutiveTransition, stepTitle) { public AndWhenAttribute() : this(null) { } - public AndWhenAttribute(string stepTitle) : base(ExecutionOrder.ConsecutiveTransition, stepTitle) { } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButGivenAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButGivenAttribute.cs index 5627944e..e0c82121 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButGivenAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButGivenAttribute.cs @@ -1,12 +1,7 @@ namespace TestStack.BDDfy { - public class ButGivenAttribute : ExecutableAttribute + public class ButGivenAttribute(string stepTitle): ExecutableAttribute(ExecutionOrder.ConsecutiveSetupState, stepTitle) { public ButGivenAttribute() : this(null) { } - - public ButGivenAttribute(string stepTitle) - : base(ExecutionOrder.ConsecutiveSetupState, stepTitle) - { - } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButWhenAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButWhenAttribute.cs index 3b5a1861..37d3cd3e 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButWhenAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/ButWhenAttribute.cs @@ -1,12 +1,7 @@ namespace TestStack.BDDfy { - public class ButWhenAttribute : ExecutableAttribute + public class ButWhenAttribute(string stepTitle): ExecutableAttribute(ExecutionOrder.ConsecutiveTransition, stepTitle) { public ButWhenAttribute() : this(null) { } - - public ButWhenAttribute(string stepTitle) - : base(ExecutionOrder.ConsecutiveTransition, stepTitle) - { - } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/GivenAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/GivenAttribute.cs index 4fe2cb04..b8742e6e 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/GivenAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/GivenAttribute.cs @@ -1,8 +1,7 @@ namespace TestStack.BDDfy { - public class GivenAttribute : ExecutableAttribute + public class GivenAttribute(string stepTitle): ExecutableAttribute(ExecutionOrder.SetupState, stepTitle) { public GivenAttribute() : this(null) { } - public GivenAttribute(string stepTitle) : base(ExecutionOrder.SetupState, stepTitle) { } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/WhenAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/WhenAttribute.cs index 36ba9de9..6d173cbd 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/WhenAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/ExecutableAttribute/GwtAttributes/WhenAttribute.cs @@ -1,8 +1,7 @@ namespace TestStack.BDDfy { - public class WhenAttribute : ExecutableAttribute + public class WhenAttribute(string stepTitle): ExecutableAttribute(ExecutionOrder.Transition, stepTitle) { public WhenAttribute() : this(null) { } - public WhenAttribute(string stepTitle) : base(ExecutionOrder.Transition, stepTitle) { } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentScanner.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentScanner.cs index 92e5f393..a97b35a4 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentScanner.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentScanner.cs @@ -39,7 +39,7 @@ namespace TestStack.BDDfy internal class FluentScanner : IFluentScanner where TScenario : class { - private readonly List _steps = new List(); + private readonly List _steps = new(); private readonly TScenario _testObject; private readonly ITestContext _testContext; private readonly MethodInfo _fakeExecuteActionMethod; diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameMatcher.cs b/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameMatcher.cs index 55aecdcb..ba7d0a9b 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameMatcher.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameMatcher.cs @@ -2,7 +2,7 @@ namespace TestStack.BDDfy { - public class MethodNameMatcher + public class MethodNameMatcher(Predicate isMethodOfInterest, ExecutionOrder executionOrder) { public MethodNameMatcher(Predicate isMethodOfInterest, bool asserts, ExecutionOrder executionOrder, bool shouldReport) : this(isMethodOfInterest, executionOrder) @@ -11,17 +11,9 @@ public MethodNameMatcher(Predicate isMethodOfInterest, bool asserts, Exe ShouldReport = shouldReport; } - public MethodNameMatcher(Predicate isMethodOfInterest, ExecutionOrder executionOrder) - { - IsMethodOfInterest = isMethodOfInterest; - ExecutionOrder = executionOrder; - Asserts = false; - ShouldReport = true; - } - - public Predicate IsMethodOfInterest { get; private set; } - public bool Asserts { get; set; } - public bool ShouldReport { get; set; } - public ExecutionOrder ExecutionOrder { get; private set; } + public Predicate IsMethodOfInterest { get; private set; } = isMethodOfInterest; + public bool Asserts { get; set; } = false; + public bool ShouldReport { get; set; } = true; + public ExecutionOrder ExecutionOrder { get; private set; } = executionOrder; } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/RunStepWithArgsAttribute.cs b/src/TestStack.BDDfy/Scanners/StepScanners/RunStepWithArgsAttribute.cs index 2367f20f..776c6587 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/RunStepWithArgsAttribute.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/RunStepWithArgsAttribute.cs @@ -3,14 +3,9 @@ namespace TestStack.BDDfy { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - public class RunStepWithArgsAttribute : Attribute + public class RunStepWithArgsAttribute(params object[] inputArguments): Attribute { - private readonly object[] _inputArguments; - - public RunStepWithArgsAttribute(params object[] inputArguments) - { - _inputArguments = inputArguments; - } + private readonly object[] _inputArguments = inputArguments; public string StepTextTemplate { get; set; } diff --git a/src/TestStack.BDDfy/Scanners/StoryMetadata.cs b/src/TestStack.BDDfy/Scanners/StoryMetadata.cs index feb60b31..cd8ac3df 100644 --- a/src/TestStack.BDDfy/Scanners/StoryMetadata.cs +++ b/src/TestStack.BDDfy/Scanners/StoryMetadata.cs @@ -3,34 +3,20 @@ namespace TestStack.BDDfy { - public class StoryMetadata + public class StoryMetadata(Type storyType, string narrative1, string narrative2, string narrative3, string title = null, string titlePrefix = null, string imageUri = null, string storyUri = null) { public StoryMetadata(Type storyType, StoryNarrativeAttribute narrative) : this(storyType, narrative.Narrative1, narrative.Narrative2, narrative.Narrative3, narrative.Title, narrative.TitlePrefix, narrative.ImageUri, narrative.StoryUri) { } - public StoryMetadata(Type storyType, string narrative1, string narrative2, string narrative3, string title = null, string titlePrefix = null, string imageUri = null, string storyUri = null) - { - Title = title ?? Configurator.Scanners.Humanize(storyType.Name); - TitlePrefix = titlePrefix ?? "Story: "; - Type = storyType; - - Narrative1 = narrative1; - Narrative2 = narrative2; - Narrative3 = narrative3; - - ImageUri = imageUri; - StoryUri = storyUri; - } - - public Type Type { get; private set; } - public string Title { get; private set; } - public string TitlePrefix { get; private set; } - public string Narrative1 { get; private set; } - public string Narrative2 { get; private set; } - public string Narrative3 { get; private set; } - public string ImageUri { get; private set; } - public string StoryUri { get; private set; } + public Type Type { get; private set; } = storyType; + public string Title { get; private set; } = title ?? Configurator.Scanners.Humanize(storyType.Name); + public string TitlePrefix { get; private set; } = titlePrefix ?? "Story: "; + public string Narrative1 { get; private set; } = narrative1; + public string Narrative2 { get; private set; } = narrative2; + public string Narrative3 { get; private set; } = narrative3; + public string ImageUri { get; private set; } = imageUri; + public string StoryUri { get; private set; } = storyUri; } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/TestContext.cs b/src/TestStack.BDDfy/TestContext.cs index 296ddda5..35a4613a 100644 --- a/src/TestStack.BDDfy/TestContext.cs +++ b/src/TestStack.BDDfy/TestContext.cs @@ -4,8 +4,8 @@ namespace TestStack.BDDfy { public class TestContext : ITestContext { - private static readonly Dictionary ContextLookup = new Dictionary(); - private static object _dictionaryLock = new object(); + private static readonly Dictionary ContextLookup = new(); + private static object _dictionaryLock = new(); private TestContext(object testObject) { diff --git a/src/testEnvironments.json b/src/testEnvironments.json new file mode 100644 index 00000000..87d98e00 --- /dev/null +++ b/src/testEnvironments.json @@ -0,0 +1,10 @@ +{ + "version": "1", + "environments": [ + { + "name": "WSL Ubuntu", + "type": "wsl", + "wslDistribution": "Ubuntu" + } + ] +} \ No newline at end of file From 95edb2fba2a654dfbba8d742abd8115110846ac8 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 13:37:23 +0100 Subject: [PATCH 08/14] add nuget publish task keep dotnet version as 8.x --- .github/workflows/build.yml | 60 +++++++++++++++++-- .../TestStack.BDDfy.Samples.csproj | 1 - .../TestStack.BDDfy.Tests.csproj | 2 - src/TestStack.BDDfy.sln | 1 + src/TestStack.BDDfy/TestStack.BDDfy.csproj | 2 - 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e318fa5..3744c47e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,7 @@ name: Build and Test on: push: pull_request: + workflow_dispatch: jobs: build: @@ -10,6 +11,26 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v5 + with: + fetch-depth: 0 # Required for GitVersion + + - name: Install GitVersion + uses: gittools/actions/gitversion/setup@v4.1.0 + with: + versionSpec: '6.x' + + - name: Determine Version + uses: gittools/actions/gitversion/execute@v4.1.0 + id: gitversion + with: + useConfigFile: true + + - name: Display GitVersion outputs + run: | + echo "Version: ${{ steps.gitversion.outputs.semVer }}" + echo "AssemblyVersion: ${{ steps.gitversion.outputs.assemblySemVer }}" + echo "FileVersion: ${{ steps.gitversion.outputs.assemblySemFileVer }}" + echo "NuGet Version: ${{ steps.gitversion.outputs.nuGetVersionV2 }}" - name: Setup .NET uses: actions/setup-dotnet@v5 @@ -18,7 +39,7 @@ jobs: - name: Build project working-directory: src - run: dotnet build --configuration Release + run: dotnet build --configuration Release /p:Version=${{ steps.gitversion.outputs.assemblySemVer }} /p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemVer }} /p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:PackageVersion=${{ steps.gitversion.outputs.nuGetVersionV2 }} - name: Run tests with coverage working-directory: src @@ -31,14 +52,41 @@ jobs: targetdir: 'coverage-report' reporttypes: 'Html;Cobertura' - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + - name: Create NuGet package + working-directory: src + run: dotnet pack --configuration Release --no-build /p:PackageVersion=${{ steps.gitversion.outputs.nuGetVersionV2 }} --output ../packages + + - name: Upload NuGet package as artifact + uses: actions/upload-artifact@v4 with: - files: ./coverage/**/coverage.cobertura.xml - fail_ci_if_error: false + name: nuget-package + path: packages/*.nupkg - name: Publish coverage report as artifact uses: actions/upload-artifact@v4 with: name: coverage-report - path: coverage-report/ \ No newline at end of file + path: coverage-report/ + + publish-nuget: + runs-on: ubuntu-latest + needs: build + if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch + environment: + name: Publish + url: https://www.nuget.org/packages/TestStack.BDDfy/ + + steps: + - name: Download NuGet package + uses: actions/download-artifact@v5 + with: + name: nuget-package + path: packages + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '8.0.x' + + - name: Publish to NuGet + run: dotnet nuget push packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate \ No newline at end of file diff --git a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj index 5709e62e..5eb13b87 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj +++ b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj @@ -1,7 +1,6 @@  - net8.0 TestStack.BDDfy.Samples TestStack.BDDfy.Samples true diff --git a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj index 830248df..b5f2de92 100644 --- a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj +++ b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj @@ -1,7 +1,5 @@  - - net8.0 TestStack.BDDfy.Tests TestStack.BDDfy.Tests true diff --git a/src/TestStack.BDDfy.sln b/src/TestStack.BDDfy.sln index c4e3d65e..6a88d54c 100644 --- a/src/TestStack.BDDfy.sln +++ b/src/TestStack.BDDfy.sln @@ -13,6 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\build.ps1 = ..\build.ps1 ..\deploy.cake = ..\deploy.cake ..\deploy.ps1 = ..\deploy.ps1 + ..\Directory.build.props = ..\Directory.build.props ..\GitVersion.yml = ..\GitVersion.yml ..\license.txt = ..\license.txt ..\logo.png = ..\logo.png diff --git a/src/TestStack.BDDfy/TestStack.BDDfy.csproj b/src/TestStack.BDDfy/TestStack.BDDfy.csproj index 90af7d26..f36fce72 100644 --- a/src/TestStack.BDDfy/TestStack.BDDfy.csproj +++ b/src/TestStack.BDDfy/TestStack.BDDfy.csproj @@ -1,7 +1,5 @@  - - net8.0 TestStack.BDDfy TestStack.BDDfy false From 1d424345080178ff2d53d2c8e747fa6f033e7c68 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 13:40:24 +0100 Subject: [PATCH 09/14] add missing build props file --- Directory.build.props | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Directory.build.props diff --git a/Directory.build.props b/Directory.build.props new file mode 100644 index 00000000..19bc63e5 --- /dev/null +++ b/Directory.build.props @@ -0,0 +1,5 @@ + + + net8.0 + + \ No newline at end of file From e73a5b4fcb416ede726b11015d6dbec7bd91d84c Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 13:48:57 +0100 Subject: [PATCH 10/14] move build props to src folder to fix build --- GitVersion.yml | 2 +- Directory.build.props => src/Directory.build.props | 0 src/TestStack.BDDfy.sln | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename Directory.build.props => src/Directory.build.props (100%) diff --git a/GitVersion.yml b/GitVersion.yml index 79ece618..246c3435 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,5 +1,5 @@ mode: ContinuousDelivery -next-version: 4.1.0 +next-version: 8.0.0 branches: {} ignore: sha: [] diff --git a/Directory.build.props b/src/Directory.build.props similarity index 100% rename from Directory.build.props rename to src/Directory.build.props diff --git a/src/TestStack.BDDfy.sln b/src/TestStack.BDDfy.sln index 6a88d54c..ddf3f47b 100644 --- a/src/TestStack.BDDfy.sln +++ b/src/TestStack.BDDfy.sln @@ -13,7 +13,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\build.ps1 = ..\build.ps1 ..\deploy.cake = ..\deploy.cake ..\deploy.ps1 = ..\deploy.ps1 - ..\Directory.build.props = ..\Directory.build.props + Directory.build.props = Directory.build.props ..\GitVersion.yml = ..\GitVersion.yml ..\license.txt = ..\license.txt ..\logo.png = ..\logo.png From 0ebe2c05ddc2e1dd20ffdff994a1ae69416c9d0b Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 13:59:43 +0100 Subject: [PATCH 11/14] test build with explicit target framework --- .github/workflows/build.yml | 4 ++-- .../TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj | 1 + src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj | 1 + src/TestStack.BDDfy/TestStack.BDDfy.csproj | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3744c47e..15cc3427 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: - name: Build project working-directory: src - run: dotnet build --configuration Release /p:Version=${{ steps.gitversion.outputs.assemblySemVer }} /p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemVer }} /p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:PackageVersion=${{ steps.gitversion.outputs.nuGetVersionV2 }} + run: dotnet build --configuration Release /p:Version=${{ steps.gitversion.outputs.assemblySemVer }} /p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemVer }} /p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }} /p:PackageVersion=${{ steps.gitversion.outputs.fullSemVer }} - name: Run tests with coverage working-directory: src @@ -54,7 +54,7 @@ jobs: - name: Create NuGet package working-directory: src - run: dotnet pack --configuration Release --no-build /p:PackageVersion=${{ steps.gitversion.outputs.nuGetVersionV2 }} --output ../packages + run: dotnet pack --configuration Release --no-build /p:PackageVersion=${{ steps.gitversion.outputs.fullSemVer }} --output ../packages - name: Upload NuGet package as artifact uses: actions/upload-artifact@v4 diff --git a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj index 5eb13b87..8a150d91 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj +++ b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj @@ -1,6 +1,7 @@  + net8.0 TestStack.BDDfy.Samples TestStack.BDDfy.Samples true diff --git a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj index b5f2de92..e8cb18b0 100644 --- a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj +++ b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj @@ -1,5 +1,6 @@  + net8.0 TestStack.BDDfy.Tests TestStack.BDDfy.Tests true diff --git a/src/TestStack.BDDfy/TestStack.BDDfy.csproj b/src/TestStack.BDDfy/TestStack.BDDfy.csproj index f36fce72..2ffbe71c 100644 --- a/src/TestStack.BDDfy/TestStack.BDDfy.csproj +++ b/src/TestStack.BDDfy/TestStack.BDDfy.csproj @@ -1,5 +1,6 @@  + net8.0 TestStack.BDDfy TestStack.BDDfy false From c10fde3306cc86edad16c123ac9dbbd331e34531 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 14:10:40 +0100 Subject: [PATCH 12/14] add text summary for coverage results to the build log --- .github/workflows/build.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15cc3427..ca3a967b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,8 +22,6 @@ jobs: - name: Determine Version uses: gittools/actions/gitversion/execute@v4.1.0 id: gitversion - with: - useConfigFile: true - name: Display GitVersion outputs run: | @@ -50,7 +48,21 @@ jobs: with: reports: 'coverage/**/coverage.cobertura.xml' targetdir: 'coverage-report' - reporttypes: 'Html;Cobertura' + reporttypes: 'Html;Cobertura;TextSummary' + + - name: Display Code Coverage Summary + run: | + echo "## 📊 Code Coverage Summary" >> $GITHUB_STEP_SUMMARY + if [ -f "coverage-report/Summary.txt" ]; then + echo '```' >> $GITHUB_STEP_SUMMARY + cat coverage-report/Summary.txt >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "### Build Log Coverage Summary:" + cat coverage-report/Summary.txt + else + echo "⚠️ Coverage summary file not found" + echo "⚠️ Coverage summary file not found" >> $GITHUB_STEP_SUMMARY + fi - name: Create NuGet package working-directory: src From b6f84205837bd91a88a44b5f03b893967447bb73 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 14:39:42 +0100 Subject: [PATCH 13/14] add steps to generate release notes --- .github/workflows/build.yml | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca3a967b..47f4c0fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -64,6 +64,52 @@ jobs: echo "⚠️ Coverage summary file not found" >> $GITHUB_STEP_SUMMARY fi + - name: Generate Rich Release Notes + id: release_notes + uses: mikepenz/release-changelog-builder-action@v5.4.1 + with: + configuration: | + { + "template": "## 🚀 Release ${{ steps.gitversion.outputs.semVer }}\n\n### 📅 Release Information\n- **Version**: ${{ steps.gitversion.outputs.semVer }}\n- **NuGet Version**: ${{ steps.gitversion.outputs.fullSemVer }}\n- **Build Date**: $(date -u +'%Y-%m-%d %H:%M:%S UTC')\n- **Commit**: ${{ github.sha }}\n\n#{{CHANGELOG}}\n\n### 📊 Statistics\n- **Total Changes**: #{{UNCATEGORIZED_COUNT}} commits\n- **Contributors**: #{{CONTRIBUTORS}}\n\n---\n*Generated automatically by GitHub Actions*", + "categories": [ + { + "title": "## 🚀 Features", + "labels": ["feature", "enhancement", "feat"] + }, + { + "title": "## 🐛 Bug Fixes", + "labels": ["bug", "fix", "bugfix"] + }, + { + "title": "## 📚 Documentation", + "labels": ["documentation", "docs"] + }, + { + "title": "## 🔧 Maintenance", + "labels": ["maintenance", "chore", "refactor"] + }, + { + "title": "## ⚠️ Breaking Changes", + "labels": ["breaking", "breaking-change"] + } + ], + "pr_template": "- #{{TITLE}} (#{{NUMBER}}) by @#{{AUTHOR}}", + "empty_template": "- #{{TITLE}} (#{{HASH}}) by @#{{AUTHOR}}", + "max_pull_requests": 200, + "max_back_track_time_days": 365 + } + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Save Release Notes to File + run: echo "${{ steps.release_notes.outputs.changelog }}" > release-notes.md + + - name: Upload Release Notes as artifact + uses: actions/upload-artifact@v4 + with: + name: release-notes + path: release-notes.md + - name: Create NuGet package working-directory: src run: dotnet pack --configuration Release --no-build /p:PackageVersion=${{ steps.gitversion.outputs.fullSemVer }} --output ../packages From ec85fb6ea2044822cfb4b5e24181f30b0ff19122 Mon Sep 17 00:00:00 2001 From: asos-gurpreetsingh Date: Mon, 6 Oct 2025 14:50:44 +0100 Subject: [PATCH 14/14] added tag and release steps --- .github/workflows/build.yml | 63 +++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 47f4c0fe..440746e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,6 +7,10 @@ on: jobs: build: runs-on: ubuntu-latest + outputs: + semver: ${{ steps.gitversion.outputs.semVer }} + fullsemver: ${{ steps.gitversion.outputs.fullSemVer }} + nugetversion: ${{ steps.gitversion.outputs.fullSemVer }} steps: - name: Checkout code @@ -28,7 +32,7 @@ jobs: echo "Version: ${{ steps.gitversion.outputs.semVer }}" echo "AssemblyVersion: ${{ steps.gitversion.outputs.assemblySemVer }}" echo "FileVersion: ${{ steps.gitversion.outputs.assemblySemFileVer }}" - echo "NuGet Version: ${{ steps.gitversion.outputs.nuGetVersionV2 }}" + echo "NuGet Version: ${{ steps.gitversion.outputs.fullSemVer }}" - name: Setup .NET uses: actions/setup-dotnet@v5 @@ -147,4 +151,59 @@ jobs: dotnet-version: '8.0.x' - name: Publish to NuGet - run: dotnet nuget push packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate \ No newline at end of file + run: dotnet nuget push packages/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate + + create-release-tag: + runs-on: ubuntu-latest + needs: [build, publish-nuget] + if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Check if tag already exists + id: check_tag + run: | + TAG="v${{ needs.build.outputs.semver }}" + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "Tag $TAG already exists" + echo "tag_exists=true" >> $GITHUB_OUTPUT + else + echo "Creating new tag: $TAG" + echo "tag_exists=false" >> $GITHUB_OUTPUT + echo "new_tag=$TAG" >> $GITHUB_OUTPUT + fi + + - name: Download Release Notes + if: steps.check_tag.outputs.tag_exists == 'false' + uses: actions/download-artifact@v5 + with: + name: release-notes + path: . + + - name: Create Git Tag and GitHub Release + if: steps.check_tag.outputs.tag_exists == 'false' + run: | + TAG="${{ steps.check_tag.outputs.new_tag }}" + + # Configure git + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Create and push tag + git tag -a "$TAG" -m "Release $TAG" + git push origin "$TAG" + + # Create GitHub release + gh release create "$TAG" \ + --title "Release $TAG" \ + --notes-file release-notes.md \ + --generate-notes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file