Skip to content

Commit 7c7327f

Browse files
committed
refactor & fix tests
1 parent 00f2521 commit 7c7327f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+16607
-3912
lines changed

AlternativeRuntimes/Runtime.Silverlight3/Async/SilverlightTestAsyncContext.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
using System;
22
using System.Reflection;
3+
using TechTalk.SpecFlow.Async;
34

45
namespace TechTalk.SpecFlow.AsyncContextProvider
56
{
67
/// <summary>
78
/// Provides an implementation of <see cref="IAsyncContextImpl"/> using the Silverlight
89
/// Unit Testing Framework's asynchronous support.
910
/// </summary>
10-
public class SilverlightTestAsyncContext : IAsyncContextImpl
11+
public class SilverlightTestAsyncContext : IAsyncTestExecutor
1112
{
1213
private readonly ISilverlightTestInstance silverlightTestInstance;
1314
private readonly UnitTestingFrameworkHelper unitTestingFrameworkHelper;
@@ -94,5 +95,10 @@ public void EnqueueTestComplete()
9495
{
9596
silverlightTestInstance.EnqueueTestComplete();
9697
}
98+
99+
public void Dispose()
100+
{
101+
//nop;
102+
}
97103
}
98104
}

Runtime/Async/AsyncContext.cs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using TechTalk.SpecFlow.Async;
23

34
namespace TechTalk.SpecFlow
45
{
@@ -17,44 +18,50 @@ namespace TechTalk.SpecFlow
1718
/// </remarks>
1819
public class AsyncContext
1920
{
20-
private readonly IAsyncContextImpl asyncContextImpl;
21+
private readonly IAsyncTestExecutor asyncTestExecutor;
2122

2223
/// <summary>
2324
/// Retrieve the current <see cref="AsyncContext"/>. Will be null unless the
2425
/// generator and runtime support asynchronous tests.
2526
/// </summary>
2627
public static AsyncContext Current
2728
{
28-
get { return ObjectContainer.AsyncContext; }
29+
//get { return ObjectContainer.AsyncContext; }
30+
get
31+
{
32+
throw new NotImplementedException(); //TODO
33+
}
2934
}
3035

31-
private AsyncContext(IAsyncContextImpl asyncContextImpl)
36+
private AsyncContext(IAsyncTestExecutor asyncTestExecutor)
3237
{
33-
this.asyncContextImpl = asyncContextImpl;
38+
this.asyncTestExecutor = asyncTestExecutor;
3439
}
3540

3641
/// <summary>
3742
/// Intended for framework use.
3843
/// </summary>
3944
/// <remarks>
4045
/// Creates a new instance of <see cref="AsyncContext"/> using the given
41-
/// <see cref="IAsyncContextImpl"/> as its implementation. Intended to be
46+
/// <see cref="IAsyncTestExecutor"/> as its implementation. Intended to be
4247
/// called from the generated test code.
4348
/// </remarks>
44-
public static void Register(IAsyncContextImpl asyncContextImpl)
49+
public static void Register(IAsyncTestExecutor asyncTestExecutor)
4550
{
46-
var asyncContext = new AsyncContext(asyncContextImpl);
47-
ObjectContainer.AsyncContext = asyncContext;
51+
var asyncContext = new AsyncContext(asyncTestExecutor);
52+
//ObjectContainer.AsyncContext = asyncContext;
53+
throw new NotImplementedException(); //TODO
4854
}
4955

5056
internal static void Unregister()
5157
{
52-
ObjectContainer.AsyncContext = null;
58+
//ObjectContainer.AsyncContext = null;
59+
throw new NotImplementedException(); //TODO
5360
}
5461

5562
internal void EnqueueWithNewContext(Action action)
5663
{
57-
asyncContextImpl.EnqueueWithNewContext(action);
64+
asyncTestExecutor.EnqueueWithNewContext(action);
5865
}
5966

6067
/// <summary>
@@ -63,15 +70,15 @@ internal void EnqueueWithNewContext(Action action)
6370
/// <param name="callback"></param>
6471
public void EnqueueCallback(Action callback)
6572
{
66-
asyncContextImpl.EnqueueCallback(callback);
73+
asyncTestExecutor.EnqueueCallback(callback);
6774
}
6875

6976
/// <summary>
7077
/// Enqueues a number of actions to be executed asynchronously, but consecutively.
7178
/// </summary>
7279
public void EnqueueCallback(params Action[] callbacks)
7380
{
74-
asyncContextImpl.EnqueueCallback(callbacks);
81+
asyncTestExecutor.EnqueueCallback(callbacks);
7582
}
7683

7784
/// <summary>
@@ -80,7 +87,7 @@ public void EnqueueCallback(params Action[] callbacks)
8087
/// <param name="continueUntil">Predicate that must return true before the work queue is continued.</param>
8188
public void EnqueueConditional(Func<bool> continueUntil)
8289
{
83-
asyncContextImpl.EnqueueConditional(continueUntil);
90+
asyncTestExecutor.EnqueueConditional(continueUntil);
8491
}
8592

8693
/// <summary>
@@ -91,7 +98,7 @@ public void EnqueueConditional(Func<bool> continueUntil)
9198
/// </remarks>
9299
public void EnqueueDelay(TimeSpan delay)
93100
{
94-
asyncContextImpl.EnqueueDelay(delay);
101+
asyncTestExecutor.EnqueueDelay(delay);
95102
}
96103

97104
/// <summary>
@@ -107,7 +114,7 @@ public void EnqueueDelay(double milliseconds)
107114

108115
internal void EnqueueTestComplete()
109116
{
110-
asyncContextImpl.EnqueueTestComplete();
117+
asyncTestExecutor.EnqueueTestComplete();
111118
}
112119
}
113120
}

