Skip to content

Commit 634e3f3

Browse files
authored
Merge pull request #327 from csf-dev:craigfowler/issue325
Errors now include the report text
2 parents 57a778d + 3420506 commit 634e3f3

5 files changed

Lines changed: 55 additions & 9 deletions

File tree

CSF.Screenplay/Reporting/JsonScreenplayReporter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ void OnRecordAsset(object sender, PerformableAssetEventArgs e)
118118
=> GetPerformanceBuilder(e).RecordAssetForCurrentPerformable(e.FilePath, e.FileSummary);
119119

120120
void OnPerformableFailed(object sender, PerformableFailureEventArgs e)
121-
=> GetPerformanceBuilder(e).RecordFailureForCurrentPerformable(e.Exception);
121+
=> GetPerformanceBuilder(e).RecordFailureForCurrentPerformable(e.Exception, e.Performable, e.Actor);
122122

123123
void OnPerformableResult(object sender, PerformableResultEventArgs e)
124124
=> GetPerformanceBuilder(e).RecordResultForCurrentPerformable(e.Result);

CSF.Screenplay/Reporting/PerformanceReportBuilder.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ public void SpotlightTurnedOff()
169169
/// <param name="actor">The actor executing the performable</param>
170170
/// <param name="performancePhase">The performance phase in which the performable occurs</param>
171171
/// <seealso cref="EndPerformable(object, Actor)"/>
172-
/// <seealso cref="RecordFailureForCurrentPerformable(Exception)"/>
172+
/// <seealso cref="RecordFailureForCurrentPerformable(Exception,object,Actor)"/>
173173
public void BeginPerformable(object performable, Actor actor, string performancePhase)
174174
{
175175
var performableReport = new PerformableReport
@@ -239,7 +239,7 @@ public void RecordResultForCurrentPerformable(object result)
239239
public void EndPerformable(object performable, Actor actor)
240240
{
241241
CurrentPerformable.Report = performable is ICanReport reporter
242-
? reporter.GetReportFragment(actor, formatter).FormattedFragment
242+
? TryGetReport(reporter, actor, formatter)
243243
: string.Format(ReportStrings.FallbackReportFormat, actor.Name, performable.GetType().FullName);
244244
CurrentPerformable.Ended = reportTimer.GetCurrentTime();
245245
performableStack.Pop();
@@ -257,12 +257,25 @@ public void EndPerformable(object performable, Actor actor)
257257
/// </para>
258258
/// </remarks>
259259
/// <param name="exception">The exception which lead to the failure</param>
260-
public void RecordFailureForCurrentPerformable(Exception exception)
260+
/// <param name="performable">The performable which is ending</param>
261+
/// <param name="actor">The actor which was executing the performable</param>
262+
public void RecordFailureForCurrentPerformable(Exception exception, object performable, Actor actor)
261263
{
262264
CurrentPerformable.Exception = exception.ToString();
263265
CurrentPerformable.ExceptionIsFromConsumedPerformable = exception is PerformableException;
264-
CurrentPerformable.Ended = reportTimer.GetCurrentTime();
265-
performableStack.Pop();
266+
EndPerformable(performable, actor);
267+
}
268+
269+
static string TryGetReport(ICanReport reporter, Actor actor, IFormatsReportFragment formatter)
270+
{
271+
try
272+
{
273+
return reporter.GetReportFragment(actor, formatter).FormattedFragment;
274+
}
275+
catch
276+
{
277+
return ReportStrings.ReportErrorMessage;
278+
}
266279
}
267280

268281
#endregion

CSF.Screenplay/Resources/ReportStrings.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@ internal static class ReportStrings
2121

2222
/// <summary>Gets a fallback report format string for an actor performing a performable which does not implement <see cref="ICanReport"/>.</summary>
2323
internal static string FallbackReportFormat => resourceManager.GetString("FallbackReportFormat");
24+
25+
/// <summary>Gets a report text which is recorded when a performable raises an exception from <see cref="ICanReport.GetReportFragment(Actor, IFormatsReportFragment)"/>.</summary>
26+
internal static string ReportErrorMessage => resourceManager.GetString("ReportErrorMessage");
2427
}
2528
}

