Skip to content

Commit b771f4c

Browse files
author
Omer Raviv
committed
Added StepExecutor class to allow users to add custom logic before/after each Step.
1 parent ee59d29 commit b771f4c

16 files changed

Lines changed: 204 additions & 84 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace TestStack.BDDfy.Tests.Configuration
2+
{
3+
public class EmptyScenario
4+
{
5+
public void GivenSomething() { }
6+
public void WhenSomething() { }
7+
public void ThenSomething() { }
8+
}
9+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Text;
3+
using NUnit.Framework;
4+
using TestStack.BDDfy.Configuration;
5+
6+
namespace TestStack.BDDfy.Tests.Configuration
7+
{
8+
[TestFixture]
9+
public class StepExecutorTests
10+
{
11+
private class TestStepExecutor : StepExecutor
12+
{
13+
readonly StringBuilder _builder = new StringBuilder();
14+
15+
public string Results
16+
{
17+
get { return _builder.ToString(); }
18+
}
19+
20+
public override object Execute(Step step, object testObject)
21+
{
22+
try
23+
{
24+
_builder.AppendLine(string.Format("About to run step '{0}'", step.Title));
25+
return base.Execute(step, testObject);
26+
}
27+
finally
28+
{
29+
_builder.AppendLine(string.Format("Finished running step '{0}'", step.Title));
30+
}
31+
}
32+
}
33+
34+
[Test]
35+
public void CustomizingStepExecutionByOverridingStepExecutor()
36+
{
37+
try
38+
{
39+
var testStepExecutor = new TestStepExecutor();
40+
41+
Configurator.StepExecutor = testStepExecutor;
42+
43+
new EmptyScenario()
44+
.Given(s => s.GivenSomething())
45+
.When(s => s.WhenSomething())
46+
.Then(s => s.ThenSomething())
47+
.BDDfy();
48+
49+
string expected =
50+
@"About to run step 'Given something'
51+
Finished running step 'Given something'
52+
About to run step 'When something'
53+
Finished running step 'When something'
54+
About to run step 'Then something'
55+
Finished running step 'Then something'
56+
";
57+
58+
Assert.AreEqual(expected, testStepExecutor.Results);
59+
60+
}
61+
finally
62+
{
63+
Configurator.StepExecutor = new StepExecutor();
64+
}
65+
}
66+
}
67+
}

TestStack.BDDfy.Tests/Processors/TestRunnerTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class TestRunnerTests
1212
public int ExampleValue { get; set; }
1313

1414
[Test]
15-
public void InitialisesScenarioWithExampleBeforeRunning()
15+
public void InitializesScenarioWithExampleBeforeRunning()
1616
{
1717
const int expectedValue = 1;
1818
var actualValue = 0;
@@ -22,7 +22,7 @@ public void InitialisesScenarioWithExampleBeforeRunning()
2222
}.Single();
2323

2424
var sut = new TestRunner();
25-
Action<object> action = o => actualValue = ExampleValue;
25+
Func<object, object> action = o => actualValue = ExampleValue;
2626
var steps = new List<Step> { new Step(action, new StepTitle("A Step"), true, ExecutionOrder.Initialize, true, new List<StepArgument>()) };
2727

2828
var scenarioWithExample = new Scenario("id", this, steps, "Scenario Text", exampleTable, new List<string>());

TestStack.BDDfy.Tests/Reporters/TextReporter/TextReporterTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ public void LongStepName()
5151
var textReporter = new TextReporter();
5252
var scenario = new Scenario(typeof(TextReporterTests), new List<Step>
5353
{
54-
new Step(o =>{ }, new StepTitle("Given a normal length title"), false, ExecutionOrder.SetupState, true, new List<StepArgument>()),
55-
new Step(o =>{ }, new StepTitle("When something of normal length happens"), false, ExecutionOrder.Transition, true, new List<StepArgument>()),
56-
new Step(o =>{ }, new StepTitle("Then some long state should be: #Title\r\n\r\nSome more stuff which is quite long on the second line\r\n\r\nAnd finally another really long line"),
54+
new Step(o => null, new StepTitle("Given a normal length title"), false, ExecutionOrder.SetupState, true, new List<StepArgument>()),
55+
new Step(o => null, new StepTitle("When something of normal length happens"), false, ExecutionOrder.Transition, true, new List<StepArgument>()),
56+
new Step(o => null, new StepTitle("Then some long state should be: #Title\r\n\r\nSome more stuff which is quite long on the second line\r\n\r\nAnd finally another really long line"),
5757
true, ExecutionOrder.Assertion, true, new List<StepArgument>()),
58-
new Step(o =>{ }, new StepTitle("And a normal length assertion"), true, ExecutionOrder.ConsecutiveAssertion, true, new List<StepArgument>())
58+
new Step(o => null, new StepTitle("And a normal length assertion"), true, ExecutionOrder.ConsecutiveAssertion, true, new List<StepArgument>())
5959
}, "Scenario Text", new List<string>());
6060
textReporter.Process(new Story(new StoryMetadata(typeof(TextReporterTests), new StoryNarrativeAttribute()),
6161
scenario));

TestStack.BDDfy.Tests/Scanner/ReflectiveScanner/WhenStepScannerFactoryAsyncMethods.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Reflection;
33
using System.Threading.Tasks;
44
using NUnit.Framework;
5+
using TestStack.BDDfy.Processors;
56

67
namespace TestStack.BDDfy.Tests.Scanner.ReflectiveScanner
78
{
@@ -11,17 +12,16 @@ public class WhenStepScannerFactoryAsyncMethods
1112
[Test]
1213
public void CallingAsyncTaskWhichThrowsIsObservedAndRethrown()
1314
{
14-
var stepAction = StepActionFactory.GetStepAction<SomeScenario>(o => AsyncTaskMethod(o));
15-
16-
Assert.Throws<ArgumentException>(()=>stepAction(new SomeScenario()));
15+
var stepAction = StepActionFactory.GetStepAction<SomeScenario>(o => AsyncTaskMethod(o));
16+
Assert.Throws<ArgumentException>(()=> AsyncTestRunner.Run(() => stepAction(new SomeScenario())));
1717
}
1818

1919
[Test]
2020
public void CallingAsyncVoidWhichThrowsIsObservedAndRethrown()
2121
{
2222
var stepAction = StepActionFactory.GetStepAction<SomeScenario>(s=>AsyncVoidMethod(s));
2323

24-
Assert.Throws<ArgumentException>(() => stepAction(new SomeScenario()));
24+
Assert.Throws<ArgumentException>(()=> AsyncTestRunner.Run(() => stepAction(new SomeScenario())));
2525
}
2626

2727
[Test]
@@ -30,7 +30,7 @@ public void InvokingAsyncTaskWhichThrowsIsObservedAndRethrown()
3030
var methodInfo = typeof(WhenStepScannerFactoryAsyncMethods).GetMethod("AsyncVoidMethod", BindingFlags.Instance | BindingFlags.NonPublic);
3131
var stepAction = StepActionFactory.GetStepAction(methodInfo, new object[] { new SomeScenario() });
3232

33-
Assert.Throws<ArgumentException>(() => stepAction(this));
33+
Assert.Throws<ArgumentException>(()=> AsyncTestRunner.Run(() => stepAction(this)));
3434
}
3535

3636
[Test]
@@ -39,7 +39,7 @@ public void InvokingAsyncVoidWhichThrowsIsObservedAndRethrown()
3939
var methodInfo = typeof(WhenStepScannerFactoryAsyncMethods).GetMethod("AsyncTaskMethod", BindingFlags.Instance | BindingFlags.NonPublic);
4040
var stepAction = StepActionFactory.GetStepAction(methodInfo, new object[] { new SomeScenario() });
4141

42-
Assert.Throws<ArgumentException>(() => stepAction(this));
42+
Assert.Throws<ArgumentException>(()=> AsyncTestRunner.Run(() => stepAction(this)));
4343
}
4444

4545
private async void AsyncVoidMethod(SomeScenario someScenario)

TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@
7676
<Compile Include="Arguments\ArgumentsProvidedForGiven.cs" />
7777
<Compile Include="Arguments\ArgumentsProvidedForThen.cs" />
7878
<Compile Include="Arguments\MultipleArgumentsProvidedForTheSameStep.cs" />
79+
<Compile Include="Configuration\EmptyScenario.cs" />
7980
<Compile Include="Configuration\SequentialKeyGeneratorTests.cs" />
81+
<Compile Include="Configuration\StepExecutorTests.cs" />
8082
<Compile Include="Configuration\TestRunnerTests.cs" />
8183
<Compile Include="Reporters\TextReporter\TextReporterTests.cs" />
8284
<Compile Include="Reporters\Html\MetroReportBuilderTests.cs" />

TestStack.BDDfy/Configuration/Configurator.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,14 @@ public static IKeyGenerator IdGenerator
2626
get { return _idGenerator; }
2727
set { _idGenerator = value; }
2828
}
29+
30+
31+
private static IStepExecutor _stepExecutor = new StepExecutor();
32+
public static IStepExecutor StepExecutor
33+
{
34+
get { return _stepExecutor; }
35+
set { _stepExecutor = value; }
36+
}
37+
2938
}
3039
}

