Skip to content
Permalink
Browse files
fix(serenity-bdd): reports are correctly stored to disk
SerenityBDDReporter used to generate the reports upon a TestRunFinished event, which is too late in
the process and doesn't leave enough time for them to be saved by the ArtifactArchiver. Introducing
a new event TestRunFinishes that occurs before TestRunFinished and generating the reports upon it
helps to synchronise the storage correctly. Test runner adapters now have to: 1) emit
TestRunFinishes when the test suite is about to complete, 2) wait for the next cue, 3) emit
TestRunFinished
  • Loading branch information
jan-molak committed Jan 27, 2020
1 parent 9230fb2 commit c050e2fef0952d530394304619b42ee692f31584
@@ -1,6 +1,6 @@
Feature: Calculations API

Scenario Outline: Calculates result of an expression
Scenario Outline: Calculates result of basic expressions

When Apisitt asks for the following calculation: <expression>
Then he should get a result of <expected_result>
@@ -13,3 +13,8 @@ Feature: Calculations API
| 2 - 3 | -1 | Subtraction |
| 2 * 5 | 10 | Multiplication |
| 5 / 2 | 2.5 | Division |

Scenario: Recognises order of operations

When Apisitt asks for the following calculation: 2 + 2 * 2
Then he should get a result of 6
@@ -0,0 +1,21 @@
import { Timestamp } from '../model';
import { DomainEvent } from './DomainEvent';

/**
* @desc
* Emitted when the last test in the test suite has finished running
* and it's time for any last-minute reporting to take place.
*/
export class TestRunFinishes extends DomainEvent {
static fromJSON(v: string) {
return new TestRunFinishes(
Timestamp.fromJSON(v as string),
);
}

constructor(
timestamp?: Timestamp,
) {
super(timestamp);
}
}
@@ -25,4 +25,5 @@ export * from './TaskFinished';
export * from './TestSuiteStarts';
export * from './TestSuiteFinished';
export * from './TestRunFinished';
export * from './TestRunFinishes';
export * from './TestRunnerDetected';
@@ -88,6 +88,8 @@ export = function ({ serenity, notifier, loader, cache }: Dependencies) {
});