Runtime/Async/AsyncTestRunner.cs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Reflection;
33

4-
namespace TechTalk.SpecFlow
4+
namespace TechTalk.SpecFlow.Async
55
{
66
/// <summary>
77
/// Implements <see cref="ITestRunner"/>, enqueueing each scenario's steps to be run asynchronously
@@ -21,9 +21,32 @@ public AsyncTestRunner(ITestRunner testRunner)
2121
this.testRunner = testRunner;
2222
}
2323

24-
private static AsyncContext AsyncContext
24+
private IAsyncTestExecutor asyncTestExecutor;
25+
26+
public IAsyncTestExecutor AsyncTestExecutor
27+
{
28+
get
29+
{
30+
if (asyncTestExecutor == null)
31+
throw new InvalidOperationException("Cannot execute asynchronous scenario without asynch test executor");
32+
33+
return asyncTestExecutor;
34+
}
35+
}
36+
37+
public void UnregisterAsyncTestExecutor()
2538
{
26-
get { return AsyncContext.Current; }
39+
if (asyncTestExecutor != null)
40+
{
41+
asyncTestExecutor.Dispose();
42+
asyncTestExecutor = null;
43+
}
44+
}
45+
46+
public void RegisterAsyncTestExecutor(IAsyncTestExecutor newAsyncTestExecutor)
47+
{
48+
UnregisterAsyncTestExecutor();
49+
asyncTestExecutor = newAsyncTestExecutor;
2750
}
2851

2952
public void InitializeTestRunner(Assembly[] bindingAssemblies)
@@ -37,7 +60,6 @@ public void OnFeatureStart(FeatureInfo featureInfo)
3760
// I don't like the idea of enqueueing async steps in a BeforeFeature. Feels like code/test smell
3861
// Also, feature setup/teardown is static, so there will be no context
3962
testRunner.OnFeatureStart(featureInfo);
40-
ObjectContainer.CurrentTestRunner = this;
4163
}
4264

4365
public void OnFeatureEnd()
@@ -46,25 +68,28 @@ public void OnFeatureEnd()
4668
// We're at the end of the async task list, so again, feels like a smell to try and enqueue something
4769
// And again, static method, so no context
4870
testRunner.OnFeatureEnd();
49-
ObjectContainer.CurrentTestRunner = null;
5071
}
5172