CSF.Screenplay/Resources/ReportStrings.restext

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ ActorCreatedFormat = {0} joined the performance
22
ActorGainedAbilityFormat = {0} is able to {1}
33
ActorSpotlitFormat = {0} was put into the spotlight
44
SpotlightTurnedOff = The spotlight was turned off
5-
FallbackReportFormat = {0} performed {1}
5+
FallbackReportFormat = {0} performed {1}
6+
ReportErrorMessage = An unexpected error occurred getting the report text for this performable

Tests/CSF.Screenplay.Tests/Reporting/PerformanceReportBuilderTests.cs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,41 @@ public void RecordFailureForCurrentPerformableShouldAddTheExceptionStringToTheRe
195195
string performancePhase)
196196
{
197197
sut.BeginPerformable(performable, actor, performancePhase);
198-
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"));
198+
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"), performable, actor);
199199
var report = sut.GetReport(outcome);
200200
Assert.That(report.Reportables,
201201
Has.One.Matches<PerformableReport>(x => x.Exception.Contains("An error occurred") && x.ExceptionIsFromConsumedPerformable == false));
202202
}
203203

204+
[Test, AutoMoqData]
205+
public void RecordFailureForCurrentPerformableShouldSetTheReportString(PerformanceReportBuilder sut,
206+
[NamedActor("Joe")] Actor actor,
207+
bool? outcome,
208+
string performable,
209+
string performancePhase)
210+
{
211+
sut.BeginPerformable(performable, actor, performancePhase);
212+
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"), performable, actor);
213+
var report = sut.GetReport(outcome);
214+
Assert.That(report.Reportables,
215+
Has.One.Matches<PerformableReport>(x => x.Report != null));
216+
}
217+
218+
[Test, AutoMoqData]
219+
public void RecordFailureForCurrentPerformableShouldUseAFallbackReportIfGettingTheReportThrows(PerformanceReportBuilder sut,
220+
[NamedActor("Joe")] Actor actor,
221+
bool? outcome,
222+
ICanReport performable,
223+
string performancePhase)
224+
{
225+
Mock.Get(performable).Setup(x => x.GetReportFragment(actor, It.IsAny<IFormatsReportFragment>())).Throws<InvalidOperationException>();
226+
sut.BeginPerformable(performable, actor, performancePhase);
227+
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"), performable, actor);
228+
var report = sut.GetReport(outcome);
229+
Assert.That(report.Reportables,
230+
Has.One.Matches<PerformableReport>(x => x.Report == "An unexpected error occurred getting the report text for this performable"));
231+
}
232+
204233
[Test, AutoMoqData]
205234
public void RecordFailureForCurrentPerformableShouldSetExceptionIsFromConsumedPerformableToTrueIfTheExceptionIsPerformableException(PerformanceReportBuilder sut,
206235
[NamedActor("Joe")] Actor actor,
@@ -209,7 +238,7 @@ public void RecordFailureForCurrentPerformableShouldSetExceptionIsFromConsumedPe
209238
string performancePhase)
210239
{
211240
sut.BeginPerformable(performable, actor, performancePhase);
212-
sut.RecordFailureForCurrentPerformable(new PerformableException("An error occurred"));
241+
sut.RecordFailureForCurrentPerformable(new PerformableException("An error occurred"), performable, actor);
213242
var report = sut.GetReport(outcome);
214243
Assert.That(report.Reportables,
215244
Has.One.Matches<PerformableReport>(x => x.Exception.Contains("An error occurred") && x.ExceptionIsFromConsumedPerformable == true));

0 commit comments

Comments
 (0)