Correctly report spec and suite duration

Previously, suite duration was always reported as 0 and spec duration
was always reported as null. Suites always used a no-op timer, and
specs set their result.duration after the result had already been sent
to reporters.

Fixes #1676.
This commit is contained in:
Steve Gravrock
2020-02-22 13:54:24 -08:00
parent a6a9550d1e
commit 93ad31e0af
9 changed files with 80 additions and 37 deletions
+5 -14
View File
@@ -71,7 +71,6 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.Expector = jRequire.Expector(j$); j$.Expector = jRequire.Expector(j$);
j$.Expectation = jRequire.Expectation(j$); j$.Expectation = jRequire.Expectation(j$);
j$.buildExpectationResult = jRequire.buildExpectationResult(j$); j$.buildExpectationResult = jRequire.buildExpectationResult(j$);
j$.noopTimer = jRequire.noopTimer();
j$.JsApiReporter = jRequire.JsApiReporter(j$); j$.JsApiReporter = jRequire.JsApiReporter(j$);
j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim( j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim(
j$ j$
@@ -681,7 +680,7 @@ getJasmineRequireObj().Spec = function(j$) {
return true; return true;
}; };
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
this.timer = attrs.timer || j$.noopTimer; this.timer = attrs.timer || new j$.Timer();
if (!this.queueableFn.fn) { if (!this.queueableFn.fn) {
this.pend(); this.pend();
@@ -746,6 +745,7 @@ getJasmineRequireObj().Spec = function(j$) {
fn: function(done) { fn: function(done) {
self.queueableFn.fn = null; self.queueableFn.fn = null;
self.result.status = self.status(excluded, failSpecWithNoExp); self.result.status = self.status(excluded, failSpecWithNoExp);
self.result.duration = self.timer.elapsed();
self.resultCallback(self.result, done); self.resultCallback(self.result, done);
} }
}; };
@@ -761,7 +761,6 @@ getJasmineRequireObj().Spec = function(j$) {
self.onException.apply(self, arguments); self.onException.apply(self, arguments);
}, },
onComplete: function() { onComplete: function() {
self.result.duration = self.timer.elapsed();
onComplete( onComplete(
self.result.status === 'failed' && self.result.status === 'failed' &&
new j$.StopExecutionError('spec failed') new j$.StopExecutionError('spec failed')
@@ -1878,6 +1877,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(), id: getNextSuiteId(),
description: description, description: description,
parentSuite: currentDeclarationSuite, parentSuite: currentDeclarationSuite,
timer: new j$.Timer(),
expectationFactory: expectationFactory, expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory, asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory, expectationResultFactory: expectationResultFactory,
@@ -2166,7 +2166,7 @@ getJasmineRequireObj().JsApiReporter = function(j$) {
* @hideconstructor * @hideconstructor
*/ */
function JsApiReporter(options) { function JsApiReporter(options) {
var timer = options.timer || j$.noopTimer, var timer = options.timer || new j$.Timer(),
status = 'loaded'; status = 'loaded';
this.started = false; this.started = false;
@@ -8246,7 +8246,7 @@ getJasmineRequireObj().Suite = function(j$) {
this.beforeAllFns = []; this.beforeAllFns = [];
this.afterAllFns = []; this.afterAllFns = [];
this.timer = attrs.timer || j$.noopTimer; this.timer = attrs.timer || new j$.Timer();
this.children = []; this.children = [];
@@ -8449,15 +8449,6 @@ getJasmineRequireObj().Timer = function() {
return Timer; return Timer;
}; };
getJasmineRequireObj().noopTimer = function() {
return {
start: function() {},
elapsed: function() {
return 0;
}
};
};
getJasmineRequireObj().TreeProcessor = function() { getJasmineRequireObj().TreeProcessor = function() {
function TreeProcessor(attrs) { function TreeProcessor(attrs) {
var tree = attrs.tree, var tree = attrs.tree,
+18 -9
View File
@@ -227,7 +227,7 @@ describe('Spec', function() {
passedExpectations: [], passedExpectations: [],
deprecationWarnings: [], deprecationWarnings: [],
pendingReason: '', pendingReason: '',
duration: null duration: jasmine.any(Number)
}, },
'things' 'things'
); );
@@ -273,21 +273,30 @@ describe('Spec', function() {
}); });
it('should report the duration of the test', function() { it('should report the duration of the test', function() {
var done = jasmine.createSpy('done callback'), var timer = jasmine.createSpyObj('timer', { start: null, elapsed: 77000 }),
timer = jasmine.createSpyObj('timer', { start: null, elapsed: 77000 }),
spec = new jasmineUnderTest.Spec({ spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') }, queueableFn: { fn: jasmine.createSpy('spec body') },
catchExceptions: function() { catchExceptions: function() {
return false; return false;
}, },
resultCallback: function() {}, resultCallback: function(result) {
queueRunnerFactory: function(attrs) { duration = result.duration;
attrs.onComplete(); },
queueRunnerFactory: function(config) {
config.queueableFns.forEach(function(qf) {
qf.fn();
});
config.cleanupFns.forEach(function(qf) {
qf.fn();
});
config.onComplete();
}, },
timer: timer timer: timer
}); }),
spec.execute(done); duration = undefined;
expect(spec.result.duration).toBe(77000);
spec.execute(function() {});
expect(duration).toBe(77000);
}); });
it('#status returns passing by default', function() { it('#status returns passing by default', function() {
+52
View File
@@ -616,6 +616,58 @@ describe("Env integration", function() {
env.execute(); env.execute();
}); });
it('reports the duration of the suite', function(done) {
var duration;
env.addReporter({
suiteDone: function(result) {
expect(duration).toBeUndefined();
duration = result.duration;
},
jasmineDone: function() {
expect(duration).toBeGreaterThanOrEqual(10);
done();
}
});
env.describe('my suite', function() {
env.it('takes time', function(done) {
// We can't just use the mock clock here because the timer is designed
// to record real time even when the mock clock is installed.
setTimeout(done, 10);
})
});
env.execute();
});
});
describe('specDone reporting', function() {
it('reports the duration of the spec', function(done) {
var duration;
env.addReporter({
specDone: function(result) {
expect(duration).toBeUndefined();
duration = result.duration;
},
jasmineDone: function() {
expect(duration).toBeGreaterThanOrEqual(10);
done();
}
});
env.describe('my suite', function() {
env.it('takes time', function(done) {
// We can't just use the mock clock here because the timer is designed
// to record real time even when the mock clock is installed.
setTimeout(done, 10);
})
});
env.execute();
});
}); });
it('reports expectation failures in global beforeAll', function(done) { it('reports expectation failures in global beforeAll', function(done) {
+1
View File
@@ -952,6 +952,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(), id: getNextSuiteId(),
description: description, description: description,
parentSuite: currentDeclarationSuite, parentSuite: currentDeclarationSuite,
timer: new j$.Timer(),
expectationFactory: expectationFactory, expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory, asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory, expectationResultFactory: expectationResultFactory,
+1 -1
View File
@@ -6,7 +6,7 @@ getJasmineRequireObj().JsApiReporter = function(j$) {
* @hideconstructor * @hideconstructor
*/ */
function JsApiReporter(options) { function JsApiReporter(options) {
var timer = options.timer || j$.noopTimer, var timer = options.timer || new j$.Timer(),
status = 'loaded'; status = 'loaded';
this.started = false; this.started = false;
+2 -2
View File
@@ -31,7 +31,7 @@ getJasmineRequireObj().Spec = function(j$) {
return true; return true;
}; };
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
this.timer = attrs.timer || j$.noopTimer; this.timer = attrs.timer || new j$.Timer();
if (!this.queueableFn.fn) { if (!this.queueableFn.fn) {
this.pend(); this.pend();
@@ -96,6 +96,7 @@ getJasmineRequireObj().Spec = function(j$) {
fn: function(done) { fn: function(done) {
self.queueableFn.fn = null; self.queueableFn.fn = null;
self.result.status = self.status(excluded, failSpecWithNoExp); self.result.status = self.status(excluded, failSpecWithNoExp);
self.result.duration = self.timer.elapsed();
self.resultCallback(self.result, done); self.resultCallback(self.result, done);
} }
}; };
@@ -111,7 +112,6 @@ getJasmineRequireObj().Spec = function(j$) {
self.onException.apply(self, arguments); self.onException.apply(self, arguments);
}, },
onComplete: function() { onComplete: function() {
self.result.duration = self.timer.elapsed();
onComplete( onComplete(
self.result.status === 'failed' && self.result.status === 'failed' &&
new j$.StopExecutionError('spec failed') new j$.StopExecutionError('spec failed')
+1 -1
View File
@@ -14,7 +14,7 @@ getJasmineRequireObj().Suite = function(j$) {
this.beforeAllFns = []; this.beforeAllFns = [];
this.afterAllFns = []; this.afterAllFns = [];
this.timer = attrs.timer || j$.noopTimer; this.timer = attrs.timer || new j$.Timer();
this.children = []; this.children = [];
-9
View File
@@ -22,12 +22,3 @@ getJasmineRequireObj().Timer = function() {
return Timer; return Timer;
}; };
getJasmineRequireObj().noopTimer = function() {
return {
start: function() {},
elapsed: function() {
return 0;
}
};
};
-1
View File
@@ -49,7 +49,6 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.Expector = jRequire.Expector(j$); j$.Expector = jRequire.Expector(j$);
j$.Expectation = jRequire.Expectation(j$); j$.Expectation = jRequire.Expectation(j$);
j$.buildExpectationResult = jRequire.buildExpectationResult(j$); j$.buildExpectationResult = jRequire.buildExpectationResult(j$);
j$.noopTimer = jRequire.noopTimer();
j$.JsApiReporter = jRequire.JsApiReporter(j$); j$.JsApiReporter = jRequire.JsApiReporter(j$);
j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim( j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim(
j$ j$