TestStack.BDDfy/IStepExecutor.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace TestStack.BDDfy
2+
{
3+
public interface IStepExecutor
4+
{
5+
object Execute(Step step, object testObject);
6+
}
7+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Security;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
6+
namespace TestStack.BDDfy.Processors
7+
{
8+
public static class AsyncTestRunner
9+
{
10+
public static void Run(Func<object> performStep)
11+
{
12+
var oldSyncContext = SynchronizationContext.Current;
13+
try
14+
{
15+
var asyncSyncContext = new AsyncTestSyncContext();
16+
SetSynchronizationContext(asyncSyncContext);
17+
var result = performStep();
18+
var task = result as Task;
19+
if (task != null)
20+
{
21+
try
22+
{
23+
task.Wait();
24+
}
25+
catch (AggregateException ae)
26+
{
27+
var innerException = ae.InnerException;
28+
ExceptionProcessor.PreserveStackTrace(innerException);
29+
throw innerException;
30+
}
31+
}
32+
else
33+
{
34+
var ex = asyncSyncContext.WaitForCompletion();
35+
if (ex != null)
36+
{
37+
ExceptionProcessor.PreserveStackTrace(ex);
38+
throw ex;
39+
}
40+
}
41+
}
42+
finally
43+
{
44+
SetSynchronizationContext(oldSyncContext);
45+
}
46+
}
47+
48+
[SecuritySafeCritical]
49+
private static void SetSynchronizationContext(SynchronizationContext context)
50+
{
51+
SynchronizationContext.SetSynchronizationContext(context);
52+
}
53+
}
54+
}

TestStack.BDDfy/Scanners/StepScanners/AsyncTestSyncContext.cs renamed to TestStack.BDDfy/Processors/AsyncTestSyncContext.cs

File renamed without changes.

0 commit comments

Comments
 (0)