5273
public void OnScenarioStart(ScenarioInfo scenarioInfo)
5374
{
54-
if (ObjectContainer.AsyncContext == null)
75+
if (asyncTestExecutor == null)
5576
throw new InvalidOperationException("Cannot start an asynchronous scenario with a null AsyncContext");
5677

5778
// No enqueueing
5879
// The queue is logically empty at this point (we're the first thing to run in a scenario)
5980
// and enqueueing right now will just add to an empty list
6081
testRunner.OnScenarioStart(scenarioInfo);
82+
83+
// register the test executor in the scenario context to be able to used AOP style
84+
ObjectContainer.ScenarioContext.Set(asyncTestExecutor);
85+
ObjectContainer.ScenarioContext.SetTestRunnerUnchecked(this);
6186
}
6287

6388
public void CollectScenarioErrors()
6489
{
6590
// Make sure these commands run after all other steps
66-
AsyncContext.EnqueueCallback(() => testRunner.CollectScenarioErrors());
67-
AsyncContext.EnqueueTestComplete();
91+
AsyncTestExecutor.EnqueueCallback(() => testRunner.CollectScenarioErrors());
92+
AsyncTestExecutor.EnqueueTestComplete();
6893
}
6994

7095
public void OnScenarioEnd()
@@ -73,37 +98,37 @@ public void OnScenarioEnd()
7398
// The test framework should ensure that we're called after the test completes
7499
testRunner.OnScenarioEnd();
75100

76-
AsyncContext.Unregister();
101+
UnregisterAsyncTestExecutor();
77102
}
78103

79104
public void Given(string text, string multilineTextArg, Table tableArg)
80105
{
81-
AsyncContext.EnqueueWithNewContext(() => testRunner.Given(text, multilineTextArg, tableArg));
106+
AsyncTestExecutor.EnqueueWithNewContext(() => testRunner.Given(text, multilineTextArg, tableArg));
82107
}
83108

84109
public void When(string text, string multilineTextArg, Table tableArg)
85110
{
86-
AsyncContext.EnqueueWithNewContext(() => testRunner.When(text, multilineTextArg, tableArg));
111+
AsyncTestExecutor.EnqueueWithNewContext(() => testRunner.When(text, multilineTextArg, tableArg));
87112
}
88113

89114
public void Then(string text, string multilineTextArg, Table tableArg)
90115
{
91-
AsyncContext.EnqueueWithNewContext(() => testRunner.Then(text, multilineTextArg, tableArg));
116+
AsyncTestExecutor.EnqueueWithNewContext(() => testRunner.Then(text, multilineTextArg, tableArg));
92117
}
93118

94119
public void And(string text, string multilineTextArg, Table tableArg)
95120
{
96-
AsyncContext.EnqueueWithNewContext(() => testRunner.And(text, multilineTextArg, tableArg));
121+
AsyncTestExecutor.EnqueueWithNewContext(() => testRunner.And(text, multilineTextArg, tableArg));
97122
}
98123

99124
public void But(string text, string multilineTextArg, Table tableArg)
100125
{
101-
AsyncContext.EnqueueWithNewContext(() => testRunner.But(text, multilineTextArg, tableArg));
126+
AsyncTestExecutor.EnqueueWithNewContext(() => testRunner.But(text, multilineTextArg, tableArg));
102127
}
103128

104129
public void Pending()
105130
{
106-
AsyncContext.EnqueueWithNewContext(() => testRunner.Pending());
131+
AsyncTestExecutor.EnqueueWithNewContext(() => testRunner.Pending());
107132
}
108133
}
109134
}

Runtime/Async/IAsyncContextImpl.cs renamed to Runtime/Async/IAsyncTestExecutor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22

