From be3d50201924e356ed014b1e02f66c591800b9ca Mon Sep 17 00:00:00 2001 From: Gurpreet Singh Date: Tue, 26 May 2026 11:59:39 +0100 Subject: [PATCH 01/12] avoid calling _createTitle function multiple times. --- src/TestStack.BDDfy/StepTitle.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/TestStack.BDDfy/StepTitle.cs b/src/TestStack.BDDfy/StepTitle.cs index d3e8daec..79721b2a 100644 --- a/src/TestStack.BDDfy/StepTitle.cs +++ b/src/TestStack.BDDfy/StepTitle.cs @@ -5,11 +5,9 @@ namespace TestStack.BDDfy public class StepTitle { private readonly Func _createTitle; + private string _title; - public StepTitle(string title) - { - _createTitle = () => title; - } + public StepTitle(string title) => _createTitle = () => _title = title; public StepTitle(Func createTitle) { @@ -23,7 +21,7 @@ public static implicit operator string(StepTitle title) public override string ToString() { - return _createTitle(); + return _title ??= _createTitle(); } } } \ No newline at end of file From 97c09bf37ef4e4066a8b44054568de0534d754d9 Mon Sep 17 00:00:00 2001 From: Gurpreet Singh Date: Tue, 26 May 2026 12:11:01 +0100 Subject: [PATCH 02/12] cache step title text once generated --- src/TestStack.BDDfy/Step.cs | 12 ++++++------ src/TestStack.BDDfy/StepTitle.cs | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/TestStack.BDDfy/Step.cs b/src/TestStack.BDDfy/Step.cs index ac331ede..1f667a7f 100644 --- a/src/TestStack.BDDfy/Step.cs +++ b/src/TestStack.BDDfy/Step.cs @@ -6,11 +6,11 @@ namespace TestStack.BDDfy { public class Step { - private readonly StepTitle _title; - + private readonly StepTitle _stepTitle; + private string _title; public Step( Func action, - StepTitle title, + StepTitle stepTitle, bool asserts, ExecutionOrder executionOrder, bool shouldReport, @@ -23,13 +23,13 @@ public Step( Result = Result.NotExecuted; Action = action; Arguments = arguments; - _title = title; + _stepTitle = stepTitle; } public Step(Step step) { Id = step.Id; - _title = step._title; + _stepTitle = step._stepTitle; Asserts = step.Asserts; ExecutionOrder = step.ExecutionOrder; ShouldReport = step.ShouldReport; @@ -46,7 +46,7 @@ public string Title { get { - return _title.ToString(); + return _title??= _stepTitle.ToString(); } } diff --git a/src/TestStack.BDDfy/StepTitle.cs b/src/TestStack.BDDfy/StepTitle.cs index 79721b2a..64250e57 100644 --- a/src/TestStack.BDDfy/StepTitle.cs +++ b/src/TestStack.BDDfy/StepTitle.cs @@ -5,9 +5,8 @@ namespace TestStack.BDDfy public class StepTitle { private readonly Func _createTitle; - private string _title; - public StepTitle(string title) => _createTitle = () => _title = title; + public StepTitle(string title) => _createTitle = () => title; public StepTitle(Func createTitle) { @@ -21,7 +20,7 @@ public static implicit operator string(StepTitle title) public override string ToString() { - return _title ??= _createTitle(); + return _createTitle(); } } } \ No newline at end of file From 8f6ff5e6878ea9d6b2bd9e5c64eb307312f16fd6 Mon Sep 17 00:00:00 2001 From: Gurpreet Singh Date: Tue, 26 May 2026 12:16:48 +0100 Subject: [PATCH 03/12] simplify property definition --- src/TestStack.BDDfy/Step.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/TestStack.BDDfy/Step.cs b/src/TestStack.BDDfy/Step.cs index 1f667a7f..b2111df2 100644 --- a/src/TestStack.BDDfy/Step.cs +++ b/src/TestStack.BDDfy/Step.cs @@ -42,16 +42,8 @@ public Step(Step step) internal Func Action { get; set; } public bool Asserts { get; private set; } public bool ShouldReport { get; private set; } - public string Title - { - get - { - return _title??= _stepTitle.ToString(); - } - } - + public string Title => _title??= _stepTitle.ToString(); public ExecutionOrder ExecutionOrder { get; private set; } - public Result Result { get; set; } public Exception Exception { get; set; } public int ExecutionSubOrder { get; set; } From 896582d16319e0fce1cf03665f1c91f568cff952 Mon Sep 17 00:00:00 2001 From: Gurpreet Singh Date: Tue, 26 May 2026 12:18:16 +0100 Subject: [PATCH 04/12] use implicit string conversion --- src/TestStack.BDDfy/Step.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TestStack.BDDfy/Step.cs b/src/TestStack.BDDfy/Step.cs index b2111df2..444af43c 100644 --- a/src/TestStack.BDDfy/Step.cs +++ b/src/TestStack.BDDfy/Step.cs @@ -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.ToString(); + public string Title => _title??= _stepTitle; public ExecutionOrder ExecutionOrder { get; private set; } public Result Result { get; set; } public Exception Exception { get; set; } From cabbb803375c29c23078f3ec616d3cd3b4221a84 Mon Sep 17 00:00:00 2001 From: Gurpreet Singh Date: Tue, 26 May 2026 23:36:07 +0100 Subject: [PATCH 05/12] add pure attribute to GWT api methods to help compile time suggestions when Bddfy() is not called --- .github/copilot-instructions.md | 4 + src/TestStack.BDDfy/Properties/Annotations.cs | 14 - .../Scanners/StepScanners/Fluent/FluentApi.cs | 303 +++++++++++------- .../Scanners/StepScanners/Fluent/FluentApi.tt | 210 ++++++------ 4 files changed, 309 insertions(+), 222 deletions(-) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..233b8675 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,4 @@ +# Copilot Instructions + +## Project Guidelines +- Repository preference: format FluentStepScannerExtensions extension methods with multiline parameters and expression-bodied single-line where clauses; add [Pure] attribute to IFluentStepBuilder members. \ No newline at end of file diff --git a/src/TestStack.BDDfy/Properties/Annotations.cs b/src/TestStack.BDDfy/Properties/Annotations.cs index 27f81204..95b14c20 100644 --- a/src/TestStack.BDDfy/Properties/Annotations.cs +++ b/src/TestStack.BDDfy/Properties/Annotations.cs @@ -354,20 +354,6 @@ public PublicAPIAttribute([NotNull] string comment) [ExcludeFromCodeCoverage] public sealed class InstantHandleAttribute : Attribute { } - /// - /// Indicates that a method does not make any observable state changes. - /// The same as System.Diagnostics.Contracts.PureAttribute - /// - /// - /// [Pure] private int Multiply(int x, int y) { return x * y; } - /// public void Foo() { - /// const int a = 2, b = 2; - /// Multiply(a, b); // Waring: Return value of pure method is not used - /// } - /// - [AttributeUsage(AttributeTargets.Method, Inherited = true)] - public sealed class PureAttribute : Attribute { } - /// /// Indicates that a parameter is a path to a file or a folder /// within a web project. Path can be relative or absolute, diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.cs index 1d67a9c2..c5e3f0fb 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.Contracts; using System.Linq.Expressions; using System.Threading.Tasks; using TestStack.BDDfy.Configuration; @@ -10,139 +11,160 @@ namespace TestStack.BDDfy { public static class FluentStepScannerExtensions { - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, string stepTextTemplate) - where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, stepTextTemplate); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) - where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step) - where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, string stepTextTemplate) - where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, stepTextTemplate); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) - where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step) - where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Action step, string title) - where TScenario : class - { - return new FluentStepBuilder(testObject).Given(step, title); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Func step, string title) - where TScenario : class - { - return new FluentStepBuilder(testObject).Given(step, title); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> action) - where TScenario : class - { - return new FluentStepBuilder(testObject).Given(action); - } - - public static IFluentStepBuilder Given(this TScenario testObject, string title) - where TScenario : class - { - return new FluentStepBuilder(testObject).Given(title); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, string stepTextTemplate) - where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, stepTextTemplate); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) - where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step) - where TScenario: class - { - return new FluentStepBuilder(testObject).When(step); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, string stepTextTemplate) - where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, stepTextTemplate); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) - where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step) - where TScenario: class - { - return new FluentStepBuilder(testObject).When(step); - } - - public static IFluentStepBuilder When(this TScenario testObject, Action step, string title) - where TScenario : class - { - return new FluentStepBuilder(testObject).When(step, title); - } - - public static IFluentStepBuilder When(this TScenario testObject, Func step, string title) - where TScenario : class - { - return new FluentStepBuilder(testObject).When(step, title); - } - - public static IFluentStepBuilder When(this TScenario testObject, string title) - where TScenario : class - { - return new FluentStepBuilder(testObject).When(title); - } + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + string stepTextTemplate) + where TScenario: class + => new FluentStepBuilder(testObject).Given(step, stepTextTemplate); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) + where TScenario: class + => new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step) + where TScenario: class + => new FluentStepBuilder(testObject).Given(step); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + string stepTextTemplate) + where TScenario: class + => new FluentStepBuilder(testObject).Given(step, stepTextTemplate); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) + where TScenario: class + => new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step) + where TScenario: class + => new FluentStepBuilder(testObject).Given(step); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Action step, + string title) + where TScenario : class + => new FluentStepBuilder(testObject).Given(step, title); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Func step, + string title) + where TScenario : class + => new FluentStepBuilder(testObject).Given(step, title); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> action) + where TScenario : class + => new FluentStepBuilder(testObject).Given(action); + + public static IFluentStepBuilder Given( + this TScenario testObject, + string title) + where TScenario : class + => new FluentStepBuilder(testObject).Given(title); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + string stepTextTemplate) + where TScenario: class + => new FluentStepBuilder(testObject).When(step, stepTextTemplate); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) + where TScenario: class + => new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step) + where TScenario: class + => new FluentStepBuilder(testObject).When(step); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + string stepTextTemplate) + where TScenario: class + => new FluentStepBuilder(testObject).When(step, stepTextTemplate); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) + where TScenario: class + => new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step) + where TScenario: class + => new FluentStepBuilder(testObject).When(step); + + public static IFluentStepBuilder When( + this TScenario testObject, + Action step, + string title) + where TScenario : class + => new FluentStepBuilder(testObject).When(step, title); + + public static IFluentStepBuilder When( + this TScenario testObject, + Func step, + string title) + where TScenario : class + => new FluentStepBuilder(testObject).When(step, title); + + public static IFluentStepBuilder When( + this TScenario testObject, + string title) + where TScenario : class + => new FluentStepBuilder(testObject).When(title); } public interface IFluentStepBuilder where TScenario: class { + [Pure] TScenario TestObject { get; } + [Pure] IFluentStepBuilder Given(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder Given(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder Given(Expression> step); + [Pure] IFluentStepBuilder Given(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder Given(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder Given(Expression> step); + [Pure] IFluentStepBuilder Given(Action step, string title); + [Pure] IFluentStepBuilder Given(Func step, string title); /// @@ -154,24 +176,34 @@ public interface IFluentStepBuilder where TScenario: class /// | Do Other | /// Search for ExampleAction on the BDDfy wiki for more information /// + [Pure] IFluentStepBuilder Given(Expression> action); + [Pure] IFluentStepBuilder Given(string title); + [Pure] IFluentStepBuilder When(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder When(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder When(Expression> step); + [Pure] IFluentStepBuilder When(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder When(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder When(Expression> step); + [Pure] IFluentStepBuilder When(Action step, string title); + [Pure] IFluentStepBuilder When(Func step, string title); /// @@ -183,24 +215,34 @@ public interface IFluentStepBuilder where TScenario: class /// | Do Other | /// Search for ExampleAction on the BDDfy wiki for more information /// + [Pure] IFluentStepBuilder When(Expression> action); + [Pure] IFluentStepBuilder When(string title); + [Pure] IFluentStepBuilder Then(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder Then(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder Then(Expression> step); + [Pure] IFluentStepBuilder Then(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder Then(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder Then(Expression> step); + [Pure] IFluentStepBuilder Then(Action step, string title); + [Pure] IFluentStepBuilder Then(Func step, string title); /// @@ -212,24 +254,34 @@ public interface IFluentStepBuilder where TScenario: class /// | Do Other | /// Search for ExampleAction on the BDDfy wiki for more information /// + [Pure] IFluentStepBuilder Then(Expression> action); + [Pure] IFluentStepBuilder Then(string title); + [Pure] IFluentStepBuilder And(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder And(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder And(Expression> step); + [Pure] IFluentStepBuilder And(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder And(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder And(Expression> step); + [Pure] IFluentStepBuilder And(Action step, string title); + [Pure] IFluentStepBuilder And(Func step, string title); /// @@ -241,24 +293,34 @@ public interface IFluentStepBuilder where TScenario: class /// | Do Other | /// Search for ExampleAction on the BDDfy wiki for more information /// + [Pure] IFluentStepBuilder And(Expression> action); + [Pure] IFluentStepBuilder And(string title); + [Pure] IFluentStepBuilder But(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder But(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder But(Expression> step); + [Pure] IFluentStepBuilder But(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder But(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder But(Expression> step); + [Pure] IFluentStepBuilder But(Action step, string title); + [Pure] IFluentStepBuilder But(Func step, string title); /// @@ -270,24 +332,34 @@ public interface IFluentStepBuilder where TScenario: class /// | Do Other | /// Search for ExampleAction on the BDDfy wiki for more information /// + [Pure] IFluentStepBuilder But(Expression> action); + [Pure] IFluentStepBuilder But(string title); + [Pure] IFluentStepBuilder TearDownWith(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder TearDownWith(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder TearDownWith(Expression> step); + [Pure] IFluentStepBuilder TearDownWith(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder TearDownWith(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder TearDownWith(Expression> step); + [Pure] IFluentStepBuilder TearDownWith(Action step, string title); + [Pure] IFluentStepBuilder TearDownWith(Func step, string title); /// @@ -299,8 +371,10 @@ public interface IFluentStepBuilder where TScenario: class /// | Do Other | /// Search for ExampleAction on the BDDfy wiki for more information /// + [Pure] IFluentStepBuilder TearDownWith(Expression> action); + [Pure] IFluentStepBuilder TearDownWith(string title); } @@ -319,8 +393,7 @@ public FluentStepBuilder(TScenario testObject) { TestObject = testObject; var existingContext = TestContext.GetContext(TestObject); - if (existingContext.FluentScanner == null) - existingContext.FluentScanner = Configurator.FluentScannerFactory.Create(testObject); + existingContext.FluentScanner ??= Configurator.FluentScannerFactory.Create(testObject); scanner = (FluentScanner) existingContext.FluentScanner; } diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.tt b/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.tt index c3ad8552..25504a56 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.tt +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Fluent/FluentApi.tt @@ -17,6 +17,7 @@ }; #> using System; +using System.Diagnostics.Contracts; using System.Linq.Expressions; using System.Threading.Tasks; @@ -27,143 +28,164 @@ namespace TestStack.BDDfy { public static class FluentStepScannerExtensions { - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, string stepTextTemplate) + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + string stepTextTemplate) where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, stepTextTemplate); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) + => new FluentStepBuilder(testObject).Given(step, stepTextTemplate); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step) + => new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step) where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, string stepTextTemplate) + => new FluentStepBuilder(testObject).Given(step); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + string stepTextTemplate) where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, stepTextTemplate); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) + => new FluentStepBuilder(testObject).Given(step, stepTextTemplate); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> step) + => new FluentStepBuilder(testObject).Given(step, includeInputsInStepTitle); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> step) where TScenario: class - { - return new FluentStepBuilder(testObject).Given(step); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Action step, string title) + => new FluentStepBuilder(testObject).Given(step); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Action step, + string title) where TScenario : class - { - return new FluentStepBuilder(testObject).Given(step, title); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Func step, string title) + => new FluentStepBuilder(testObject).Given(step, title); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Func step, + string title) where TScenario : class - { - return new FluentStepBuilder(testObject).Given(step, title); - } - - public static IFluentStepBuilder Given(this TScenario testObject, Expression> action) + => new FluentStepBuilder(testObject).Given(step, title); + + public static IFluentStepBuilder Given( + this TScenario testObject, + Expression> action) where TScenario : class - { - return new FluentStepBuilder(testObject).Given(action); - } - - public static IFluentStepBuilder Given(this TScenario testObject, string title) + => new FluentStepBuilder(testObject).Given(action); + + public static IFluentStepBuilder Given( + this TScenario testObject, + string title) where TScenario : class - { - return new FluentStepBuilder(testObject).Given(title); - } + => new FluentStepBuilder(testObject).Given(title); - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, string stepTextTemplate) + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + string stepTextTemplate) where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, stepTextTemplate); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) + => new FluentStepBuilder(testObject).When(step, stepTextTemplate); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step) + => new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step) where TScenario: class - { - return new FluentStepBuilder(testObject).When(step); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, string stepTextTemplate) + => new FluentStepBuilder(testObject).When(step); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + string stepTextTemplate) where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, stepTextTemplate); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step, bool includeInputsInStepTitle) + => new FluentStepBuilder(testObject).When(step, stepTextTemplate); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step, + bool includeInputsInStepTitle) where TScenario: class - { - return new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); - } - - public static IFluentStepBuilder When(this TScenario testObject, Expression> step) + => new FluentStepBuilder(testObject).When(step, includeInputsInStepTitle); + + public static IFluentStepBuilder When( + this TScenario testObject, + Expression> step) where TScenario: class - { - return new FluentStepBuilder(testObject).When(step); - } - - public static IFluentStepBuilder When(this TScenario testObject, Action step, string title) + => new FluentStepBuilder(testObject).When(step); + + public static IFluentStepBuilder When( + this TScenario testObject, + Action step, + string title) where TScenario : class - { - return new FluentStepBuilder(testObject).When(step, title); - } - - public static IFluentStepBuilder When(this TScenario testObject, Func step, string title) + => new FluentStepBuilder(testObject).When(step, title); + + public static IFluentStepBuilder When( + this TScenario testObject, + Func step, + string title) where TScenario : class - { - return new FluentStepBuilder(testObject).When(step, title); - } - - public static IFluentStepBuilder When(this TScenario testObject, string title) + => new FluentStepBuilder(testObject).When(step, title); + + public static IFluentStepBuilder When( + this TScenario testObject, + string title) where TScenario : class - { - return new FluentStepBuilder(testObject).When(title); - } + => new FluentStepBuilder(testObject).When(title); } public interface IFluentStepBuilder where TScenario: class { + [Pure] TScenario TestObject { get; } <# foreach (var stepType in steps) { #> + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Expression> step); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Expression> step, string stepTextTemplate); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Expression> step, bool includeInputsInStepTitle); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Expression> step); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Action step, string title); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Func step, string title); /// @@ -175,8 +197,10 @@ namespace TestStack.BDDfy /// | Do Other | /// Search for ExampleAction on the BDDfy wiki for more information /// + [Pure] IFluentStepBuilder <#=stepType.Item1#>(Expression> action); + [Pure] IFluentStepBuilder <#=stepType.Item1#>(string title); <# } From e1cfdfefa40f72d9352697960ace6a42e15c28bc Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 28 May 2026 14:17:08 +0100 Subject: [PATCH 06/12] remove tests that did not add any value and where causing other tests to fail randomly --- .../CanRunAsyncSteps.cs | 12 ++++------ .../CanRunAsyncVoidSteps.cs | 18 -------------- .../Processors/AsyncTestSyncContext.cs | 24 +++++++++++++------ 3 files changed, 21 insertions(+), 33 deletions(-) delete mode 100644 src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs diff --git a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs index 47516cc1..194c27ca 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs @@ -7,7 +7,7 @@ namespace TestStack.BDDfy.Samples { public class CanRunAsyncSteps { - private Sut _sut; + private object _sut; internal async void GivenSomeAsyncSetup() { @@ -25,23 +25,19 @@ internal async void AndThenBddfyShouldCaptureExceptionsThrownInAsyncMethod() throw new Exception("Exception in async void method!!"); } - private async Task CreateSut() + private static async Task CreateSut() { await Task.Delay(500); - return new Sut(); + return new object(); } [Fact] public void Run() { var engine = this.LazyBDDfy(); - var exception = Should.Throw(() => engine.Run()); + var exception = Should.Throw(engine.Run); exception.Message.ShouldBe("Exception in async void method!!"); } - - internal class Sut - { - } } } \ No newline at end of file diff --git a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs deleted file mode 100644 index 36afc1e5..00000000 --- a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Threading.Tasks; -using TestStack.BDDfy.Configuration; -using Xunit; - -namespace TestStack.BDDfy.Samples -{ - public class CanRunAsyncVoidSteps - { - [Fact] - internal void Run() => this.BDDfy(); - internal void SetUp() => Configurator.AsyncVoidSupportEnabled = false; - internal void TearDown() => Configurator.AsyncVoidSupportEnabled = true; - - internal async void GivenNonAsyncStep() => await Task.CompletedTask; - internal async void WhenSomethingHappens() => await Task.CompletedTask; - internal async void ThenAssertSomething() => await Task.CompletedTask; - } -} \ No newline at end of file diff --git a/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs b/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs index ecdbfe62..bab669be 100644 --- a/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs +++ b/src/TestStack.BDDfy/Processors/AsyncTestSyncContext.cs @@ -8,21 +8,26 @@ namespace TestStack.BDDfy /// internal class AsyncTestSyncContext : SynchronizationContext { - readonly ManualResetEvent _event = new(initialState: true); + readonly object _lock = new(); Exception _exception; int _operationCount; public override void OperationCompleted() { - var result = Interlocked.Decrement(ref _operationCount); - if (result == 0) - _event.Set(); + lock (_lock) + { + _operationCount--; + if (_operationCount == 0) + Monitor.PulseAll(_lock); + } } public override void OperationStarted() { - Interlocked.Increment(ref _operationCount); - _event.Reset(); + lock (_lock) + { + _operationCount++; + } } public override void Post(SendOrPostCallback d, object state) @@ -59,7 +64,12 @@ public override void Send(SendOrPostCallback d, object state) public Exception WaitForCompletion() { - _event.WaitOne(); + lock (_lock) + { + while (_operationCount > 0) + Monitor.Wait(_lock); + } + return _exception; } } From bd7b4bf5bb25b9ad89f8d44521f69ec6109c69f5 Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 28 May 2026 17:39:48 +0100 Subject: [PATCH 07/12] remove redundant tests rename test cases with better name re order scanner matches to allow GWT name preference --- readme.md | 2 +- .../{CanRunAsyncSteps.cs => CanRunAsyncVoidSteps.cs} | 4 ++-- src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs | 2 +- .../Arguments/ArgumentsProvidedForGiven.cs | 2 +- .../Arguments/ArgumentsProvidedForThen.cs | 2 +- .../Arguments/MultipleArgumentsProvidedForTheSameStep.cs | 2 +- .../Stories/StoryClassAndScenarioClassAreTheSame.cs | 2 +- .../StepScanners/MethodName/DefaultMethodNameStepScanner.cs | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) rename src/Samples/TestStack.BDDfy.Samples/{CanRunAsyncSteps.cs => CanRunAsyncVoidSteps.cs} (91%) diff --git a/readme.md b/readme.md index 8bfe45ed..5370208a 100644 --- a/readme.md +++ b/readme.md @@ -122,7 +122,7 @@ If you prefer to use the official `JetBrains.Annotations` NuGet package instead This is only the tip of iceberg. Absolutely everything you do with BDDfy is extensible and customizable. -You might see full documentation of BDDfy on the [TestStack documentation website](http://bddfy.teststack.net/). +You might see full documentation of BDDfy on the [Read The Docs](https://teststackbddfy.readthedocs.io). Oh and while you are there don't forget to checkout other cool projects from [TestStack](http://www.teststack.net/). ## Authors diff --git a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs similarity index 91% rename from src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs rename to src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs index 194c27ca..06654da4 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncSteps.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CanRunAsyncVoidSteps.cs @@ -5,7 +5,7 @@ namespace TestStack.BDDfy.Samples { - public class CanRunAsyncSteps + public class CanRunAsyncVoidSteps { private object _sut; @@ -32,7 +32,7 @@ private static async Task CreateSut() } [Fact] - public void Run() + public void RunTestWithAsyncVoidSteps() { var engine = this.LazyBDDfy(); var exception = Should.Throw(engine.Run); diff --git a/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs b/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs index ac41d335..3446942b 100644 --- a/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs +++ b/src/Samples/TestStack.BDDfy.Samples/CanWorkWithoutAStory.cs @@ -17,7 +17,7 @@ internal void Then_the_namespace_is_used_in_the_report() } [Fact] - public void Execute() + public void RunTestWithoutAStory() { this.BDDfy(); } diff --git a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs index cc6bb5a8..37d3d4cd 100644 --- a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs +++ b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs @@ -54,7 +54,7 @@ void ThenSeveralSetsOfArgumentsArePassedInProperly() } [Fact] - public void Execute() + public void RunTestWithArgumentsProvidedForGiven() { this.BDDfy(); } diff --git a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForThen.cs b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForThen.cs index 3cbe11b1..f355cdc3 100644 --- a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForThen.cs +++ b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForThen.cs @@ -17,7 +17,7 @@ void ThenArgumentsAreSentToThenPart(int argument1, string argument2) } [Fact] - public void Execute() + public void RunTestWithArgumentsProvidedForThen() { this.BDDfy(); } diff --git a/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs b/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs index 893b13c9..72271e4f 100644 --- a/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs +++ b/src/TestStack.BDDfy.Tests/Arguments/MultipleArgumentsProvidedForTheSameStep.cs @@ -25,7 +25,7 @@ void ThenTheMethodIsCalledOncePerArgument() } [Fact] - public void Execute() + public void RunTestWithMultipleArgumentsProvidedForTheSameStep() { this.BDDfy(); } diff --git a/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs b/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs index e105b2c2..e183f51f 100644 --- a/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs +++ b/src/TestStack.BDDfy.Tests/Stories/StoryClassAndScenarioClassAreTheSame.cs @@ -48,7 +48,7 @@ void andTheNarrativeIsReturnedAsExpected() } [Fact] - public void Execute() + public void RunTestWithStoryClassAndScenarioClassAreTheSame() { try { diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/DefaultMethodNameStepScanner.cs b/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/DefaultMethodNameStepScanner.cs index 7aab44b9..81724951 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/DefaultMethodNameStepScanner.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/DefaultMethodNameStepScanner.cs @@ -7,8 +7,6 @@ public class DefaultMethodNameStepScanner : MethodNameStepScanner public DefaultMethodNameStepScanner() : base(CleanupTheStepText) { - AddMatcher(new MethodNameMatcher(s => s.EndsWith("Context", StringComparison.OrdinalIgnoreCase), ExecutionOrder.Initialize) { ShouldReport = false }); - AddMatcher(new MethodNameMatcher(s => s.Equals("Setup", StringComparison.OrdinalIgnoreCase), ExecutionOrder.Initialize) { ShouldReport = false }); AddMatcher(new MethodNameMatcher(s => s.StartsWith("Given", StringComparison.OrdinalIgnoreCase), ExecutionOrder.SetupState)); AddMatcher(new MethodNameMatcher(s => s.StartsWith("AndGiven", StringComparison.OrdinalIgnoreCase), ExecutionOrder.ConsecutiveSetupState)); AddMatcher(new MethodNameMatcher(s => s.StartsWith("And_Given_", StringComparison.OrdinalIgnoreCase), ExecutionOrder.ConsecutiveSetupState)); @@ -26,6 +24,8 @@ public DefaultMethodNameStepScanner() AddMatcher(new MethodNameMatcher(s => s.StartsWith("But", StringComparison.OrdinalIgnoreCase), ExecutionOrder.ConsecutiveAssertion) { Asserts = true }); AddMatcher(new MethodNameMatcher(s => s.StartsWith("But_Then_", StringComparison.OrdinalIgnoreCase), ExecutionOrder.ConsecutiveAssertion) { Asserts = true }); AddMatcher(new MethodNameMatcher(s => s.StartsWith("ButThen", StringComparison.OrdinalIgnoreCase), ExecutionOrder.ConsecutiveAssertion) { Asserts = true }); + AddMatcher(new MethodNameMatcher(s => s.EndsWith("Context", StringComparison.OrdinalIgnoreCase), ExecutionOrder.Initialize) { ShouldReport = false }); + AddMatcher(new MethodNameMatcher(s => s.Equals("Setup", StringComparison.OrdinalIgnoreCase), ExecutionOrder.Initialize) { ShouldReport = false }); AddMatcher(new MethodNameMatcher(s => s.StartsWith("TearDown", StringComparison.OrdinalIgnoreCase), ExecutionOrder.TearDown) { ShouldReport = false }); } From a57aa2bf1cdf39236277a5f4488fd3f0b1a55fe1 Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 28 May 2026 17:43:48 +0100 Subject: [PATCH 08/12] resolve conflict --- src/TestStack.BDDfy/StepTitle.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TestStack.BDDfy/StepTitle.cs b/src/TestStack.BDDfy/StepTitle.cs index 64250e57..d0eefdb7 100644 --- a/src/TestStack.BDDfy/StepTitle.cs +++ b/src/TestStack.BDDfy/StepTitle.cs @@ -20,7 +20,7 @@ public static implicit operator string(StepTitle title) public override string ToString() { - return _createTitle(); + return _title ??= _createTitle(); } } } \ No newline at end of file From a4d0393ed1552884a546c7247b88b9896e3b02a1 Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 28 May 2026 17:51:02 +0100 Subject: [PATCH 09/12] Fix bad merge fix names and apply modern code style to definition --- .../BuyingTrainFareWithExamples.cs | 4 +- .../Arguments/ArgumentsProvidedForGiven.cs | 6 +- ...MultipleArgumentsProvidedForTheSameStep.cs | 2 +- .../Exceptions/WhenAnInconclusiveTestIsRun.cs | 4 +- .../Processors/TestRunnerTests.cs | 4 +- .../Reporters/Html/HtmlReporterTests.cs | 2 +- .../Reporters/ReportModelMapperTests.cs | 2 +- .../Reporters/ReportTestData.cs | 68 +++++++++---------- .../Scanner/Examples/FluentWithExamples.cs | 4 +- .../AmbiguousHeaderMatchTests.cs | 2 +- .../FluentScanner/BDDfyUsingFluentApi.cs | 14 ++-- .../DoesNotConflictWithnSubstitute.cs | 2 +- .../ExpressionExtensionsTests.cs | 8 +-- .../WhenStepsAreScannedUsingFluentScanner.cs | 2 +- ...leAttributeOrderOrdersTheStepsCorrectly.cs | 2 +- ...ttributeAndMethodNamingConventionIsUsed.cs | 4 +- ...NamingConventionsOtherThanGivenWhenThen.cs | 4 +- .../WhenTestClassUsesExecutableAttributes.cs | 4 +- src/TestStack.BDDfy/Processors/StoryCache.cs | 2 +- src/TestStack.BDDfy/Reporters/ReportModel.cs | 8 +-- .../Reporters/Serializers/JsonFormatter.cs | 10 +-- .../StepScanners/Examples/ExampleTable.cs | 2 +- .../MethodName/MethodNameStepScanner.cs | 6 +- src/TestStack.BDDfy/StepTitle.cs | 5 +- src/TestStack.BDDfy/TestContext.cs | 6 +- 25 files changed, 87 insertions(+), 90 deletions(-) diff --git a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs index 9a0a9c4c..9af74060 100644 --- a/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs +++ b/src/Samples/TestStack.BDDfy.Samples/BuyingTrainFareWithExamples.cs @@ -7,8 +7,8 @@ public class BuyingTrainFareWithExamples { #pragma warning disable 649 // ReSharper disable once InconsistentNaming - private Fare fare; - private BuyerCategory _buyerCategory; + private readonly Fare fare; + private readonly BuyerCategory _buyerCategory; #pragma warning restore 649 Money Price { get; set; } diff --git a/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs b/src/TestStack.BDDfy.Tests/Arguments/ArgumentsProvidedForGiven.cs index 37d3d4cd..395f57fd 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(); - private List _andGivenInput2 = new(); - private List _andGivenInput3 = new(); + private readonly List _andGivenInput1 = []; + private readonly List _andGivenInput2 = []; + private readonly List _andGivenInput3 = []; 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 72271e4f..14430d8b 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(); + private readonly List _inputs = []; [RunStepWithArgs(1)] [RunStepWithArgs(2)] diff --git a/src/TestStack.BDDfy.Tests/Exceptions/WhenAnInconclusiveTestIsRun.cs b/src/TestStack.BDDfy.Tests/Exceptions/WhenAnInconclusiveTestIsRun.cs index 67a2e548..65125ebf 100644 --- a/src/TestStack.BDDfy.Tests/Exceptions/WhenAnInconclusiveTestIsRun.cs +++ b/src/TestStack.BDDfy.Tests/Exceptions/WhenAnInconclusiveTestIsRun.cs @@ -28,8 +28,8 @@ public void TearDownThis() } } - Engine _engine; - private Scenario _scenario; + readonly Engine _engine; + private readonly Scenario _scenario; Step GivenStep { diff --git a/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs b/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs index 85b32b7f..5f98ba33 100644 --- a/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs +++ b/src/TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs @@ -23,9 +23,9 @@ public void InitializesScenarioWithExampleBeforeRunning() var sut = new TestRunner(); Func action = o => actualValue = ExampleValue; - var steps = new List { new(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, []) }; - var scenarioWithExample = new Scenario("id", this, steps, "Scenario Text", exampleTable, new List()); + var scenarioWithExample = new Scenario("id", this, steps, "Scenario Text", exampleTable, []); var story = new Story(new StoryMetadata(typeof(TestRunnerTests), new StoryNarrativeAttribute()), scenarioWithExample); sut.Process(story); diff --git a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs index bfa0b4ca..e54258f6 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/Html/HtmlReporterTests.cs @@ -10,7 +10,7 @@ namespace TestStack.BDDfy.Tests.Reporters.Html { public class HtmlReporterTests { - private TestableHtmlReporter _sut; + private readonly TestableHtmlReporter _sut; private const string OutputPath = @"C:\Reports"; private const string ReportData = "Report Data"; private const string CustomStylesheet = "some custom css in here!"; diff --git a/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs b/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs index 93f815a2..7d4fecc6 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/ReportModelMapperTests.cs @@ -9,7 +9,7 @@ namespace TestStack.BDDfy.Tests.Reporters public class ReportModelMapperTests { - private List _stories; + private readonly List _stories; public ReportModelMapperTests() { diff --git a/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs b/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs index d6da41d4..4047e738 100644 --- a/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs +++ b/src/TestStack.BDDfy.Tests/Reporters/ReportTestData.cs @@ -49,14 +49,14 @@ public IEnumerable CreateMixContainingEachTypeOfOutcomeWithOneScenarioPer var stories = new List { - 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(storyMetadata1, new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario [for Happiness]", [])), + new(storyMetadata1, new Scenario(typeof(SadPathScenario), GetFailingExecutionSteps(), "Sad Path Scenario [for Happiness]", [])), + new(storyMetadata1, new Scenario(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario [for Happiness]", [])), + new(storyMetadata1, new Scenario(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario [for Happiness]", [])), + new(testThatReportWorksWithNoStory, new Scenario(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario [with no story]", [])), + new(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetFailingExecutionSteps(), "Sad Path Scenario [with no story]", [])), + new(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario [with no story]", [])), + new(testThatReportWorksWithNoStory, new Scenario(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario [with no story]", [])), new(storyMetadata2, GetScenarios(true, true)), new(storyMetadata3, GetScenarios(false, true)), }; @@ -118,15 +118,15 @@ private Scenario[] GetScenarios(bool includeFailingScenario, bool includeExample } return 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()) + new(exampleId, typeof(ExampleScenario), GetExampleExecutionSteps(), "Example Scenario", exampleTable.ElementAt(0), []), + new(exampleId, typeof(ExampleScenario), exampleExecutionSteps, "Example Scenario", exampleTable.ElementAt(1), []) }.ToArray(); } return new List { - new(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", new List()), - new(typeof(SadPathScenario), sadExecutionSteps, "Sad Path Scenario", new List()) + new(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", []), + new(typeof(SadPathScenario), sadExecutionSteps, "Sad Path Scenario", []) }.ToArray(); } @@ -134,10 +134,10 @@ private Scenario[] GetOneOfEachScenarioResult() { var scenarios = 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()) + new(typeof(HappyPathScenario), GetHappyExecutionSteps(), "Happy Path Scenario", []), + new(typeof(SadPathScenario), GetSadExecutionSteps(), "Sad Path Scenario", []), + new(typeof(SadPathScenario), GetInconclusiveExecutionSteps(), "Inconclusive Scenario", []), + new(typeof(SadPathScenario), GetNotImplementedExecutionSteps(), "Not Implemented Scenario", []) }; // 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(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}, + new(null, new StepTitle("Given a positive account balance"), true, ExecutionOrder.Assertion, true, []) {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, []) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Then money is dispensed"), true, ExecutionOrder.Assertion, true, []) {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(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}, + new(null, new StepTitle("Given a account balance"), true, ExecutionOrder.Assertion, true, []) {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, []) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Then money dispensed"), true, ExecutionOrder.Assertion, true, []) {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(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}, + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, []) {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, []) {Duration = new TimeSpan(0, 0, 0, 0, 5), Result = Result.Passed}, + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, []) {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(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()), + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, []), + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, []), + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, []), }; SetAllStepResults(steps, Result.Passed); @@ -220,9 +220,9 @@ private List GetInconclusiveExecutionSteps() { var steps = new List { - 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)}, + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, []) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, []) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, []) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, }; SetAllStepResults(steps, Result.Passed); @@ -237,9 +237,9 @@ private List GetNotImplementedExecutionSteps() { var steps = new List { - 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)}, + new(null, new StepTitle("Given a negative account balance"), true, ExecutionOrder.Assertion, true, []) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("When the account holder requests money"), true, ExecutionOrder.Assertion, true, []) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, + new(null, new StepTitle("Then no money is dispensed"), true, ExecutionOrder.Assertion, true, []) {Duration = new TimeSpan(0, 0, 0, 0, 5)}, }; SetAllStepResults(steps, Result.Passed); diff --git a/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs b/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs index 2b7efd13..fe4f884e 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/Examples/FluentWithExamples.cs @@ -101,8 +101,8 @@ private void MethodTaking__ExampleInt__(int exampleInt) public int WrongType { get; set; } public int Prop1 { get; set; } - private string _prop2 = null; - private 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/FluentScanner/AmbiguousHeaderMatchTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/AmbiguousHeaderMatchTests.cs index b606b761..93b287b2 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/AmbiguousHeaderMatchTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/AmbiguousHeaderMatchTests.cs @@ -6,7 +6,7 @@ namespace TestStack.BDDfy.Tests.Scanner.FluentScanner { public class AmbiguousHeaderMatchTests { - private int _count = 0; + private readonly int _count = 0; [Fact] public void ThrowsWhenMultipleHeadersMatchParameterName() diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs index cbca64c6..434ecbd1 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/BDDfyUsingFluentApi.cs @@ -84,21 +84,21 @@ internal void ThenTheArgumentsArePassedInProperlyAndStoredOnTheSameObjectInstanc _arrayInput2.ShouldBe(expectedInput2); } - string _primitiveInput1Field = "1"; - int _primitiveInput2Field = 2; + readonly string _primitiveInput1Field = "1"; + readonly int _primitiveInput2Field = 2; - SomeEnumForTesting _enumInputField = SomeEnumForTesting.Value2; + readonly SomeEnumForTesting _enumInputField = SomeEnumForTesting.Value2; public string PrimitiveInput1Property { get { return _primitiveInput1Field; } } public int PrimitiveInput2Property { get { return _primitiveInput2Field; } } public SomeEnumForTesting EnumInputProperty { get { return _enumInputField; } } - string[] _arrayInput1Field = new[] { "1", "2" }; - int[] _arrayInput2Field = new[] { 3, 4 }; + readonly string[] _arrayInput1Field = new[] { "1", "2" }; + readonly int[] _arrayInput2Field = new[] { 3, 4 }; - private IEnumerable EnumerableString = new[] {"1", null, "2"}; - private IEnumerable EnumerableInt = new[] {1, 2}; + private readonly IEnumerable EnumerableString = new[] {"1", null, "2"}; + private readonly IEnumerable EnumerableInt = new[] {1, 2}; public string[] ArrayInput1Property { get { return _arrayInput1Field; } } public int[] ArrayInput2Property { get { return _arrayInput2Field; } } diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs index 23a3e325..23dc2e0c 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/DoesNotConflictWithnSubstitute.cs @@ -24,7 +24,7 @@ private void ThenICanStillUseNSubsitute() private void WhenSomethingHappens() { - _exampleTable = new ExampleTable(); + _exampleTable = []; _subsitute.Examples = _exampleTable; } diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs index f58b2a25..045e658f 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/ExpressionExtensionsTests.cs @@ -92,11 +92,11 @@ List GetArguments(Expression> action, Class return action.ExtractArguments(instance).ToList(); } - int _input1 = 1; - string _input2 = "2"; + readonly int _input1 = 1; + readonly string _input2 = "2"; const string ConstInput2 = "2"; - int[] _arrayInput1 = { 1, 2 }; + readonly int[] _arrayInput1 = { 1, 2 }; public string[] _arrayInput2 = { "3", "4" }; public int[] ArrayInput1 @@ -129,7 +129,7 @@ string GetInput2(string someInput) return someInput + " Input 2"; } - ContainerType container = new(); + readonly ContainerType container = new(); [Fact] public void NoArguments() diff --git a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs index 032dda2a..1815ce5b 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/FluentScanner/WhenStepsAreScannedUsingFluentScanner.cs @@ -9,7 +9,7 @@ namespace TestStack.BDDfy.Tests.Scanner.FluentScanner [Collection(TestCollectionName.ModifiesConfigurator)] public class WhenStepsAreScannedUsingFluentScanner { - private IEnumerable _steps; + private readonly IEnumerable _steps; public WhenStepsAreScannedUsingFluentScanner() { diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/ExecutableAttributeOrderOrdersTheStepsCorrectly.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/ExecutableAttributeOrderOrdersTheStepsCorrectly.cs index a3f45317..14169a9a 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/ExecutableAttributeOrderOrdersTheStepsCorrectly.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/ExecutableAttributeOrderOrdersTheStepsCorrectly.cs @@ -8,7 +8,7 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { public class ExecutableAttributeOrderOrdersTheStepsCorrectly { - private List _steps; + private readonly List _steps; private class TypeWithOrderedAttribute { diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs index 2d80844e..7f2279d5 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed.cs @@ -9,8 +9,8 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { public class WhenCombinationOfExecutableAttributeAndMethodNamingConventionIsUsed { - private Scenario _scenario; - private ScenarioWithMixedSteps _sut; + private readonly Scenario _scenario; + private readonly ScenarioWithMixedSteps _sut; private class ScenarioWithMixedSteps { diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs index 9693ecad..680a3838 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen.cs @@ -10,8 +10,8 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { public class WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen { - private List _steps; - ScenarioClass _scenario; + private readonly List _steps; + readonly ScenarioClass _scenario; public WhenMethodNamesFollowNamingConventionsOtherThanGivenWhenThen() { diff --git a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs index 12a8c0fc..5d47e522 100644 --- a/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs +++ b/src/TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenTestClassUsesExecutableAttributes.cs @@ -10,8 +10,8 @@ namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner { public class WhenTestClassUsesExecutableAttributes { - private TypeWithAttribute _typeWithAttribute; - private List _steps; + private readonly TypeWithAttribute _typeWithAttribute; + private readonly List _steps; private class TypeWithAttribute { diff --git a/src/TestStack.BDDfy/Processors/StoryCache.cs b/src/TestStack.BDDfy/Processors/StoryCache.cs index 0b0892ed..20437f5d 100644 --- a/src/TestStack.BDDfy/Processors/StoryCache.cs +++ b/src/TestStack.BDDfy/Processors/StoryCache.cs @@ -4,7 +4,7 @@ namespace TestStack.BDDfy.Processors { public class StoryCache : IProcessor { - private static readonly IList Cache = new List(); + private static readonly IList Cache = []; public ProcessType ProcessType { diff --git a/src/TestStack.BDDfy/Reporters/ReportModel.cs b/src/TestStack.BDDfy/Reporters/ReportModel.cs index 833514df..1bc3c1ea 100644 --- a/src/TestStack.BDDfy/Reporters/ReportModel.cs +++ b/src/TestStack.BDDfy/Reporters/ReportModel.cs @@ -10,14 +10,14 @@ public class ReportModel public ReportModel() { - Stories = new List(); + Stories = []; } public class Story { public Story() { - Scenarios = new List(); + Scenarios = []; } public string Namespace { get; set; } @@ -42,8 +42,8 @@ public class Scenario { public Scenario() { - Tags = new List(); - Steps = new List(); + Tags = []; + Steps = []; } public string Id { get; set; } diff --git a/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs b/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs index 2fa425f7..4e2e7f78 100644 --- a/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs +++ b/src/TestStack.BDDfy/Reporters/Serializers/JsonFormatter.cs @@ -5,9 +5,9 @@ namespace TestStack.BDDfy.Reporters.Serializers // http://www.limilabs.com/blog/json-net-formatter public class JsonFormatter { - StringWalker _walker; - IndentWriter _writer = new(); - StringBuilder _currentLine = new(); + readonly StringWalker _walker; + readonly IndentWriter _writer = new(); + readonly StringBuilder _currentLine = new(); bool _quoted; public JsonFormatter(string json) @@ -102,7 +102,7 @@ private void WriteCurrentLine() public class IndentWriter { - StringBuilder _sb = new(); + readonly StringBuilder _sb = new(); int _indent; public void Indent() @@ -137,7 +137,7 @@ public override string ToString() public class StringWalker(string s) { - string _s = s; + readonly string _s = s; public int Index { get; set; } = -1; public bool MoveNext() diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs index 2345b493..113227f6 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleTable.cs @@ -8,7 +8,7 @@ namespace TestStack.BDDfy { public class ExampleTable(params string[] headers): ICollection { - private readonly List _rows = new(); + private readonly List _rows = []; public string[] Headers { get; private set; } = headers; diff --git a/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameStepScanner.cs b/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameStepScanner.cs index 88546e38..e1a21e50 100644 --- a/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameStepScanner.cs +++ b/src/TestStack.BDDfy/Scanners/StepScanners/MethodName/MethodNameStepScanner.cs @@ -49,7 +49,7 @@ public MethodNameStepScanner(Func stepTextTransformer, params Me public MethodNameStepScanner(Func stepTextTransformer) { _stepTextTransformer = stepTextTransformer; - _matchers = new List(); + _matchers = []; } protected void AddMatcher(MethodNameMatcher matcher) @@ -113,14 +113,14 @@ private Step GetStep(object testObject, MethodNameMatcher matcher, MethodInfo me } var stepAction = GetStepAction(method, inputs.ToArray(), returnsItsText); - return new Step(stepAction, new StepTitle(stepMethodName), matcher.Asserts, matcher.ExecutionOrder, matcher.ShouldReport, new List()); + return new Step(stepAction, new StepTitle(stepMethodName), matcher.Asserts, matcher.ExecutionOrder, matcher.ShouldReport, []); } private Step GetStep(object testObject, MethodNameMatcher matcher, MethodInfo method, bool returnsItsText, object[] inputs = null, RunStepWithArgsAttribute argAttribute = null) { var stepMethodName = GetStepTitle(method, testObject, argAttribute, returnsItsText); var stepAction = GetStepAction(method, inputs, returnsItsText); - return new Step(stepAction, new StepTitle(stepMethodName), matcher.Asserts, matcher.ExecutionOrder, matcher.ShouldReport, new List()); + return new Step(stepAction, new StepTitle(stepMethodName), matcher.Asserts, matcher.ExecutionOrder, matcher.ShouldReport, []); } private string GetStepTitle(MethodInfo method, object testObject, RunStepWithArgsAttribute argAttribute, bool returnsItsText) diff --git a/src/TestStack.BDDfy/StepTitle.cs b/src/TestStack.BDDfy/StepTitle.cs index d0eefdb7..f2ea54f6 100644 --- a/src/TestStack.BDDfy/StepTitle.cs +++ b/src/TestStack.BDDfy/StepTitle.cs @@ -18,9 +18,6 @@ public static implicit operator string(StepTitle title) return title.ToString(); } - public override string ToString() - { - return _title ??= _createTitle(); - } + public override string ToString() => _createTitle(); } } \ No newline at end of file diff --git a/src/TestStack.BDDfy/TestContext.cs b/src/TestStack.BDDfy/TestContext.cs index 4c9c6e37..ee8dfc5e 100644 --- a/src/TestStack.BDDfy/TestContext.cs +++ b/src/TestStack.BDDfy/TestContext.cs @@ -4,13 +4,13 @@ namespace TestStack.BDDfy { public class TestContext : ITestContext { - private static readonly Dictionary ContextLookup = new(); - private static object _dictionaryLock = new(); + private static readonly Dictionary ContextLookup = []; + private static readonly object _dictionaryLock = new(); private TestContext(object testObject) { TestObject = testObject; - Tags = new List(); + Tags = []; } public static void SetContext(object testObject, ITestContext context) From aaf7de31d005d0a318adca917300e01245c4c9f1 Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 28 May 2026 19:18:51 +0100 Subject: [PATCH 10/12] pin ubuntu and gitversion specs --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bfba6024..4fb88345 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: semver: ${{ steps.gitversion.outputs.semVer }} fullsemver: ${{ steps.gitversion.outputs.fullSemVer }} @@ -36,7 +36,7 @@ jobs: - name: Install GitVersion uses: gittools/actions/gitversion/setup@v4.1.0 with: - versionSpec: '6.x' + versionSpec: '6.0.x' - name: Determine Version uses: gittools/actions/gitversion/execute@v4.1.0 From d6e2df79d579cbf1111161f7080cc61fba691011 Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 28 May 2026 19:21:51 +0100 Subject: [PATCH 11/12] use gitversion that works with donet gitversion tools --- .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 4fb88345..c3448605 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ jobs: - name: Install GitVersion uses: gittools/actions/gitversion/setup@v4.1.0 with: - versionSpec: '6.0.x' + versionSpec: '6.1.x' - name: Determine Version uses: gittools/actions/gitversion/execute@v4.1.0 From c8e402f3b1c103cc7951650333ad52c06e37558e Mon Sep 17 00:00:00 2001 From: Test Date: Thu, 28 May 2026 19:30:14 +0100 Subject: [PATCH 12/12] update gitversion tools --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3448605..f3b3761e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,12 +34,12 @@ jobs: fetch-depth: 0 # Required for GitVersion - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v4.1.0 + uses: gittools/actions/gitversion/setup@v4.5.0 with: - versionSpec: '6.1.x' + versionSpec: '6.7.x' - name: Determine Version - uses: gittools/actions/gitversion/execute@v4.1.0 + uses: gittools/actions/gitversion/execute@v4.5.0 id: gitversion - name: Format NuGet version