Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit 1a0c18f

Browse files
committed
Merge branch 'release/0.7.0' into production
2 parents f7172f7 + d17c293 commit 1a0c18f

File tree

69 files changed

+1125
-592
lines changed

Some content is hidden

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

69 files changed

+1125
-592
lines changed

CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<RootNamespace>CSF.Screenplay.NUnit</RootNamespace>
99
<AssemblyName>CSF.Screenplay.NUnit</AssemblyName>
1010
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
11-
<ReleaseVersion>0.6.0</ReleaseVersion>
11+
<ReleaseVersion>0.7.0</ReleaseVersion>
1212
</PropertyGroup>
1313
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1414
<DebugSymbols>true</DebugSymbols>

CSF.Screenplay.NUnit/CSF.Screenplay.NUnit.nuspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>CSF.Screenplay.NUnit</id>
5-
<version>0.6.0-alpha</version>
5+
<version>0.7.0-alpha</version>
66
<title>CSF.Screenplay.NUnit</title>
77
<authors>CSF Software Ltd</authors>
88
<licenseUrl>https://opensource.org/licenses/MIT</licenseUrl>
@@ -13,7 +13,7 @@
1313
<dependencies>
1414
<dependency id="CSF.Reflection" version="[1.0.1,2.0.0)" />
1515
<dependency id="NUnit" version="[3.4.0,4.0.0)" />
16-
<dependency id="CSF.Screenplay" version="0.6.0-alpha" />
16+
<dependency id="CSF.Screenplay" version="0.7.0-alpha" />
1717
</dependencies>
1818
</metadata>
1919
<files>

CSF.Screenplay.NUnit/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
1818
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
1919

20-
[assembly: AssemblyVersion("0.6.0.0")]
20+
[assembly: AssemblyVersion("0.7.0.0")]
2121

2222
// The following attributes are used to specify the signing key for the assembly,
2323
// if desired. See the Mono documentation for more information about signing.

CSF.Screenplay.NUnit/ScenarioAdapter.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,27 @@ public ScenarioAdapter(ITest featureSuite, IMethodInfo scenarioMethod, IScreenpl
112112
}
113113

114114
/// <summary>
115-
/// Gets the success of a single test.
115+
/// Gets a value which indicates whether a single test passed.
116116
/// </summary>
117117
/// <returns><c>true</c>, if the test was successful, <c>false</c> otherwise.</returns>
118118
/// <param name="test">Test.</param>
119119
public static bool GetSuccess(ITest test)
120120
{
121-
// TODO: #96 - is this call to TestContext.CurrentContext thread-safe or not?
122121
var result = TestContext.CurrentContext.Result;
123122
return result.Outcome.Status == TestStatus.Passed;
124123
}
125124

125+
/// <summary>
126+
/// Gets a value which indicates whether a single test failed.
127+
/// </summary>
128+
/// <returns><c>true</c>, if the test was a failure, <c>false</c> otherwise.</returns>
129+
/// <param name="test">Test.</param>
130+
public static bool GetFailure(ITest test)
131+
{
132+
var result = TestContext.CurrentContext.Result;
133+
return result.Outcome.Status == TestStatus.Failed;
134+
}
135+
126136
/// <summary>
127137
/// Gets an <see cref="IScreenplayScenario"/> from a given NUnit test instance.
128138
/// </summary>

CSF.Screenplay.NUnit/ScreenplayAttribute.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ public void BeforeTest(ITest test)
4545
public void AfterTest(ITest test)
4646
{
4747
var scenario = ScenarioAdapter.GetScenario(test);
48-
var success = ScenarioAdapter.GetSuccess(test);
48+
var outcome = GetOutcome(test);
4949
var integration = integrationReader.GetIntegration(test);
50-
integration.AfterScenario(scenario, success);
50+
integration.AfterScenario(scenario, outcome);
5151
}
5252

5353
/// <summary>
@@ -63,6 +63,17 @@ public IEnumerable<TestMethod> BuildFrom(IMethodInfo method, Test suite)
6363
return BuildFrom(method, suite, scenario);
6464
}
6565