this.registerHandler('AfterFeatures', (features, callback) => {
notifier.testRunFinishes();

serenity.waitForNextCue()
.then(() => notifier.testRunFinished())
.then(() => callback(), error => callback(error));
@@ -11,6 +11,8 @@ export = function (dependencies: Dependencies) {
});

AfterAll(function () {
dependencies.notifier.testRunFinishes();

return dependencies.serenity.waitForNextCue()
.then(() => {
dependencies.notifier.testRunFinished();
@@ -11,6 +11,8 @@ export = function (dependencies: Dependencies) {
});

AfterAll(function () {
dependencies.notifier.testRunFinishes();

return dependencies.serenity.waitForNextCue()
.then(() => {
dependencies.notifier.testRunFinished();
@@ -12,6 +12,7 @@ import {
TaskFinished,
TaskStarts,
TestRunFinished,
TestRunFinishes,
TestRunnerDetected,
} from '@serenity-js/core/lib/events';
import { ActivityDetails, CapabilityTag, Category, Description, FeatureTag, Name, Outcome, ScenarioDetails, Tag, ThemeTag } from '@serenity-js/core/lib/model';
@@ -96,6 +97,12 @@ export class Notifier {
);
}

testRunFinishes() {
this.emit(
new TestRunFinishes(this.serenity.currentTime()),
);
}

testRunFinished() {
this.emit(
new TestRunFinished(this.serenity.currentTime()),
@@ -8,6 +8,7 @@ import {
TaskFinished,
TaskStarts,
TestRunFinished,
TestRunFinishes,
TestRunnerDetected,
TestSuiteFinished,
TestSuiteStarts,
@@ -16,7 +17,8 @@ import { ErrorSerialiser, FileSystemLocation } from '@serenity-js/core/lib/io';
import {
ActivityDetails,
Category,
CorrelationId, ExecutionCompromised,
CorrelationId,
ExecutionCompromised,
ExecutionFailedWithAssertionError,
ExecutionFailedWithError,
ExecutionSkipped,
@@ -104,6 +106,8 @@ export class SerenityReporterForJasmine {
* @param {JasmineDoneInfo} suiteInfo
*/
jasmineDone(suiteInfo: JasmineDoneInfo) {
this.emit(new TestRunFinishes(this.serenity.currentTime()));

return this.serenity.waitForNextCue()
.then(() => {
this.emit(new TestRunFinished(this.serenity.currentTime()));
@@ -1,6 +1,6 @@
import { expect } from '@integration/testing-tools';
import { AssertionError, ImplementationPendingError, Stage, StageManager, TestCompromisedError } from '@serenity-js/core';
import { ArtifactGenerated, SceneFinished, SceneStarts, TestRunFinished, TestRunnerDetected } from '@serenity-js/core/lib/events';
import { ArtifactGenerated, SceneFinished, SceneStarts, TestRunFinishes, TestRunnerDetected } from '@serenity-js/core/lib/events';
import { FileSystemLocation, Path } from '@serenity-js/core/lib/io';
import {
Category,
@@ -68,7 +68,7 @@ describe('SerenityBDDReporter', () => {
given(reporter).isNotifiedOfFollowingEvents(
new SceneStarts(defaultCardScenario),
new SceneFinished(defaultCardScenario, new ExecutionSuccessful()),
new TestRunFinished(),
new TestRunFinishes(),
);

expect(stageManager.notifyOf.callCount).to.equal(1);
@@ -81,7 +81,7 @@ describe('SerenityBDDReporter', () => {
* @test {SceneStarts}
* @test {SceneFinished}
* @test {ExecutionSuccessful}
* @test {TestRunFinished}
* @test {TestRunFinishes}
*/
it('is a valid artifact', () => {
expect(artifact).to.be.instanceOf(TestReport);
@@ -94,7 +94,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
* @test {ExecutionIgnored}
*/
@@ -104,7 +104,7 @@ describe('SerenityBDDReporter', () => {
new SceneFinished(defaultCardScenario, new ExecutionSuccessful()),
new SceneStarts(voucherScenario),
new SceneFinished(voucherScenario, new ExecutionIgnored()),
new TestRunFinished(),
new TestRunFinishes(),
);

expect(stageManager.notifyOf.callCount).to.equal(2);
@@ -129,7 +129,7 @@ describe('SerenityBDDReporter', () => {
given(reporter).isNotifiedOfFollowingEvents(
new SceneStarts(defaultCardScenario, startTime),
new SceneFinished(defaultCardScenario, new ExecutionSuccessful(), startTime.plus(scenarioDuration)),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -139,7 +139,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
*/
it('contains the id of the scenario', () => {
@@ -150,7 +150,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
*/
it('contains the name of the scenario', () => {
@@ -162,7 +162,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
*/
it('contains the start time of the scenario', () => {
@@ -173,7 +173,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
*/
it('contains the duration of the scenario', () => {
@@ -193,14 +193,14 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
*/
it('has finished with success', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionSuccessful()),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -212,14 +212,14 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ImplementationPending}
*/
it('hasn\'t been implemented yet', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ImplementationPending(new ImplementationPendingError('method missing'))),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -231,14 +231,14 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionIgnored}
*/
it('has been ignored', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionIgnored()),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -250,14 +250,14 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSkipped}
*/
it('has been skipped', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionSkipped()),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -269,7 +269,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionFailedWithAssertionError}
*/
it('has failed with an assertion error', () => {
@@ -278,7 +278,7 @@ describe('SerenityBDDReporter', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionFailedWithAssertionError(assertionError)),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -293,7 +293,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {TestCompromisedError}
* @test {ExecutionCompromised}
*/
@@ -304,7 +304,7 @@ describe('SerenityBDDReporter', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionCompromised(assertionError)),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -319,7 +319,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionFailedWithError}
*/
it('has failed with a non-assertion error', () => {
@@ -334,7 +334,7 @@ describe('SerenityBDDReporter', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionFailedWithError(error)),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -361,7 +361,7 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionCompromised}
*/
it('has been compromised', () => {
@@ -381,7 +381,7 @@ describe('SerenityBDDReporter', () => {

given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionCompromised(error)),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -427,14 +427,14 @@ describe('SerenityBDDReporter', () => {
* @test {TestRunnerDetected}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
*/
it('specifies the test runner', () => {
given(reporter).isNotifiedOfFollowingEvents(
new TestRunnerDetected(new Name('Cucumber')),
new SceneFinished(defaultCardScenario, new ExecutionSuccessful()),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);
@@ -446,13 +446,13 @@ describe('SerenityBDDReporter', () => {
* @test {SerenityBDDReporter}
* @test {SceneStarts}
* @test {SceneFinished}
* @test {TestRunFinished}
* @test {TestRunFinishes}
* @test {ExecutionSuccessful}
*/
it('specifies the user story covered', () => {
given(reporter).isNotifiedOfFollowingEvents(
new SceneFinished(defaultCardScenario, new ExecutionSuccessful()),
new TestRunFinished(),
new TestRunFinishes(),
);

report = stageManager.notifyOf.firstCall.lastArg.artifact.map(_ => _);

0 comments on commit c050e2f

Please sign in to comment.