diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 114151ab..abe596bf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -146,7 +146,7 @@ jobs: run: echo "${{ steps.release_notes.outputs.changelog }}" > release-notes.md - name: Upload Release Notes as artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: release-notes path: release-notes.md @@ -185,6 +185,7 @@ jobs: - name: Create Bddfy package working-directory: src + if: steps.changes.outputs.BddfyUpdated == 'true' || github.event_name == 'release' run: >- dotnet pack ./TestStack.BDDfy/*.csproj @@ -194,13 +195,13 @@ jobs: --output ../packages - name: Upload NuGet package as artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: nuget-package path: packages/*.nupkg - name: Publish coverage report as artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: coverage-report path: coverage-report/ diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHasInsufficientFund.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHasInsufficientFund.cs index ae90dcb9..2517432a 100644 --- a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHasInsufficientFund.cs +++ b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHasInsufficientFund.cs @@ -5,8 +5,8 @@ namespace TestStack.BDDfy.Samples.Atm { public class AccountHasInsufficientFund { - private Card _card; - private Atm _atm; + private Card _card = null!; + private Atm _atm = null!; // You can override step text using executable attributes [Given("Given the Account Balance is $10")] @@ -63,5 +63,12 @@ public void VerifyLazy() var engine = this.LazyBDDfy(); engine.Run(); } + + [Fact] + public void VerifyLazyWithAllArguments() + { + var engine = this.LazyBDDfy("lazy scenario", nameof(AccountHasInsufficientFund)); + engine.Run(); + } } } \ No newline at end of file diff --git a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs index a31fb495..0c830985 100644 --- a/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs +++ b/src/Samples/TestStack.BDDfy.Samples/Atm/AccountHolderWithdrawsCash.cs @@ -16,8 +16,8 @@ public class AccountHolderWithdrawsCash private const string WhenTheAccountHolderRequestsTitleTemplate = "When the account holder requests ${0}"; private const string AndTheCardShouldBeReturnedTitleTemplate = "And the card should be returned"; - private Card _card; - private Atm _atm; + private Card _card = null!; + private Atm _atm = null!; internal void Given_the_Account_Balance_is(int balance) { diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs index 117b2969..1d9d0fd4 100644 --- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs +++ b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs @@ -3,14 +3,12 @@ namespace TestStack.BDDfy.Samples { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "")] public class BuyingTrainFareWithExamples { - #pragma warning disable 649 - // ReSharper disable once InconsistentNaming - private readonly Fare fare; - private readonly BuyerCategory _buyerCategory; - #pragma warning restore 649 - Money Price { get; set; } + private readonly Fare fare = null!; + private readonly BuyerCategory _buyerCategory = default!; + Money Price { get; set; } = null!; [Fact] public void SuccessfulRailCardPurchases() diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs index b032fa3d..ba413f91 100644 --- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs +++ b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFares/Money.cs @@ -11,9 +11,9 @@ protected bool Equals(Money other) return Amount == other.Amount; } - public override bool Equals(object obj) + public override bool Equals(object? obj) { - if (ReferenceEquals(null, obj)) return false; + if (obj is null) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((Money)obj); diff --git a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs index 06654da4..bf22d0e4 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs @@ -7,7 +7,7 @@ namespace TestStack.BDDfy.Samples { public class CanRunAsyncVoidSteps { - private object _sut; + private object _sut = null!; internal async void GivenSomeAsyncSetup() { diff --git a/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs b/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs index 5293448a..881d2449 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CustomTextReporter.cs @@ -14,7 +14,7 @@ public class CustomTextReporter : IProcessor { private static readonly string Path; - private static string OutputDirectory + private static string? OutputDirectory { get { @@ -25,7 +25,7 @@ private static string OutputDirectory static CustomTextReporter() { - Path = System.IO.Path.Combine(OutputDirectory, "BDDfy-text-report.txt"); + Path = System.IO.Path.Combine(OutputDirectory ?? string.Empty, "BDDfy-text-report.txt"); if(File.Exists(Path)) File.Delete(Path); @@ -52,7 +52,7 @@ public void Process(Story story) if (scenario.Result != Result.Passed && scenario.Steps.Any(s => s.Exception != null)) { scenarioReport.Append(string.Format(" {0} : ", scenario.Result)); - scenarioReport.AppendLine(scenario.Steps.First(s => s.Result == scenario.Result).Exception.Message); + scenarioReport.AppendLine(scenario.Steps.First(s => s.Result == scenario.Result).Exception?.Message); } scenarioReport.AppendLine(); diff --git a/src/Samples/TestStack.BDDfy.Samples/GlobalSuppressions.cs b/src/Samples/TestStack.BDDfy.Samples/GlobalSuppressions.cs new file mode 100644 index 00000000..04ab15b3 --- /dev/null +++ b/src/Samples/TestStack.BDDfy.Samples/GlobalSuppressions.cs @@ -0,0 +1,8 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Test step methods cannot be static", Scope = "namespaceanddescendants", Target = "~N:TestStack.BDDfy.Samples")] \ 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 eb227dc8..7ff2ec5c 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj +++ b/src/Samples/TestStack.BDDfy.Samples/TestStack.BDDfy.Samples.csproj @@ -15,6 +15,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + + all diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Game.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Game.cs index 3a9ba31f..6effde4e 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Game.cs +++ b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Game.cs @@ -25,7 +25,7 @@ public Game(string[] firstRow, string[] secondRow, string[] thirdRow) _board[2] = (string[])thirdRow.Clone(); } - public string Winner + public string? Winner { get { @@ -62,15 +62,11 @@ public void PlayAt(int row, int column) _board[row][column] = player; } - public override bool Equals(object obj) - { - var game = obj as Game; - return game != null && base.Equals(game); - } + public override bool Equals(object? obj) => obj is Game game && Equals(game); public bool Equals(Game other) { - if (ReferenceEquals(null, other)) return false; + if (other is null) return false; if (ReferenceEquals(this, other)) return true; for (int i = 0; i < 3; i++) diff --git a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Helpers.cs b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Helpers.cs index 98d1876c..7da9f793 100644 --- a/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Helpers.cs +++ b/src/Samples/TestStack.BDDfy.Samples/TicTacToe/Helpers.cs @@ -18,7 +18,7 @@ public class GameUnderTest protected const string O = Game.O; protected const string N = Game.N; - protected Game Game { get; set; } + protected Game Game { get; set; } = null!; } public abstract class NewGame : GameUnderTest diff --git a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs b/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs index 8e78f3b2..17c9cd15 100644 --- a/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs +++ b/src/TestStack.BDDfy.Tests/Configuration/StepExecutorTests.cs @@ -18,7 +18,7 @@ public string Results get { return _builder.ToString(); } } - public override object Execute(Step step, object testObject) + public override object? Execute(Step step, object testObject) { try { diff --git a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs index 1ca455cd..544bcd60 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionThrowingTest.cs @@ -9,7 +9,7 @@ namespace TestStack.BDDfy.Tests.Exceptions private bool _givenShouldThrow; private bool _whenShouldThrow; private bool _thenShouldThrow; - Scenario _scenario; + Scenario _scenario = null!; void Given() { @@ -130,7 +130,7 @@ Scenario Scenario } } - Story Story { get; set; } + Story Story { get; set; } = null!; public void AssertTearDownMethodIsExecuted() { diff --git a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionsWhenUsingExamples.cs b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionsWhenUsingExamples.cs index 5bc1fb53..d04bda10 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/ExceptionsWhenUsingExamples.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/ExceptionsWhenUsingExamples.cs @@ -17,9 +17,9 @@ public void CorrectlyReportsErrorWhenAllStepsNotRun() {"foo", "bar"} }; - string arg1 = null; - string arg2 = null; - var arg3 = default(string); + string arg1 = null!; + string arg2 = null!; + var arg3 = default(string)!; this.Given(_ => AFailingStep(arg1), "Given a failing step") .Then(_ => NonExecutedStep(arg2), "Then multiple assertions") .And(_ => NonExecutedStep(arg3), "The second one blows up") diff --git a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenGivenThrowsNotImplementedException.cs b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenGivenThrowsNotImplementedException.cs index 27240924..400f80b9 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenGivenThrowsNotImplementedException.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenGivenThrowsNotImplementedException.cs @@ -9,13 +9,13 @@ public class WhenGivenThrowsNotImplementedException : NotImplementedExceptionBas private void ExecuteUsingFluentScanner() { var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Given, true)); - ex.GetType().FullName.ShouldContain("Inconclusive"); + ex.GetType().FullName!.ShouldContain("Inconclusive"); } private void ExecuteUsingReflectingScanners() { var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Given, false)); - ex.GetType().FullName.ShouldContain("Inconclusive"); + ex.GetType().FullName!.ShouldContain("Inconclusive"); } [Fact] diff --git a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenThenThrowsNotImplementedException.cs b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenThenThrowsNotImplementedException.cs index 1f00d20e..798baeb7 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenThenThrowsNotImplementedException.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenThenThrowsNotImplementedException.cs @@ -9,13 +9,13 @@ public class WhenThenThrowsNotImplementedException : NotImplementedExceptionBase private void ExecuteUsingReflectingScanners() { var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Then, false)); - ex.GetType().FullName.ShouldContain("Inconclusive"); + ex.GetType().FullName!.ShouldContain("Inconclusive"); } private void ExecuteUsingFluentScanner() { var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.Then, true)); - ex.GetType().FullName.ShouldContain("Inconclusive"); + ex.GetType().FullName!.ShouldContain("Inconclusive"); } [Fact] @@ -33,7 +33,7 @@ public void WhenIsReportedAsSuccessfulWhenUsingReflectingScanners() } [Fact] - public void ThenIsReportedAsNotImplemenetedWhenUsingReflectingScanners() + public void ThenIsReportedAsNotImplementedWhenUsingReflectingScanners() { ExecuteUsingReflectingScanners(); Sut.AssertThenStepResult(Result.NotImplemented); diff --git a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenWhenThrowsNotImplementedException.cs b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenWhenThrowsNotImplementedException.cs index 1788f865..88dc60cf 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenWhenThrowsNotImplementedException.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/NotImplementedException/WhenWhenThrowsNotImplementedException.cs @@ -9,13 +9,13 @@ public class WhenWhenThrowsNotImplementedException : NotImplementedExceptionBase private void ExecuteUsingReflectingScanners() { var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.When, false)); - ex.GetType().FullName.ShouldContain("Inconclusive"); + ex.GetType().FullName!.ShouldContain("Inconclusive"); } private void ExecuteUsingFluentScanner() { var ex = Should.Throw(() => Sut.Execute(ThrowingMethods.When, true)); - ex.GetType().FullName.ShouldContain("Inconclusive"); + ex.GetType().FullName!.ShouldContain("Inconclusive"); } [Fact] diff --git a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenResolvingExceptionsFromDifferentScanners.cs b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenResolvingExceptionsFromDifferentScanners.cs index 7c59bdc8..ab7d6d48 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenResolvingExceptionsFromDifferentScanners.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenResolvingExceptionsFromDifferentScanners.cs @@ -7,7 +7,7 @@ namespace TestStack.BDDfy.Tests.Exceptions.OtherExceptions { public class WhenResolvingExceptionsFromDifferentScanners { - private ExceptionThrowingTest _sut; + private ExceptionThrowingTest _sut = null!; /// /// Test to resolve issue where fluent scanner was returning the inner exception rather than the outer one. diff --git a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenThenThrowsExceptionWithExamples.cs b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenThenThrowsExceptionWithExamples.cs index d8de522f..34f59e1a 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenThenThrowsExceptionWithExamples.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/OtherExceptions/WhenThenThrowsExceptionWithExamples.cs @@ -29,7 +29,7 @@ public void EachFailedAssertionExampleRunsTeardown() engine.Story.Result.ShouldBe(Result.Failed); var titles = engine.Story.Scenarios.Select(s => s.Steps.Single(step => step.Result == Result.Failed).Title).ToArray(); - titles.ShouldAllBe(t => t.StartsWith("Then", StringComparison.OrdinalIgnoreCase)); + titles.ShouldAllBe(t => t!.StartsWith("Then", StringComparison.OrdinalIgnoreCase)); } [Fact] @@ -51,7 +51,7 @@ public void EachFailedGivenExampleRunsTeardown() engine.Story.Result.ShouldBe(Result.Failed); var titles = engine.Story.Scenarios.Select(s=>s.Steps.Single(step=>step.Result == Result.Failed).Title).ToArray(); - titles.ShouldAllBe(t=> t.StartsWith("Given", StringComparison.OrdinalIgnoreCase)); + titles.ShouldAllBe(t=> t!.StartsWith("Given", StringComparison.OrdinalIgnoreCase)); } [Fact] @@ -73,7 +73,7 @@ public void EachFailedWhenExampleRunsTeardown() engine.Story.Result.ShouldBe(Result.Failed); var titles = engine.Story.Scenarios.Select(s => s.Steps.Single(step => step.Result == Result.Failed).Title).ToArray(); - titles.ShouldAllBe(t => t.StartsWith("When", StringComparison.OrdinalIgnoreCase)); + titles.ShouldAllBe(t => t!.StartsWith("When", StringComparison.OrdinalIgnoreCase)); } } } diff --git a/src/TestStack.BDDfy.Tests/FileWriterShould.cs b/src/TestStack.BDDfy.Tests/FileWriterShould.cs index 6fcc27b3..083812d5 100644 --- a/src/TestStack.BDDfy.Tests/FileWriterShould.cs +++ b/src/TestStack.BDDfy.Tests/FileWriterShould.cs @@ -15,7 +15,7 @@ public sealed class FileWriterShould [InlineData("report.txt", "TestDirectory")] [InlineData("./reports/report.txt", "TestDirectory")] [InlineData("./reports/report.txt", "TestDirectory/Reports")] - public void CreatePathIfItDoesNotExist(string reportName, string outputDirectory) + public void CreatePathIfItDoesNotExist(string reportName, string? outputDirectory) { var fileWriter = new FileWriter(); outputDirectory = outputDirectory is null ? null : System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString(), $"{outputDirectory}"); diff --git a/src/TestStack.BDDfy.Tests/GlobalSuppressions.cs b/src/TestStack.BDDfy.Tests/GlobalSuppressions.cs new file mode 100644 index 00000000..e40ab68c --- /dev/null +++ b/src/TestStack.BDDfy.Tests/GlobalSuppressions.cs @@ -0,0 +1,9 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Test step methods cannot be static", Scope = "namespaceanddescendants", Target = "~N:TestStack.BDDfy.Tests")] + \ No newline at end of file diff --git a/src/TestStack.BDDfy.Tests/HumanizerTests.cs b/src/TestStack.BDDfy.Tests/HumanizerTests.cs index 079666a9..a4734876 100644 --- a/src/TestStack.BDDfy.Tests/HumanizerTests.cs +++ b/src/TestStack.BDDfy.Tests/HumanizerTests.cs @@ -93,7 +93,7 @@ public void ReportsIllegalExampleStepNames(string stepName, string expectedStepT [InlineData("")] [InlineData(" ")] [InlineData(null)] - internal void HumanizeWithNullOrEmptyInput_ReturnsTheSame(string providedInput) + internal void HumanizeWithNullOrEmptyInput_ReturnsTheSame(string? providedInput) { Humanizer.Humanize(providedInput).ShouldBe(providedInput); } diff --git a/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/DiagnosticsReporterTests.cs b/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/DiagnosticsReporterTests.cs index b7fd6c26..fa0e3dfd 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/DiagnosticsReporterTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/DiagnosticsReporterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using NSubstitute; using TestStack.BDDfy.Reporters; using TestStack.BDDfy.Reporters.Diagnostics; @@ -10,8 +9,8 @@ namespace TestStack.BDDfy.Tests.Reporters.Diagnostics { public class DiagnosticsReporterTests { - private IReportBuilder _builder; - private IReportWriter _writer; + private IReportBuilder _builder = null!; + private IReportWriter _writer = null!; [Fact] public void ShouldCreateReportIfProcessingSucceeds() @@ -19,7 +18,7 @@ public void ShouldCreateReportIfProcessingSucceeds() var sut = CreateSut(); _builder.CreateReport(Arg.Any()).Returns("Report Data"); - sut.Process(new List()); + sut.Process([]); _writer.Received().OutputReport("Report Data", Arg.Any(), Arg.Any()); } @@ -30,7 +29,7 @@ public void ShouldPrintErrorInReportIfProcessingFails() var sut = CreateSut(); _builder.CreateReport(Arg.Any()).Returns(x => { throw new Exception("Error occurred."); }); - sut.Process(new List()); + sut.Process([]); _writer.Received().OutputReport( Arg.Is(s => s.StartsWith("Error occurred.")), diff --git a/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs b/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs index ea665961..c018f79a 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/Diagnostics/WhenBuildingReportDiagnostics.cs @@ -9,9 +9,9 @@ namespace TestStack.BDDfy.Tests.Reporters.Diagnostics { public class WhenBuildingReportDiagnostics { - private DiagnosticsReportBuilder _sut; - private IEnumerable _stories; - private IList _result; + private DiagnosticsReportBuilder _sut = null!; + private IEnumerable _stories = null!; + private IList _result = null!; internal void GivenADiagnosticsReportBuilder() { diff --git a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs index e54258f6..6c0153d2 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using NSubstitute; using Shouldly; @@ -27,7 +26,7 @@ public void ShouldCreateReportIfProcessingSucceeds() { _sut.ReportBuilder.CreateReport(Arg.Any()).Returns(ReportData); - _sut.Process(new List()); + _sut.Process([]); _sut.Writer.Received().OutputReport(ReportData, Arg.Any(), Arg.Any()); } diff --git a/src/TestStack.BDDfy.Tests/Reporters/MarkDown/MarkDownReporterTests.cs b/src/TestStack.BDDfy.Tests/Reporters/MarkDown/MarkDownReporterTests.cs index 7b71f6ca..e1293a53 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/MarkDown/MarkDownReporterTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/MarkDown/MarkDownReporterTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using NSubstitute; using TestStack.BDDfy.Reporters; using TestStack.BDDfy.Reporters.MarkDown; @@ -10,8 +9,8 @@ namespace TestStack.BDDfy.Tests.Reporters.MarkDown { public class MarkDownReporterTests { - private IReportBuilder _builder; - private IReportWriter _writer; + private IReportBuilder _builder = null!; + private IReportWriter _writer = null!; [Fact] public void ShouldCreateReportIfProcessingSucceeds() @@ -19,7 +18,7 @@ public void ShouldCreateReportIfProcessingSucceeds() var sut = CreateSut(); _builder.CreateReport(Arg.Any()).Returns("Report Data"); - sut.Process(new List()); + sut.Process([]); _writer.Received().OutputReport("Report Data", Arg.Any(), Arg.Any()); } @@ -30,7 +29,7 @@ public void ShouldPrintErrorInReportIfProcessingFails() var sut = CreateSut(); _builder.CreateReport(Arg.Any()).Returns(x => { throw new Exception("Error occurred."); }); - sut.Process(new List()); + sut.Process([]); _writer.Received().OutputReport( Arg.Is(s => s.StartsWith("Error occurred.")), diff --git a/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs b/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs index 7d4fecc6..4f59430b 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs @@ -13,8 +13,7 @@ public class ReportModelMapperTests public ReportModelMapperTests() { - _stories = new ReportTestData().CreateTwoStoriesEachWithOneFailingScenarioAndOnePassingScenarioWithThreeStepsOfFiveMillisecondsAndEachHasTwoExamples() - .ToList(); + _stories = [.. new ReportTestData().CreateTwoStoriesEachWithOneFailingScenarioAndOnePassingScenarioWithThreeStepsOfFiveMillisecondsAndEachHasTwoExamples()]; } [Fact] @@ -28,26 +27,38 @@ public void story_should_map_to_report_story() mapped[i].Namespace.ShouldBe(_stories[i].Namespace); mapped[i].Result.ShouldBe(_stories[i].Result); mapped[i].Scenarios.Count.ShouldBe(_stories[i].Scenarios.Count()); - mapped[i].Metadata.ShouldNotBe(null); + mapped[i].Metadata.ShouldNotBeNull(); } } [Fact] public void story_metadata_should_map_to_report_story_metadata() { - var mapped = _stories.ToReportModel().Stories; + var mapped = _stories.ToReportModel().Stories.Select(x => new + { + x.Metadata!.Narrative1, + x.Metadata.Narrative2, + x.Metadata.Narrative3, + x.Metadata.Title, + x.Metadata.TitlePrefix, + x.Metadata.Type, + x.Metadata.ImageUri, + x.Metadata.StoryUri + }).ToArray(); - for (int i = 0; i < 2; i++) + var original = _stories.Select(x => new { - mapped[i].Metadata.Narrative1.ShouldBe(_stories[i].Metadata.Narrative1); - mapped[i].Metadata.Narrative2.ShouldBe(_stories[i].Metadata.Narrative2); - mapped[i].Metadata.Narrative3.ShouldBe(_stories[i].Metadata.Narrative3); - mapped[i].Metadata.Title.ShouldBe(_stories[i].Metadata.Title); - mapped[i].Metadata.TitlePrefix.ShouldBe(_stories[i].Metadata.TitlePrefix); - mapped[i].Metadata.Type.ShouldBe(_stories[i].Metadata.Type); - mapped[i].Metadata.ImageUri.ShouldBe(_stories[i].Metadata.ImageUri); - mapped[i].Metadata.StoryUri.ShouldBe(_stories[i].Metadata.StoryUri); - } + x.Metadata!.Narrative1, + x.Metadata.Narrative2, + x.Metadata.Narrative3, + x.Metadata.Title, + x.Metadata.TitlePrefix, + x.Metadata.Type, + x.Metadata.ImageUri, + x.Metadata.StoryUri + }).ToArray(); + + mapped.ShouldBeEquivalentTo(original); } [Fact] @@ -91,14 +102,17 @@ public void step_should_map_to_report_step() [Fact] public void example_should_map_to_report_example() { - var scenarios = _stories[0].Scenarios.ToList(); - var mapped = _stories.ToReportModel().Stories[0].Scenarios; + var scenarios = _stories[0].Scenarios.Select(x=> new { + x.Example!.Headers, + x.Example.Values + }).ToArray(); - for (int i = 0; i < 2; i++) - { - mapped[i].Example.Headers.ShouldBe(scenarios[i].Example.Headers); - mapped[i].Example.Values.ShouldBe(scenarios[i].Example.Values); - } + var mapped = _stories.ToReportModel().Stories[0].Scenarios.Select(x=> new { + x.Example!.Headers, + x.Example.Values + }).ToArray(); + + mapped.ShouldBeEquivalentTo(scenarios); } } } diff --git a/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs b/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs index 4047e738..9eef6951 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs @@ -27,7 +27,7 @@ public IEnumerable CreateMixContainingEachTypeOfOutcome() var storyMetadata1 = new StoryMetadata(typeof(RegularAccountHolderStory), "As a person", "I want ice cream", "So that I can be happy", "Happiness"); 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"); - const StoryMetadata testThatReportWorksWithNoStory = null; + const StoryMetadata testThatReportWorksWithNoStory = null!; var stories = new List { @@ -45,7 +45,7 @@ public IEnumerable CreateMixContainingEachTypeOfOutcomeWithOneScenarioPer var storyMetadata2 = new StoryMetadata(typeof(GoldAccountHolderStory), "As an unhappy examples story", "I want to see failed steps", "So that I can diagnose what's wrong", "Unhappy examples"); var storyMetadata3 = new StoryMetadata(typeof(PlatinumAccountHolderStory), "As a happy examples story", "I want a clean report with examples", "So that the report is clean and readable", "Happy Examples"); - const StoryMetadata testThatReportWorksWithNoStory = null; + const StoryMetadata testThatReportWorksWithNoStory = null!; var stories = new List { @@ -116,18 +116,18 @@ private Scenario[] GetScenarios(bool includeFailingScenario, bool includeExample last.Exception = ex; } } - return new List - { + return + [ new(exampleId, typeof(ExampleScenario), GetExampleExecutionSteps(), "Example Scenario", exampleTable.ElementAt(0), []), new(exampleId, typeof(ExampleScenario), exampleExecutionSteps, "Example Scenario", exampleTable.ElementAt(1), []) - }.ToArray(); + ]; } - return new List - { + return + [ new(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", []), new(typeof(SadPathScenario), sadExecutionSteps, "Sad Path Scenario", []) - }.ToArray(); + ]; } private Scenario[] GetOneOfEachScenarioResult() @@ -155,7 +155,7 @@ private Scenario[] GetOneOfEachScenarioResult() last.Exception = ex; } - return scenarios.ToArray(); + return [.. scenarios]; } private List GetHappyExecutionSteps() diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleActionTests.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleActionTests.cs index 4e88cbf5..288144b8 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleActionTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleActionTests.cs @@ -11,7 +11,7 @@ public class ExampleActionTests [Fact] public void CanUseActionsInExamples() { - ExampleAction actionToPerform = null; + ExampleAction actionToPerform = null!; int valueShouldBe = 0; var story = this.Given(_ => SomeSetup()) .When(() => actionToPerform) diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs index 2a9f2bbc..3a0bc248 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleTableTests.cs @@ -65,9 +65,11 @@ public void Add_WhenColumnCountMismatch_Throws() [Fact] public void CollectionOperations_WorkCorrectly() { - var table = new ExampleTable("A"); - table.Add("val1"); - table.Add("val2"); + var table = new ExampleTable("A") + { + "val1", + "val2" + }; table.Count.ShouldBe(2); table.IsReadOnly.ShouldBeFalse(); @@ -84,9 +86,11 @@ public void CollectionOperations_WorkCorrectly() [Fact] public void CopyTo_CopiesElements() { - var table = new ExampleTable("A"); - table.Add("x"); - table.Add("y"); + var table = new ExampleTable("A") + { + "x", + "y" + }; var array = new Example[3]; table.CopyTo(array, 1); diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs index ca27accf..9c143927 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/ExampleValueTests.cs @@ -11,6 +11,7 @@ public void CanFormatAsStringTests() { new ExampleValue("Header", null, () => 0).GetValueAsString().ShouldBe(""); new ExampleValue("Header", 1, () => 0).GetValueAsString().ShouldBe("1"); + new ExampleValue("Header", (int?)1, () => 0).GetValueAsString().ShouldBe("1"); new ExampleValue("Header", new object(), () => 0).GetValueAsString().ShouldBe("System.Object"); new ExampleValue("Header", new[] {1, 2}, () => 0).GetValueAsString().ShouldBe("1, 2"); } diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs index fe4f884e..2754bd20 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs @@ -60,7 +60,7 @@ public void ExampleTypeMismatch() .WithExamples(new ExampleTable("Wrong type") { new object(), - new object[] { null } + new object[] { null! } }) .BDDfy()); @@ -101,8 +101,8 @@ private void MethodTaking__ExampleInt__(int exampleInt) public int WrongType { get; set; } public int Prop1 { get; set; } - private readonly string _prop2 = null; - private readonly string multiWordHeading = null; + private readonly string _prop2 = null!; + private readonly string multiWordHeading = null!; public ExecutionOrder Prop_3 { get; set; } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/ReflectiveWithExamples.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/ReflectiveWithExamples.cs index ce47cc66..874633a9 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/ReflectiveWithExamples.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/ReflectiveWithExamples.cs @@ -10,7 +10,7 @@ public class ReflectiveWithExamples { private readonly Story _story; - public string SecondExample { get; set; } + public string SecondExample { get; set; } = null!; public ReflectiveWithExamples() { _story = this diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs index 434ecbd1..030eb875 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs @@ -27,12 +27,12 @@ public class SomeClassWithStaticMembers SoThat = "So that I can be in full control of what is passed in")] public class BDDfyUsingFluentApi { - private string[] _arrayInput1; - private int[] _arrayInput2; + private string[] _arrayInput1 = null!; + private int[] _arrayInput2 = null!; private int _primitiveInput2; - private string _primitiveInput1; + private string _primitiveInput1 = null!; private SomeEnumForTesting _enumInput; - private Action _action; + private Action _action = null!; internal void GivenAnAction(Action actionInput) { @@ -63,8 +63,8 @@ internal void GivenArrayInputs(string[] input1, int[] input2) internal void GivenEnumerableInputs(IEnumerable input1, IEnumerable input2) { - _arrayInput1 = input1.ToArray(); - _arrayInput2 = input2.ToArray(); + _arrayInput1 = [.. input1]; + _arrayInput2 = [.. input2]; } internal void ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(string expectedInput1, int expectedInput2) @@ -94,11 +94,11 @@ internal void ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstanc public SomeEnumForTesting EnumInputProperty { get { return _enumInputField; } } - readonly string[] _arrayInput1Field = new[] { "1", "2" }; - readonly int[] _arrayInput2Field = new[] { 3, 4 }; + readonly string[] _arrayInput1Field = ["1", "2"]; + readonly int[] _arrayInput2Field = [3, 4]; - private readonly IEnumerable EnumerableString = new[] {"1", null, "2"}; - private readonly IEnumerable EnumerableInt = new[] {1, 2}; + private readonly IEnumerable EnumerableString = ["1", null!, "2"]; + private readonly IEnumerable EnumerableInt = [1, 2]; public string[] ArrayInput1Property { get { return _arrayInput1Field; } } public int[] ArrayInput2Property { get { return _arrayInput2Field; } } @@ -130,8 +130,8 @@ public void PassingPublicStaticPrimitivePropertyAsArguments() [Fact] public void PassingNullPrimitiveArgumentInline() { - this.Given(x => x.GivenPrimitiveInputs(null, 2), "Given inline input arguments {0} and {1}") - .Then(x => x.ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(null, 2)) + this.Given(x => x.GivenPrimitiveInputs(null!, 2), "Given inline input arguments {0} and {1}") + .Then(x => x.ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(null!, 2)) .BDDfy(); } @@ -149,7 +149,7 @@ public void PassingPrimitiveArgumentsUsingVariables() [Fact] public void PassingNullAsPrimitiveArgumentsUsingVariables() { - string input1 = null; + string input1 = null!; var input2 = 2; this.Given(x => x.GivenPrimitiveInputs(input1, input2), "Given input arguments {0} and {1} are passed in using varialbles") @@ -217,16 +217,16 @@ public void PassingEnumerableArguments() [Fact] public void PassingNullArrayArgumentInline() { - this.Given(x => x.GivenArrayInputs(new[] {"1", null, "2"}, new[] {1, 2}), "Given inline input arguments {0} and {1}") - .Then(x => x.ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(new[] { "1", null, "2" }, new[] { 1, 2 })) + this.Given(x => x.GivenArrayInputs(new[] { "1", null!, "2" }, new[] { 1, 2 }), "Given inline input arguments {0} and {1}") + .Then(x => x.ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(new[] { "1", null!, "2" }, new[] { 1, 2 })) .BDDfy(); } [Fact] public void PassingNullAsArrayArgumentInline() { - this.Given(x => x.GivenArrayInputs(null, new[] {1, 2}), "Given inline input arguments {0} and {1}") - .Then(x => x.ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(null, new[] { 1, 2 })) + this.Given(x => x.GivenArrayInputs(null!, new[] {1, 2}), "Given inline input arguments {0} and {1}") + .Then(x => x.ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(null!, new[] { 1, 2 })) .BDDfy(); } @@ -244,7 +244,7 @@ public void PassingArrayArgumentsUsingVariables() [Fact] public void PassingNullAsOneOfArrayArgumentUsingVariables() { - var input1 = new[] {null, "2"}; + var input1 = new[] {null!, "2"}; var input2 = new[] {3, 4}; this.Given(x => x.GivenArrayInputs(input1, input2), "Given array input arguments {0} and {1} are passed in using variables") @@ -313,5 +313,18 @@ public void CanPassActionAndTitleToFluentApi() .Then(x => x.ThenCallingTheActionThrows(), "Then calling the action does throw that exception") .BDDfy(); } + + [Fact] + public void WhenWithTitleOnlyCreatesStepWithCorrectTitle() + { + const string whenTitle = "When something happens"; + var story = this.When(whenTitle) + .Then(x => x.ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstance(null!, 0)) + .BDDfy(); + + var scenario = story.Scenarios.First(); + var whenStep = scenario.Steps.First(s => s.Title == whenTitle); + whenStep.ExecutionOrder.ShouldBe(ExecutionOrder.Transition); + } } } \ No newline at end of file diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs index 23dc2e0c..e7ec06a2 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs @@ -5,8 +5,8 @@ namespace TestStack.BDDfy.Tests.Scanner.FluentScanner { public class DoesNotConflictWithnSubstitute { - private ITestContext _subsitute; - private ExampleTable _exampleTable; + private ITestContext _subsitute = null!; + private ExampleTable _exampleTable = null!; [Fact] public void CanUseFluentApiWithNSubstitute() diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs index 045e658f..e6ca65eb 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs @@ -24,7 +24,7 @@ protected string[] InheritedArrayInput2 { get { - return new[] { "5", "6" }; + return ["5", "6"]; } } } @@ -35,9 +35,9 @@ private class ContainerType { public int Target { get; set; } - public string Target2 { get; set; } + public string Target2 { get; set; } = null!; - public ContainerType SubContainer { get; set; } + public ContainerType SubContainer { get; set; } = null!; public override string ToString() { @@ -72,7 +72,7 @@ public void MethodWithNullableArg(decimal? nullableInput) } - public Bar Foo { get; set; } + public Bar Foo { get; set; } = null!; public class Bar { @@ -82,14 +82,14 @@ public void Baz() } } - List GetArgumentValues(Expression> action, ClassUnderTest instance) + List GetArgumentValues(Expression> action, ClassUnderTest instance) { - return action.ExtractArguments(instance).Select(o => o.Value).ToList(); + return [.. action.ExtractArguments(instance).Select(o => o.Value)]; } List GetArguments(Expression> action, ClassUnderTest instance) { - return action.ExtractArguments(instance).ToList(); + return [.. action.ExtractArguments(instance)]; } readonly int _input1 = 1; @@ -138,7 +138,7 @@ public void NoArguments() arguments.Count.ShouldBe(0); } - void AssertReturnedArguments(List arguments, params object[] expectedArgs) + void AssertReturnedArguments(List arguments, params object?[] expectedArgs) { arguments.Count.ShouldBe(expectedArgs.Length); for (int i = 0; i < expectedArgs.Length; i++) @@ -178,7 +178,7 @@ public void InputArgumentsProvidedWhenCastIsInvolved() var input1 = default(decimal); var arguments = GetArguments(x => x.MethodWithNullableArg(input1), new ClassUnderTest()); input1 = 1; - AssertReturnedArguments(arguments.Select(a => a.Value).ToList(), input1); + AssertReturnedArguments([.. arguments.Select(a => a.Value)], input1); } [Fact] @@ -271,16 +271,16 @@ public void ComplexArgument2() [Fact] public void ComplexArgumentWhenContainerIsNull() { - ContainerType nullContainer = null; - var arguments = GetArgumentValues(x => x.MethodWithInputs(nullContainer.SubContainer), new ClassUnderTest()); - AssertReturnedArguments(arguments, new object[] { null }); + ContainerType? nullContainer = null; + var arguments = GetArgumentValues(x => x.MethodWithInputs(nullContainer!.SubContainer), new ClassUnderTest()); + AssertReturnedArguments(arguments, [null]); } [Fact] public void MethodCallValue() { var arguments = GetArgumentValues(x => x.MethodWithInputs(GetNumberThree(), GetFooString()), new ClassUnderTest()); - AssertReturnedArguments(arguments, new object[] { 3, "Foo" }); + AssertReturnedArguments(arguments, [3, "Foo"]); } [Fact] diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ScenarioToBeScannedUsingFluentScanner.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ScenarioToBeScannedUsingFluentScanner.cs index c7ee3db8..0a094501 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ScenarioToBeScannedUsingFluentScanner.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ScenarioToBeScannedUsingFluentScanner.cs @@ -1,4 +1,5 @@ -using System; +using Shouldly; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -11,8 +12,8 @@ class ScenarioToBeScannedUsingFluentScanner internal const string InputDateStepTitleTemplate = "The provided date is {0:MMM d yyyy}"; public static readonly DateTime InputDate = DateTime.Parse("2011-10-20", new CultureInfo("en-AU")); - private string[] _input1; - private int[] _input2; + private string[] _input1 = null!; + private int[] _input2 = null!; private int _input3; public int Input3 @@ -87,6 +88,7 @@ public static IEnumerable GetSteps(ScenarioToBeScannedUsingFluentScanner t .And(s => s.ThenTitleFormatingWorksToo(InputDate), InputDateStepTitleTemplate) .TearDownWith(s => s.Dispose())).FluentScanner; + fluentScanner.ShouldNotBeNull(); return fluentScanner.GetScanner(null, null).Scan().Scenarios.SelectMany(s => s.Steps).ToList(); } } diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs index 899a52f5..5988b271 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepTitleTests.cs @@ -9,7 +9,7 @@ namespace TestStack.BDDfy.Tests.Scanner.FluentScanner [Collection(TestCollectionName.ModifiesConfigurator)] public class StepTitleTests { - private string _state; + private string _state = null!; [Fact] public void UseConfiguration_IncludeInputsInStepTitle() diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepsWithChainedMethods.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepsWithChainedMethods.cs index 4410e187..b594d4fe 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepsWithChainedMethods.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/StepsWithChainedMethods.cs @@ -11,9 +11,9 @@ public class StepsWithChainedMethods private SutStepBuilder _sutStepBuilder = new(); private class SutStepBuilder { - public string state; - private string color; - private string horn; + public string state = null!; + private string color = null!; + private string horn = null!; public SutStepBuilder with_color(string color) { this.color = color; return this; } public SutStepBuilder with_horn(string horn) { this.horn = horn; return this; } diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/UsingCustomStepTitleFactory.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/UsingCustomStepTitleFactory.cs index 2624fabf..a9528a8c 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/UsingCustomStepTitleFactory.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/UsingCustomStepTitleFactory.cs @@ -16,7 +16,7 @@ private class CustomStepTitleFactory : IStepTitleFactory public bool IncludeInputsInStepTitle { get; set; } = true; public StepTitle Create( - string stepTextTemplate, + string? stepTextTemplate, bool? includeInputsInStepTitle, MethodInfo methodInfo, StepArgument[] inputArguments, diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs index 1815ce5b..951444ba 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs @@ -23,13 +23,7 @@ public void IndicatedStepsAreReturned() _steps.Count().ShouldBe(12); } - Step GivenSomeStateStep - { - get - { - return _steps.Single(s => s.Title == "Given some state 1, 2"); - } - } + Step GivenSomeStateStep => _steps.Single(s => s.Title == "Given some state 1, 2"); [Fact] public void GivenSomeState_StepIsASetupMethod() @@ -49,13 +43,8 @@ public void GivenSomeState_StepReports() GivenSomeStateStep.ShouldReport.ShouldBe(true); } - Step WhenSomeStepUsesIncompatibleNamingConventionStep - { - get - { - return _steps.Single(s => s.Title.Trim() == "And when some step uses incompatible naming convention"); - } - } + Step WhenSomeStepUsesIncompatibleNamingConventionStep + => _steps.Single(s => s.Title == "And when some step uses incompatible naming convention"); [Fact] public void WhenSomeStepUsesIncompatibleNamingConvention_IsAConsecutiveSetupMethod() @@ -75,13 +64,7 @@ public void WhenSomeStepUsesIncompatibleNamingConvention_Reports() WhenSomeStepUsesIncompatibleNamingConventionStep.ShouldReport.ShouldBe(true); } - Step AndAMethodTakesArrayInputsStep - { - get - { - return _steps.Single(s => s.Title.Trim() == "And a method takes array inputs 1, 2, 3, 4, 5"); - } - } + Step AndAMethodTakesArrayInputsStep => _steps.Single(s => s.Title == "And a method takes array inputs 1, 2, 3, 4, 5"); [Fact] public void AndAMethodTakesArrayInputs_IsAConsecutiveSetupMethod() @@ -101,13 +84,7 @@ public void AndAMethodTakesArrayInputs_Reports() AndAMethodTakesArrayInputsStep.ShouldReport.ShouldBe(true); } - Step WhenSomethingHappensTransitionStep - { - get - { - return _steps.Single(s => s.Title == "When something happens some input here"); - } - } + Step WhenSomethingHappensTransitionStep => _steps.Single(s => s.Title == "When something happens some input here"); [Fact] public void WhenSomethingHappensTransitionStep_IsATransitionStep() @@ -127,13 +104,7 @@ public void WhenSomethingHappensTransitionStep_Reports() WhenSomethingHappensTransitionStep.ShouldReport.ShouldBe(true); } - Step WhenSomethingHappensTransitionStepIgnoringInputInStepTitle - { - get - { - return _steps.Single(s => s.Title == "And when something happens"); - } - } + Step WhenSomethingHappensTransitionStepIgnoringInputInStepTitle => _steps.Single(s => s.Title == "And when something happens"); [Fact] public void WhenSomethingHappensTransitionStepIgnoringInputInStepTitle_IsAConsecutiveTransitionStep() @@ -153,13 +124,7 @@ public void WhenSomethingHappensTransitionStepIgnoringInputInStepTitle_Reports() WhenSomethingHappensTransitionStepIgnoringInputInStepTitle.ShouldReport.ShouldBe(true); } - Step WhenSomethingHappensConsecutiveTransitionStep - { - get - { - return _steps.Single(s => s.Title.Trim() == "step used with other input for the second time"); - } - } + Step WhenSomethingHappensConsecutiveTransitionStep => _steps.Single(s => s.Title == "step used with other input for the second time"); [Fact] public void WhenSomethingHappensConsecutiveTransitionStep_IsAConsecutiveTransitionStep() @@ -179,13 +144,7 @@ public void WhenSomethingHappensConsecutiveTransitionStep_Reports() WhenSomethingHappensConsecutiveTransitionStep.ShouldReport.ShouldBe(true); } - Step AndThenSomethingElseHappensStep - { - get - { - return _steps.Single(s => s.Title.Trim() == "Overriding step name without arguments"); - } - } + Step AndThenSomethingElseHappensStep => _steps.Single(s => s.Title == "Overriding step name without arguments"); [Fact] public void AndThenSomethingElseHappensStep_IsAConsecutiveTransitionStep() @@ -205,13 +164,7 @@ public void AndThenSomethingElseHappensStep_Reports() AndThenSomethingElseHappensStep.ShouldReport.ShouldBe(true); } - Step ThenTheFollowingAssertionsShouldBeCorrectStep - { - get - { - return _steps.Single(s => s.Title == "Then the following assertions should be correct"); - } - } + Step ThenTheFollowingAssertionsShouldBeCorrectStep => _steps.Single(s => s.Title == "Then the following assertions should be correct"); [Fact] public void ThenTheFollowingAssertionsShouldBeCorrectStep_IsAnAssertingStep() @@ -231,13 +184,7 @@ public void ThenTheFollowingAssertionsShouldBeCorrectStep_Reports() ThenTheFollowingAssertionsShouldBeCorrectStep.ShouldReport.ShouldBe(true); } - Step AndIncorrectAttributeWouldNotMatterStep - { - get - { - return _steps.Single(s => s.Title.Trim() == "And incorrect attribute would not matter"); - } - } + Step AndIncorrectAttributeWouldNotMatterStep => _steps.Single(s => s.Title == "And incorrect attribute would not matter"); [Fact] public void AndIncorrectAttributeWouldNotMatterStep_IsAConsecutiveAssertingStep() @@ -265,7 +212,7 @@ Step AndInputsAreFormattedPropertlyInTheTitle ScenarioToBeScannedUsingFluentScanner.InputDateStepTitleTemplate, ScenarioToBeScannedUsingFluentScanner.InputDate); - return _steps.Single(s => s.Title.Trim() == formattedTitle); + return _steps.Single(s => s.Title == formattedTitle); } } @@ -275,13 +222,7 @@ public void AndInputsAreFormattedPropertlyInTheTitle_IsAConsecutiveAssertingStep AndInputsAreFormattedPropertlyInTheTitle.ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveAssertion); } - Step TearDownStep - { - get - { - return _steps.Single(s => s.Title == "Dispose"); - } - } + Step TearDownStep => _steps.Single(s => s.Title == "Dispose"); [Fact] public void TearDownStep_IsAConsecutiveAssertingStep() diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs index 7f2279d5..bf38ea30 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs @@ -60,13 +60,12 @@ public void ThenIAmNotAStep() public WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed() { _sut = new ScenarioWithMixedSteps(); - _scenario = + _scenario = new ReflectiveScenarioScanner( - new IStepScanner[] - { - new ExecutableAttributeStepScanner(), - new DefaultMethodNameStepScanner() - }).Scan(TestContext.GetContext(_sut)).First(); + [ + new ExecutableAttributeStepScanner(), + new DefaultMethodNameStepScanner() + ]).Scan(TestContext.GetContext(_sut)).First(); } [Fact] @@ -125,7 +124,7 @@ public void LegacyConsecutiveAssertionStepIsScanned() void VerifyStepAndItsProperties(Expression stepMethodAction, ExecutionOrder expectedOrder, int expectedCount = 1) { - var matchingSteps = _scenario.Steps.Where(s => s.Title.Trim() == Configurator.Humanizer.Humanize(Helpers.GetMethodInfo(stepMethodAction).Name)); + var matchingSteps = _scenario.Steps.Where(s => s.Title == Configurator.Humanizer.Humanize(Helpers.GetMethodInfo(stepMethodAction).Name)); matchingSteps.Count().ShouldBe(expectedCount); matchingSteps.All(s => s.ExecutionOrder == expectedOrder).ShouldBe(true); } diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs index 680a3838..64b72d46 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs @@ -22,8 +22,8 @@ public WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen() var andAssertMatcher = new MethodNameMatcher(s => s.StartsWith("AndAssert", StringComparison.Ordinal), true, ExecutionOrder.ConsecutiveAssertion, true); var methodNameMatchers = new[] { assertMatcher, andAssertMatcher, specEndMatcher, specStartMatcher, setupMethod }; _scenario = new ScenarioClass(); - var scanner = new MethodNameStepScanner(s => s, methodNameMatchers); - _steps = scanner.Scan(TestContext.GetContext(_scenario)).ToList(); + var scanner = new MethodNameStepScanner(s => s!, methodNameMatchers); + _steps = [.. scanner.Scan(TestContext.GetContext(_scenario))]; } class ScenarioClass @@ -89,7 +89,7 @@ public void IncorrectSpecificationStepIsNotAdded() void AssertSpecificationStepIsScannedProperly(Expression getSpecMethod) { - var specMethods = _steps.Where(s => s.Title.Trim() == Configurator.Humanizer.Humanize(Helpers.GetMethodInfo(getSpecMethod).Name)); + var specMethods = _steps.Where(s => s.Title == Configurator.Humanizer.Humanize(Helpers.GetMethodInfo(getSpecMethod).Name)); specMethods.Count().ShouldBe(1); var specStep = specMethods.First(); specStep.Asserts.ShouldBe(false); diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepScannerFactoryAsyncMethods.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepScannerFactoryAsyncMethods.cs index fdf67b5a..e2679b52 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepScannerFactoryAsyncMethods.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepScannerFactoryAsyncMethods.cs @@ -7,6 +7,8 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "")] + public class WhenStepScannerFactoryAsyncMethods { [Fact] @@ -28,7 +30,8 @@ public void CallingAsyncVoidWhichThrowsIsObservedAndRethrown() public void InvokingAsyncTaskWhichThrowsIsObservedAndRethrown() { var methodInfo = typeof(WhenStepScannerFactoryAsyncMethods).GetMethod("AsyncVoidMethod", BindingFlags.Instance | BindingFlags.NonPublic); - var stepAction = StepActionFactory.GetStepAction(methodInfo, new object[] { new SomeScenario() }); + methodInfo.ShouldNotBeNull(); + var stepAction = StepActionFactory.GetStepAction(methodInfo, [new SomeScenario()]); Should.Throw(()=> AsyncTestRunner.Run(() => stepAction(this))); } @@ -37,7 +40,8 @@ public void InvokingAsyncTaskWhichThrowsIsObservedAndRethrown() public void InvokingAsyncVoidWhichThrowsIsObservedAndRethrown() { var methodInfo = typeof(WhenStepScannerFactoryAsyncMethods).GetMethod("AsyncTaskMethod", BindingFlags.Instance | BindingFlags.NonPublic); - var stepAction = StepActionFactory.GetStepAction(methodInfo, new object[] { new SomeScenario() }); + methodInfo.ShouldNotBeNull(); + var stepAction = StepActionFactory.GetStepAction(methodInfo, [new SomeScenario()]); Should.Throw(()=> AsyncTestRunner.Run(() => stepAction(this))); } @@ -45,13 +49,13 @@ public void InvokingAsyncVoidWhichThrowsIsObservedAndRethrown() private async void AsyncVoidMethod(SomeScenario someScenario) { await Task.Yield(); - throw new ArgumentException(); + ArgumentException.ThrowIfNullOrEmpty(null); } private async Task AsyncTaskMethod(SomeScenario obj) { await Task.Yield(); - throw new ArgumentException(); + ArgumentException.ThrowIfNullOrEmpty(null); } private class SomeScenario diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsAreDefinedInABaseClass.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsAreDefinedInABaseClass.cs index 8131d8f7..2665ba7f 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsAreDefinedInABaseClass.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsAreDefinedInABaseClass.cs @@ -7,7 +7,7 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { public class WhenStepsAreDefinedInABaseClass { - private Story _story; + private Story _story = null!; class TheBaseClass { diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs index 96901c6c..a26dc267 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepsReturnTheirText.cs @@ -42,7 +42,7 @@ public void Test() private static void AssertStep(Step step, string stepTitle, ExecutionOrder order, bool asserts = false, bool shouldReport = true) { - step.Title.Trim().ShouldBe(stepTitle); + step.Title.ShouldBe(stepTitle); step.Asserts.ShouldBe(asserts); step.ExecutionOrder.ShouldBe(order); step.ShouldReport.ShouldBe(shouldReport); diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassFollowsGivenWhenThenNamingConvention.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassFollowsGivenWhenThenNamingConvention.cs index b3ace10e..d5f4adb1 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassFollowsGivenWhenThenNamingConvention.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassFollowsGivenWhenThenNamingConvention.cs @@ -7,8 +7,8 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { public class WhenTestClassFollowsGivenWhenThenNamingConvention { - private List _steps; - private TypeWithoutAttribute _typeWithoutAttribute; + private List _steps = null!; + private TypeWithoutAttribute _typeWithoutAttribute = null!; private class TypeWithoutAttribute { @@ -42,7 +42,7 @@ public void But_Given_Some_OTHER_state_is_not_set() { } public void VerifyScannedSteps() { _typeWithoutAttribute = new TypeWithoutAttribute(); - _steps = new DefaultMethodNameStepScanner().Scan(TestContext.GetContext(_typeWithoutAttribute)).ToList(); + _steps = [.. new DefaultMethodNameStepScanner().Scan(TestContext.GetContext(_typeWithoutAttribute))]; int stepIndex = 0; _steps.Count.ShouldBe(24); @@ -74,7 +74,7 @@ public void VerifyScannedSteps() private static void AssertStep(Step step, string stepTitle, ExecutionOrder order, bool asserts = false, bool shouldReport = true) { - step.Title.Trim().ShouldBe(stepTitle); + step.Title.ShouldBe(stepTitle); step.Asserts.ShouldBe(asserts); step.ExecutionOrder.ShouldBe(order); step.ShouldReport.ShouldBe(shouldReport); diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs index 5d47e522..d6e534b2 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs @@ -21,7 +21,7 @@ private class TypeWithAttribute [Then] [RunStepWithArgs(1, 2)] [RunStepWithArgs(3, 4)] - public void Then(int input1, int input2) { } + public void Then(int _, int __) { } public void ThenIShouldNotBeReturnedBecauseIDoNotHaveAttributes() { } @@ -63,13 +63,12 @@ public void Executable() { } public WhenTestClassUsesExecutableAttributes() { _typeWithAttribute = new TypeWithAttribute(); - _steps = new ExecutableAttributeStepScanner().Scan(TestContext.GetContext(_typeWithAttribute)).ToList(); + _steps = [.. new ExecutableAttributeStepScanner().Scan(TestContext.GetContext(_typeWithAttribute))]; } - private static string GetStepTextFromMethodName(Expression methodInfoAction) - { - return Configurator.Humanizer.Humanize(Helpers.GetMethodInfo(methodInfoAction).Name); - } + private static string GetStepTextFromMethodName(Expression methodInfoAction) + => Configurator.Humanizer.Humanize(Helpers.GetMethodInfo(methodInfoAction).Name) + ?? throw new InvalidOperationException("Step text could not be generated."); [Fact] public void DecoratedMethodsAreReturned() @@ -83,25 +82,25 @@ public void Given() var givenStep = _steps.Single(s => s.Title == "Given"); givenStep.ExecutionOrder.ShouldBe(ExecutionOrder.SetupState); givenStep.Asserts.ShouldBe(false); - givenStep.Title.Trim().ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.Given())); + givenStep.Title.ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.Given())); } [Fact] public void AndGiven() { - var step = _steps.Single(s => s.Title.Trim() == "Some other part of the given"); + var step = _steps.Single(s => s.Title == "Some other part of the given"); step.ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveSetupState); step.Asserts.ShouldBe(false); - step.Title.Trim().ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.SomeOtherPartOfTheGiven())); + step.Title.ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.SomeOtherPartOfTheGiven())); } [Fact] public void ButGiven() { - var step = _steps.Single(s => s.Title.Trim() == "Setup should avoid somethings"); + var step = _steps.Single(s => s.Title == "Setup should avoid somethings"); step.ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveSetupState); step.Asserts.ShouldBe(false); - step.Title.Trim().ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.SetupShouldAvoidSomethings())); + step.Title.ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.SetupShouldAvoidSomethings())); } [Fact] @@ -116,18 +115,18 @@ public void When() [Fact] public void TheOtherPartOfWhen() { - var step = _steps.Single(s => s.Title.Trim() == "The other part of when"); + var step = _steps.Single(s => s.Title == "The other part of when"); step.ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveTransition); - step.Title.Trim().ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.TheOtherPartOfWhen())); + step.Title.ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.TheOtherPartOfWhen())); step.Asserts.ShouldBe(false); } [Fact] public void ButWhen() { - var step = _steps.Single(s => s.Title.Trim() == "And something has not happened"); + var step = _steps.Single(s => s.Title == "And something has not happened"); step.ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveTransition); - step.Title.Trim().ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.AndSomethingHasNotHappened())); + step.Title.ShouldBe(GetStepTextFromMethodName(() => _typeWithAttribute.AndSomethingHasNotHappened())); step.Asserts.ShouldBe(false); } @@ -137,16 +136,16 @@ public void ThenStepsWithArgs() var steps = _steps.Where(s => s.Title == "Then 1, 2" || s.Title == "Then 3, 4").ToList(); steps.All(s => s.ExecutionOrder == ExecutionOrder.Assertion).ShouldBe(true); steps.All(s => s.Asserts).ShouldBe(true); - steps.All(s => s.Title.EndsWith(" 1, 2") || s.Title.EndsWith(" 3, 4")).ShouldBe(true); + steps.All(s => s.Title!.EndsWith(" 1, 2") || s.Title.EndsWith(" 3, 4")).ShouldBe(true); } [Fact] public void AndThen() { - var step = _steps.Single(s => s.Title.Trim() == TypeWithAttribute.MethodTextForAndThen); + var step = _steps.Single(s => s.Title == TypeWithAttribute.MethodTextForAndThen); step.ExecutionOrder.ShouldBe(ExecutionOrder.ConsecutiveAssertion); step.Asserts.ShouldBe(true); - step.Title.Trim().ShouldBe(TypeWithAttribute.MethodTextForAndThen); + step.Title!.Trim().ShouldBe(TypeWithAttribute.MethodTextForAndThen); } [Fact] diff --git a/src/TestStack.BDDfy.Tests/Stories/CanUseACustomStoryAttribute.cs b/src/TestStack.BDDfy.Tests/Stories/CanUseACustomStoryAttribute.cs index fc2e003b..433d3d28 100644 --- a/src/TestStack.BDDfy.Tests/Stories/CanUseACustomStoryAttribute.cs +++ b/src/TestStack.BDDfy.Tests/Stories/CanUseACustomStoryAttribute.cs @@ -11,19 +11,19 @@ class InOrderToStoryAttribute : StoryNarrativeAttribute private const string I_want_prefix = "I want"; // ReSharper restore InconsistentNaming - public string InOrderTo + public string? InOrderTo { get { return Narrative1; } set { Narrative1 = CleanseProperty(value, In_order_to_prefix); } } - public string AsA + public string? AsA { get { return Narrative2; } set { Narrative2 = CleanseProperty(value, As_a_prefix); } } - public string IWant + public string? IWant { get { return Narrative3; } set { Narrative3 = CleanseProperty(value, I_want_prefix); } @@ -40,7 +40,7 @@ public class CanUseACustomStoryAttribute public void When_InOrderTo_is_specified_the_InOrderTo_syntax_is_used() { var story = new DummyScenario().BDDfy(); - + story.Metadata.ShouldNotBeNull(); story.Metadata.Narrative1.ShouldBe("In order to do something"); story.Metadata.Narrative2.ShouldBe("As a programmer"); story.Metadata.Narrative3.ShouldBe("I want this to work"); diff --git a/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInFluentMode.cs b/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInFluentMode.cs index 398a5274..dac94acb 100644 --- a/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInFluentMode.cs +++ b/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInFluentMode.cs @@ -14,6 +14,7 @@ public void Verify() .Then(_ => ThenTheSpecifiedStoryShouldBeUsed()) .BDDfy(); + story.Metadata.ShouldNotBeNull(); story.Metadata.Type.ShouldBe(typeof(SharedStoryNotion)); } diff --git a/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInReflectiveMode.cs b/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInReflectiveMode.cs index c8d394c4..1fd8eae6 100644 --- a/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInReflectiveMode.cs +++ b/src/TestStack.BDDfy.Tests/Stories/StoryCanBeSpecifiedInReflectiveMode.cs @@ -11,6 +11,7 @@ public void Verify() { var story = this.BDDfy(); + story.Metadata.ShouldNotBeNull(); story.Metadata.Type.ShouldBe(typeof(SharedStoryNotion)); } diff --git a/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs b/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs index e183f51f..2d6a7642 100644 --- a/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs +++ b/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs @@ -6,7 +6,7 @@ namespace TestStack.BDDfy.Tests.Stories { public class StoryClassAndScenarioClassAreTheSame { - private Story _story; + private Story _story = null!; [Story( AsA = "As a story with no scenarios specified using attributes", @@ -27,7 +27,7 @@ void WhenTheStoryIsBddified() void ThenStoryIsReturnedAsAStory() { - _story.Metadata.Type.ShouldBe(typeof(StoryAsScenario)); + _story.Metadata!.Type.ShouldBe(typeof(StoryAsScenario)); } [AndThen(StepTitle = "and as a scenario")] @@ -41,7 +41,7 @@ void andAsAScenario() void andTheNarrativeIsReturnedAsExpected() { var expectedNarrative = (StoryAttribute)typeof(StoryAsScenario).GetCustomAttributes(typeof(StoryAttribute), false).First(); - _story.Metadata.ShouldNotBe(null); + _story.Metadata.ShouldNotBeNull(); _story.Metadata.Narrative1.ShouldBe(expectedNarrative.AsA); _story.Metadata.Narrative2.ShouldBe(expectedNarrative.IWant); _story.Metadata.Narrative3.ShouldBe(expectedNarrative.SoThat); diff --git a/src/TestStack.BDDfy.Tests/Stories/StoryDouble.cs b/src/TestStack.BDDfy.Tests/Stories/StoryDouble.cs index 74e77bdd..def10471 100644 --- a/src/TestStack.BDDfy.Tests/Stories/StoryDouble.cs +++ b/src/TestStack.BDDfy.Tests/Stories/StoryDouble.cs @@ -17,6 +17,7 @@ public void ScanningAScenarioWithoutArgsFromAStoryClass() var scanner = new DefaultScanner(TestContext.GetContext(testObject), new ReflectiveScenarioScanner(new DefaultMethodNameStepScanner()), typeof(StoryDouble)); var story = scanner.Scan(); + story.Metadata.ShouldNotBeNull(); story.Metadata.Type.ShouldBe(typeof(StoryDouble)); story.Scenarios.Count().ShouldBe(1); story.Scenarios.Single().TestObject.ShouldBeAssignableTo(); diff --git a/src/TestStack.BDDfy.Tests/Stories/StorySubclass.cs b/src/TestStack.BDDfy.Tests/Stories/StorySubclass.cs index 0e28e36b..b4c4a5c1 100644 --- a/src/TestStack.BDDfy.Tests/Stories/StorySubclass.cs +++ b/src/TestStack.BDDfy.Tests/Stories/StorySubclass.cs @@ -5,15 +5,13 @@ namespace TestStack.BDDfy.Tests.Stories { public class StoryAttributeIsInheritedFromBaseClass : StoryClassBase { - Story _story; - [Fact] public void Verify() { - _story = this.BDDfy(); - _story.Metadata.ShouldNotBe(null); - _story.Metadata.Title.ShouldBe(StoryTitle); - _story.Metadata.TitlePrefix.ShouldBe(StoryTitlePrefix); + var story = this.BDDfy(); + story.Metadata.ShouldNotBeNull(); + story.Metadata.Title.ShouldBe(StoryTitle); + story.Metadata.TitlePrefix.ShouldBe(StoryTitlePrefix); } void WhenTheSubclassIsBddified() diff --git a/src/TestStack.BDDfy.Tests/Stories/WhenAStoryHasUriAndImageMetadata.cs b/src/TestStack.BDDfy.Tests/Stories/WhenAStoryHasUriAndImageMetadata.cs index 39b6d75f..6203cf79 100644 --- a/src/TestStack.BDDfy.Tests/Stories/WhenAStoryHasUriAndImageMetadata.cs +++ b/src/TestStack.BDDfy.Tests/Stories/WhenAStoryHasUriAndImageMetadata.cs @@ -15,6 +15,7 @@ public class WhenAStoryHasUriAndImageMetadata public void Then_it_is_injected_by_BDDfy() { var story = new DummyScenario().BDDfy(); + story.Metadata.ShouldNotBeNull(); story.Metadata.StoryUri.ShouldBe("http://teststoryuri.com.au"); story.Metadata.ImageUri.ShouldBe("http://teststoryuri.com.au/storyimg.png"); } diff --git a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesAsATextInAsAProperty.cs b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesAsATextInAsAProperty.cs index 9347923a..33b4b4c3 100644 --- a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesAsATextInAsAProperty.cs +++ b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesAsATextInAsAProperty.cs @@ -13,7 +13,7 @@ public class WhenStoryAttibuteMissesAsATextInAsAProperty public void Then_it_is_injected_by_BDDfy() { var story = new DummyScenario().BDDfy(); - + story.Metadata.ShouldNotBeNull(); story.Metadata.Narrative1.ShouldBe("As a programmer"); story.Metadata.Narrative2.ShouldBe("I want the missing 'As a' to be added to story metadata"); story.Metadata.Narrative3.ShouldBe("So that I don't have to duplicate it on the string"); diff --git a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesDuplicateTextsInProperties.cs b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesDuplicateTextsInProperties.cs index f5c1b21a..af7b0776 100644 --- a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesDuplicateTextsInProperties.cs +++ b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesDuplicateTextsInProperties.cs @@ -13,7 +13,7 @@ public class WhenStoryAttibuteMissesDuplicateTextsInProperties public void Then_it_is_injected_by_BDDfy() { var story = new DummyScenario().BDDfy(); - + story.Metadata.ShouldNotBeNull(); story.Metadata.Narrative1.ShouldBe("As a programmer"); story.Metadata.Narrative2.ShouldBe("I want the missing texts to be added to story metadata"); story.Metadata.Narrative3.ShouldBe("So that I don't have to duplicate it on the string"); diff --git a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesIWantTextInIWantProperty.cs b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesIWantTextInIWantProperty.cs index a839f597..c4b53e55 100644 --- a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesIWantTextInIWantProperty.cs +++ b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesIWantTextInIWantProperty.cs @@ -13,7 +13,7 @@ public class WhenStoryAttibuteMissesIWantTextInIWantProperty public void Then_it_is_injected_by_BDDfy() { var story = new DummyScenario().BDDfy(); - + story.Metadata.ShouldNotBeNull(); story.Metadata.Narrative1.ShouldBe("As a programmer"); story.Metadata.Narrative2.ShouldBe("I want the missing 'I want' to be added to story metadata"); story.Metadata.Narrative3.ShouldBe("So that I don't have to duplicate it on the string"); diff --git a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesSoThatTextInSoThatProperty.cs b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesSoThatTextInSoThatProperty.cs index 32aa0d3b..280e9044 100644 --- a/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesSoThatTextInSoThatProperty.cs +++ b/src/TestStack.BDDfy.Tests/Stories/WhenStoryAttibuteMissesSoThatTextInSoThatProperty.cs @@ -13,7 +13,7 @@ public class WhenStoryAttibuteMissesSoThatTextInSoThatProperty public void Then_it_is_injected_by_BDDfy() { var story = new DummyScenario().BDDfy(); - + story.Metadata.ShouldNotBeNull(); story.Metadata.Narrative1.ShouldBe("As a programmer"); story.Metadata.Narrative2.ShouldBe("I want the missing 'So that' to be added to story metadata"); story.Metadata.Narrative3.ShouldBe("So that I don't have to duplicate it on the string"); diff --git a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj index e4bb5a53..5d5be63b 100644 --- a/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj +++ b/src/TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj @@ -14,6 +14,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/TestStack.BDDfy.Tests/UnusedExampleValueScenario.cs b/src/TestStack.BDDfy.Tests/UnusedExampleValueScenario.cs index e2758b41..e213a806 100644 --- a/src/TestStack.BDDfy.Tests/UnusedExampleValueScenario.cs +++ b/src/TestStack.BDDfy.Tests/UnusedExampleValueScenario.cs @@ -20,7 +20,7 @@ public void WhenExampleIsNotUsedItThrows() public void NullableEnumIsUsedProperly() { SomeEnum? nullableEnum = null; - string anotherExample = null; + string anotherExample = null!; this.Given(_ => GivenANullableEnumExample(nullableEnum)) .Then(_ => AnotherValueIsChanged(anotherExample)) @@ -32,10 +32,12 @@ public void NullableEnumIsUsedProperly() .BDDfy(); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "")] private void AnotherValueIsChanged(string anotherExample) { } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "")] private void GivenANullableEnumExample(SomeEnum? nullableEnum) { } diff --git a/src/TestStack.BDDfy.Tests/WithTagsExtensionsTests.cs b/src/TestStack.BDDfy.Tests/WithTagsExtensionsTests.cs index 9875994f..2d38d9a0 100644 --- a/src/TestStack.BDDfy.Tests/WithTagsExtensionsTests.cs +++ b/src/TestStack.BDDfy.Tests/WithTagsExtensionsTests.cs @@ -1,4 +1,3 @@ -using System.Linq; using Shouldly; using Xunit; diff --git a/src/TestStack.BDDfy.Tests/XUnitOutputReporter.cs b/src/TestStack.BDDfy.Tests/XUnitOutputReporter.cs index 870b0d1d..3f8a3242 100644 --- a/src/TestStack.BDDfy.Tests/XUnitOutputReporter.cs +++ b/src/TestStack.BDDfy.Tests/XUnitOutputReporter.cs @@ -1,16 +1,19 @@ +using System; using TestStack.BDDfy.Reporters; using Xunit; namespace TestStack.BDDfy.Tests { - public class XUnitOutputReporter(ITestOutputHelper testOutputHelper = null): TextReporter + public class XUnitOutputReporter(ITestOutputHelper? testOutputHelper = null): TextReporter { - private readonly ITestOutputHelper _outputHelper = testOutputHelper ?? Xunit.TestContext.Current.TestOutputHelper; + private readonly ITestOutputHelper _outputHelper = testOutputHelper + ?? Xunit.TestContext.Current.TestOutputHelper + ?? throw new InvalidOperationException("No ITestOutputHelper instance available."); - protected override void WriteLine(string text = null) + protected override void WriteLine(string? text = null) { if (text is not null) _outputHelper.WriteLine(text); - base.WriteLine(text); + base.WriteLine(text); } protected override void Write(string text, params object[] args) diff --git a/src/TestStack.BDDfy.sln b/src/TestStack.BDDfy.sln index 7fcee885..82cf5b9e 100644 --- a/src/TestStack.BDDfy.sln +++ b/src/TestStack.BDDfy.sln @@ -8,12 +8,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\.gitattributes = ..\.gitattributes ..\.gitignore = ..\.gitignore .runsettings = .runsettings - ..\appveyor.deploy.yml = ..\appveyor.deploy.yml - ..\appveyor.yml = ..\appveyor.yml - ..\build.cake = ..\build.cake - ..\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 diff --git a/src/TestStack.BDDfy/Reporters/ReportModel.cs b/src/TestStack.BDDfy/Reporters/ReportModel.cs index c7a65285..11f1b70c 100644 --- a/src/TestStack.BDDfy/Reporters/ReportModel.cs +++ b/src/TestStack.BDDfy/Reporters/ReportModel.cs @@ -40,7 +40,7 @@ public class Scenario public TimeSpan Duration { get; set; } - public List Steps { get; set; } = []; + public List Steps { get; } = []; public Result Result { get; set; } } @@ -69,8 +69,6 @@ public class Example public string[] Headers { get; set; } = []; public IEnumerable Values { get; set; } = []; - - public override string ToString() => string.Join(", ", Values.Select(i => i.ToString())); } } } diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs index bfca1bcf..6c51414d 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/Example.cs @@ -11,7 +11,5 @@ public class Example(params ExampleValue[] items) public IEnumerable Values { get; } = items; public object? GetValueOf(int index, Type targetType) => Values.ElementAt(index).GetValue(targetType); - - public override string ToString() => string.Join(", ", Values.Select(i => i.ToString())); } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs index d10fa883..d2fc8d6d 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs @@ -23,7 +23,7 @@ public class ExampleValue(string header, object? underlyingValue, Func getR } ValueHasBeenUsed = true; - return null; + return default; } var valueIsString = _underlyingValue is string; diff --git a/src/TestStack.BDDfy/Step.cs b/src/TestStack.BDDfy/Step.cs index 8400f035..4dbe0e8a 100644 --- a/src/TestStack.BDDfy/Step.cs +++ b/src/TestStack.BDDfy/Step.cs @@ -9,7 +9,7 @@ public class Step private readonly StepTitle _stepTitle; private string? _title; public Step( - Func action, + Func? action, StepTitle stepTitle, bool asserts, ExecutionOrder executionOrder, @@ -42,7 +42,7 @@ public Step(Step step) internal Func? Action { get; set; } public bool Asserts { get; private set; } public bool ShouldReport { get; private set; } - public string? Title => _title??= _stepTitle; + public string? Title => (_title ??= _stepTitle)?.Trim(); public ExecutionOrder ExecutionOrder { get; private set; } public Result Result { get; set; } public Exception? Exception { get; set; }