66+
bool? GetOutcome(ITest test)
67+
{
68+
var success = ScenarioAdapter.GetSuccess(test);
69+
var failure = ScenarioAdapter.GetFailure(test);
70+
71+
if(success) return true;
72+
if(failure) return false;
73+
74+
return null;
75+
}
76+
6677
IEnumerable<TestMethod> BuildFrom(IMethodInfo method, Test suite, IScreenplayScenario scenario)
6778
{
6879
var builder = new NUnitTestCaseBuilder();

CSF.Screenplay.Reporting/Builders/PerformanceBuilder.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,18 @@ public Performance GetPerformance()
7979
Reportables.ToArray());
8080
}
8181

82-
Outcome GetOutcome()
82+
PerformanceOutcome GetOutcome()
8383
{
8484
if(IsFailure && Exception != null)
85-
return Outcome.FailureWithException;
85+
return PerformanceOutcome.FailureWithException;
8686

8787
if(IsFailure)
88-
return Outcome.Failure;
88+
return PerformanceOutcome.Failure;
8989

9090
if(HasResult)
91-
return Outcome.SuccessWithResult;
91+
return PerformanceOutcome.SuccessWithResult;
9292

93-
return Outcome.Success;
93+
return PerformanceOutcome.Success;
9494
}
9595