3-
namespace TechTalk.SpecFlow
3+
namespace TechTalk.SpecFlow.Async
44
{
55
/// <summary>
66
/// Intended for framework use.
@@ -16,7 +16,7 @@ namespace TechTalk.SpecFlow
1616
/// implemented by the feature test classes.
1717
/// </para>
1818
/// </remarks>
19-
public interface IAsyncContextImpl
19+
public interface IAsyncTestExecutor : IDisposable
2020
{
2121
/// <summary>
2222
/// Enqueues an asynchronous and non-blocking wait for at least the given time before continuing.
@@ -84,8 +84,8 @@ public interface IAsyncContextImpl
8484
/// </para>
8585
/// <para>
8686
/// Used by the <see cref="AsyncTestRunner"/> during <see cref="ITestRunner.CollectScenarioErrors"/>.
87-
/// Marked as internal abstract rather than implemented on <see cref="IAsyncContextImpl"/>
88-
/// because <see cref="IAsyncContextImpl"/> is public (so others can implement it) and
87+
/// Marked as internal abstract rather than implemented on <see cref="IAsyncTestExecutor"/>
88+
/// because <see cref="IAsyncTestExecutor"/> is public (so others can implement it) and
8989
/// we don't want people calling it unexpectedly.
9090
/// </para>
9191
/// </remarks>

Runtime/ObjectContainer.cs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Reflection;
4+
using TechTalk.SpecFlow.Async;
45
using TechTalk.SpecFlow.Bindings;
56
using TechTalk.SpecFlow.Configuration;
67
using TechTalk.SpecFlow.ErrorHandling;
@@ -39,13 +40,14 @@ private static RuntimeConfiguration GetConfiguration()
3940
private static ITestRunner syncTestRunner;
4041
private static ITestRunner asyncTestRunner;
4142

42-
public static ITestRunner CurrentTestRunner { get; set; }
43-
44-
internal static ITestRunner SyncTestRunner
45-
{
46-
get { return EnsureSyncTestRunner(Assembly.GetCallingAssembly()); }
47-
set { syncTestRunner = value; }
48-
}
43+
//TODO
44+
// public static ITestRunner CurrentTestRunner { get; set; }
45+
//
46+
// internal static ITestRunner SyncTestRunner
47+
// {
48+
// get { return EnsureSyncTestRunner(Assembly.GetCallingAssembly()); }
49+
// set { syncTestRunner = value; }
50+
// }
4951

5052
internal static ITestRunner EnsureSyncTestRunner(Assembly callingAssembly)
5153
{
@@ -58,11 +60,11 @@ internal static ITestRunner EnsureSyncTestRunner(Assembly callingAssembly)
5860
});
5961
}
6062

61-
internal static ITestRunner AsyncTestRunner
62-
{
63-
get { return EnsureAsyncTestRunner(Assembly.GetCallingAssembly()); }
64-
set { asyncTestRunner = value; }
65-
}
63+
// internal static ITestRunner AsyncTestRunner
64+
// {
65+
// get { return EnsureAsyncTestRunner(Assembly.GetCallingAssembly()); }
66+
// set { asyncTestRunner = value; }
67+
// }
6668

6769
internal static ITestRunner EnsureAsyncTestRunner(Assembly callingAssembly)
6870
{
@@ -150,12 +152,6 @@ private static void DisposeScenarioContext()
150152

151153
#endregion
152154

153-
#region AsyncContext
154-
155-
public static AsyncContext AsyncContext { get; internal set; }
156-
157-
#endregion
158-
159155
#region TraceListener
160156
private static ITraceListener traceListener = null;
161157

Runtime/ScenarioContext.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,18 @@ static public ScenarioContext Current
3535
internal List<string> MissingSteps { get; private set; }
3636
internal Stopwatch Stopwatch { get; private set; }
3737

38-
public ScenarioContext(ScenarioInfo scenarioInfo)
38+
internal ITestRunner TestRunner { get; private set; } //TODO: initialize
39+
40+
[Obsolete("eliminate this method when separating test runner from test execution engine")]
41+
internal void SetTestRunnerUnchecked(ITestRunner newTestRunner)
3942
{
43+
TestRunner = newTestRunner;
44+
}
45+
46+
internal ScenarioContext(ScenarioInfo scenarioInfo, ITestRunner testRunner)
47+
{
48+
TestRunner = testRunner;
49+
4050
Stopwatch = new Stopwatch();
4151
Stopwatch.Start();
4252

@@ -49,7 +59,7 @@ public ScenarioContext(ScenarioInfo scenarioInfo)
4959

5060
public void Pending()
5161
{
52-
ObjectContainer.CurrentTestRunner.Pending();
62+
TestRunner.Pending();
5363
}
5464

5565
private Dictionary<Type, object> bindingInstances = new Dictionary<Type, object>();

0 commit comments

Comments
 (0)