9696
/// <summary>
Lines changed: 58 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
4+
using System.Linq;
35
using CSF.Screenplay.Abilities;
46
using CSF.Screenplay.Actors;
57
using CSF.Screenplay.Reporting.Models;
@@ -11,10 +13,7 @@ namespace CSF.Screenplay.Reporting.Builders
1113
/// </summary>
1214
public class ReportBuilder
1315
{
14-
List<Models.Scenario> scenarios;
15-
Models.Scenario currentScenario;
16-
PerformanceType currentPerformanceType;
17-
Stack<PerformanceBuilder> builderStack;
16+
readonly ConcurrentDictionary<Guid, ScenarioBuilder> scenarios;
1817

1918
/// <summary>
2019
/// Begins reporting upon a new scenario.
@@ -23,112 +22,113 @@ public class ReportBuilder
2322
/// <param name="featureName">The feature name.</param>
2423
/// <param name="idName">The uniquely identifying name for the test.</param>
2524
/// <param name="featureId">The uniquely identifying name for the feature.</param>
26-
public void BeginNewScenario(string idName, string friendlyName = null, string featureName = null, string featureId = null)
25+
/// <param name="scenarioId">The screenplay scenario identity.</param>
26+
public void BeginNewScenario(string idName,
27+
string friendlyName,
28+
string featureName,
29+
string featureId,
30+
Guid scenarioId)
2731
{
28-
currentScenario = new Models.Scenario(idName, friendlyName, featureName, featureId);
29-
scenarios.Add(currentScenario);
30-
currentPerformanceType = PerformanceType.Unspecified;
31-
builderStack.Clear();
32+
var success = scenarios.TryAdd(scenarioId, new ScenarioBuilder(idName, friendlyName, featureName, featureId));
33+
if(!success)
34+
throw new InvalidOperationException("The current scenario already exists in the current builder instance");
3235
}
3336

3437
/// <summary>
3538
/// Reports the end of a scenario.
3639
/// </summary>
37-
/// <param name="isSuccess">Optional. If set to <c>false</c> then the scenario is marked as a failure.</param>
38-
public void EndScenario(bool isSuccess = true)
40+
/// <param name="outcome">If set to <c>false</c> then the scenario is marked as a failure.</param>
41+
/// <param name="scenarioId">The screenplay scenario identity.</param>
42+
public void EndScenario(bool? outcome,
43+
Guid scenarioId)
3944
{
40-
EnsureCurrentScenario();
41-
42-
if(!isSuccess)
43-
currentScenario.IsFailure = true;
44-
45-
currentScenario = null;
46-
builderStack.Clear();
45+
var scenario = GetScenario(scenarioId);
46+
scenario.Finalise(outcome);
4747
}
4848

4949
/// <summary>
5050
/// Begins reporting of a new performable.
5151
/// </summary>
5252
/// <param name="actor">Actor.</param>
5353
/// <param name="performable">Performable.</param>
54-
public void BeginPerformance(INamed actor, Performables.IPerformable performable)
54+
/// <param name="scenarioId">The screenplay scenario identity.</param>
55+
public void BeginPerformance(INamed actor, Performables.IPerformable performable,
56+
Guid scenarioId)
5557
{
56-
EnsureCurrentScenario();
57-
58-
var builder = new PerformanceBuilder {
59-
Performable = performable,
60-
Actor = actor,
61-
PerformanceType = currentPerformanceType,
62-
};
63-
AddPerformanceBuilder(builder);
58+
var scenario = GetScenario(scenarioId);
59+
scenario.BeginPerformance(actor, performable);
6460
}
6561

6662
/// <summary>
6763
/// Begins reporting of a performance of a given type.
6864
/// </summary>
6965
/// <param name="performanceType">Performance type.</param>
70-
public void BeginPerformanceType(PerformanceType performanceType)
66+
/// <param name="scenarioId">The screenplay scenario identity.</param>
67+
public void BeginPerformanceType(PerformanceType performanceType,
68+
Guid scenarioId)
7169
{
72-
EnsureCurrentScenario();
73-
74-
performanceType.RequireDefinedValue(nameof(performanceType));
75-
currentPerformanceType = performanceType;
70+
var scenario = GetScenario(scenarioId);
71+
scenario.BeginPerformanceType(performanceType);
7672
}
7773

7874
/// <summary>
7975
/// Records that the current performable has received a result.
8076
/// </summary>
8177
/// <param name="performable">Performable.</param>
8278
/// <param name="result">Result.</param>
83-
public void RecordResult(Performables.IPerformable performable, object result)
79+
/// <param name="scenarioId">The screenplay scenario identity.</param>
80+
public void RecordResult(Performables.IPerformable performable, object result,
81+
Guid scenarioId)
8482
{
85-
var builder = PeekCurrentBuilder(performable);
86-
87-
builder.HasResult = true;
88-
builder.Result = result;
83+
var scenario = GetScenario(scenarioId);
84+
scenario.RecordResult(performable, result);
8985
}
9086

9187
/// <summary>
9288
/// Records that the current performable has failed with an exception.
9389
/// </summary>
9490
/// <param name="performable">Performable.</param>
9591
/// <param name="exception">Exception.</param>
96-
public void RecordFailure(Performables.IPerformable performable, Exception exception)
92+
/// <param name="scenarioId">The screenplay scenario identity.</param>
93+
public void RecordFailure(Performables.IPerformable performable, Exception exception,
94+
Guid scenarioId)
9795
{
98-
var builder = PeekCurrentBuilder(performable);
99-
100-
builder.IsFailure = true;
101-
builder.Exception = exception;
102-
103-
FinalisePerformance(performable);
96+
var scenario = GetScenario(scenarioId);
97+
scenario.RecordFailure(performable, exception);
10498
}
10599

106100
/// <summary>
107101
/// Records that the current performable has completed successfully.
108102
/// </summary>
109103
/// <param name="performable">Performable.</param>
110-
public void RecordSuccess(Performables.IPerformable performable)
104+
/// <param name="scenarioId">The screenplay scenario identity.</param>
105+
public void RecordSuccess(Performables.IPerformable performable,
106+
Guid scenarioId)
111107
{
112-
FinalisePerformance(performable);
108+
var scenario = GetScenario(scenarioId);
109+
scenario.RecordSuccess(performable);
113110
}
114111

115112
/// <summary>
116113
/// Ends the performance of the current type.
117114
/// </summary>
118-
public void EndPerformanceType()
115+
public void EndPerformanceType(Guid scenarioId)
119116
{
120-
currentPerformanceType = PerformanceType.Unspecified;
117+
var scenario = GetScenario(scenarioId);
118+
scenario.EndPerformanceType();
121119
}
122120

123121
/// <summary>
124122
/// Reports that the given actor has gained the given ability.
125123
/// </summary>
126124
/// <param name="actor">Actor.</param>
127125
/// <param name="ability">Ability.</param>
128-
public void GainAbility(INamed actor, IAbility ability)
126+
/// <param name="scenarioId">The screenplay scenario identity.</param>
127+
public void GainAbility(INamed actor, IAbility ability,
128+
Guid scenarioId)
129129
{
130-
var item = new GainAbility(actor, Outcome.Success, ability, currentPerformanceType);
131-
AddReportable(item);
130+
var scenario = GetScenario(scenarioId);
131+
scenario.GainAbility(actor, ability);
132132
}
133133

134134
/// <summary>
@@ -137,86 +137,24 @@ public void GainAbility(INamed actor, IAbility ability)
137137
/// <returns>The report.</returns>
138138
public Report GetReport()
139139
{
140-
return new Report(scenarios.ToArray());
141-
}
142-
143-
void AddReportable(Reportable item)
144-
{
145-
if(item == null)
146-
throw new ArgumentNullException(nameof(item));
147-
148-
var list = GetCurrentReportables();
149-
list.Add(item);
150-
}
151-
152-
void FinalisePerformance(Performables.IPerformable performable)
153-
{
154-
var builder = PopCurrentBuilder(performable);
155-
var performance = builder.GetPerformance();
156-
AddReportable(performance);
157-
}
158-
159-
void AddPerformanceBuilder(PerformanceBuilder builder)
160-
{
161-
if(builder == null)
162-
throw new ArgumentNullException(nameof(builder));
163-
164-
builderStack.Push(builder);
165-
}
166-
167-
PerformanceBuilder PopCurrentBuilder(Performables.IPerformable expectedPerformable)
168-
{
169-
PeekCurrentBuilder(expectedPerformable);
170-
return builderStack.Pop();
140+
return new Report(scenarios.Values.Select(x => x.GetScenario()).ToArray());
171141
}
172142

173-
PerformanceBuilder PeekCurrentBuilder(Performables.IPerformable expectedPerformable = null)
143+
ScenarioBuilder GetScenario(Guid identity)
174144
{
175-
if(builderStack.Count == 0 && expectedPerformable == null)
176-
return null;
177-
else if(builderStack.Count == 0)
178-
throw new InvalidOperationException("An expected performable was specified but the builder stack was empty, this is not permitted.");
179-
180-
var current = builderStack.Peek();
181-
182-
if(expectedPerformable == null)
183-
return current;
145+
ScenarioBuilder scenario;
146+
if(!scenarios.TryGetValue(identity, out scenario))
147+
throw new InvalidOperationException("There is no matching scenario in the current builder.");
184148

185-
if(!ReferenceEquals(expectedPerformable, current.Performable))
186-
{
187-
throw new ArgumentException("The expected performable must be the same as the current builder.",
188-
nameof(expectedPerformable));
189-
}
190-
191-
return current;
192-
}
193-
194-
IList<Reportable> GetCurrentReportables()
195-
{
196-
var currentBuilder = PeekCurrentBuilder();
197-
if(currentBuilder != null)
198-
return currentBuilder.Reportables;
199-
200-
if(currentScenario != null)
201-
return currentScenario.Reportables;
202-
203-
throw new InvalidOperationException("Cannot get the current reportables, there must be either a current builder or a current scenario.");
204-
}
205-
206-
void EnsureCurrentScenario()
207-
{
208-
if(ReferenceEquals(currentScenario, null))
209-
throw new InvalidOperationException("There must be a current scenario in order to report upon performables.");
149+
return scenario;
210150
}
211151

212152
/// <summary>
213153
/// Initializes a new instance of the <see cref="ReportBuilder"/> class.
214154
/// </summary>
215155
public ReportBuilder()
216156
{
217-
scenarios = new List<Models.Scenario>();
218-
builderStack = new Stack<PerformanceBuilder>();
219-
currentPerformanceType = PerformanceType.Unspecified;
157+
scenarios = new ConcurrentDictionary<Guid,ScenarioBuilder>();
220158
}
221159
}
222160
}

0 commit comments

Comments
 (0)