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

View File

@@ -71,7 +71,6 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.Expector = jRequire.Expector(j$);
j$.Expectation = jRequire.Expectation(j$);
j$.buildExpectationResult = jRequire.buildExpectationResult(j$);
j$.noopTimer = jRequire.noopTimer();
j$.JsApiReporter = jRequire.JsApiReporter(j$);
j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim(
j$
@@ -681,7 +680,7 @@ getJasmineRequireObj().Spec = function(j$) {
return true;
};
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
this.timer = attrs.timer || j$.noopTimer;
this.timer = attrs.timer || new j$.Timer();
if (!this.queueableFn.fn) {
this.pend();
@@ -746,6 +745,7 @@ getJasmineRequireObj().Spec = function(j$) {
fn: function(done) {
self.queueableFn.fn = null;
self.result.status = self.status(excluded, failSpecWithNoExp);
self.result.duration = self.timer.elapsed();
self.resultCallback(self.result, done);
}
};
@@ -761,7 +761,6 @@ getJasmineRequireObj().Spec = function(j$) {
self.onException.apply(self, arguments);
},
onComplete: function() {
self.result.duration = self.timer.elapsed();
onComplete(
self.result.status === 'failed' &&
new j$.StopExecutionError('spec failed')
@@ -1878,6 +1877,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: description,
parentSuite: currentDeclarationSuite,
timer: new j$.Timer(),
expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory,
@@ -2166,7 +2166,7 @@ getJasmineRequireObj().JsApiReporter = function(j$) {
* @hideconstructor
*/
function JsApiReporter(options) {
var timer = options.timer || j$.noopTimer,
var timer = options.timer || new j$.Timer(),
status = 'loaded';
this.started = false;
@@ -8246,7 +8246,7 @@ getJasmineRequireObj().Suite = function(j$) {
this.beforeAllFns = [];
this.afterAllFns = [];
this.timer = attrs.timer || j$.noopTimer;
this.timer = attrs.timer || new j$.Timer();
this.children = [];
@@ -8449,15 +8449,6 @@ getJasmineRequireObj().Timer = function() {
return Timer;
};
getJasmineRequireObj().noopTimer = function() {
return {
start: function() {},
elapsed: function() {
return 0;
}
};
};
getJasmineRequireObj().TreeProcessor = function() {
function TreeProcessor(attrs) {
var tree = attrs.tree,

View File

@@ -227,7 +227,7 @@ describe('Spec', function() {
passedExpectations: [],
deprecationWarnings: [],
pendingReason: '',
duration: null
duration: jasmine.any(Number)
},
'things'
);
@@ -273,21 +273,30 @@ describe('Spec', function() {
});
it('should report the duration of the test', function() {
var done = jasmine.createSpy('done callback'),
timer = jasmine.createSpyObj('timer', { start: null, elapsed: 77000 }),
var timer = jasmine.createSpyObj('timer', { start: null, elapsed: 77000 }),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') },
catchExceptions: function() {
return false;
},
resultCallback: function() {},
queueRunnerFactory: function(attrs) {
attrs.onComplete();
resultCallback: function(result) {
duration = result.duration;
},
queueRunnerFactory: function(config) {
config.queueableFns.forEach(function(qf) {
qf.fn();
});
config.cleanupFns.forEach(function(qf) {
qf.fn();
});
config.onComplete();
},
timer: timer
});
spec.execute(done);
expect(spec.result.duration).toBe(77000);
}),
duration = undefined;
spec.execute(function() {});
expect(duration).toBe(77000);
});
it('#status returns passing by default', function() {

View File

@@ -616,6 +616,58 @@ describe("Env integration", function() {
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) {

View File

@@ -952,6 +952,7 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: description,
parentSuite: currentDeclarationSuite,
timer: new j$.Timer(),
expectationFactory: expectationFactory,
asyncExpectationFactory: suiteAsyncExpectationFactory,
expectationResultFactory: expectationResultFactory,

View File

@@ -6,7 +6,7 @@ getJasmineRequireObj().JsApiReporter = function(j$) {
* @hideconstructor
*/
function JsApiReporter(options) {
var timer = options.timer || j$.noopTimer,
var timer = options.timer || new j$.Timer(),
status = 'loaded';
this.started = false;

View File

@@ -31,7 +31,7 @@ getJasmineRequireObj().Spec = function(j$) {
return true;
};
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
this.timer = attrs.timer || j$.noopTimer;
this.timer = attrs.timer || new j$.Timer();
if (!this.queueableFn.fn) {
this.pend();
@@ -96,6 +96,7 @@ getJasmineRequireObj().Spec = function(j$) {
fn: function(done) {
self.queueableFn.fn = null;
self.result.status = self.status(excluded, failSpecWithNoExp);
self.result.duration = self.timer.elapsed();
self.resultCallback(self.result, done);
}
};
@@ -111,7 +112,6 @@ getJasmineRequireObj().Spec = function(j$) {
self.onException.apply(self, arguments);
},
onComplete: function() {
self.result.duration = self.timer.elapsed();
onComplete(
self.result.status === 'failed' &&
new j$.StopExecutionError('spec failed')

View File

@@ -14,7 +14,7 @@ getJasmineRequireObj().Suite = function(j$) {
this.beforeAllFns = [];
this.afterAllFns = [];
this.timer = attrs.timer || j$.noopTimer;
this.timer = attrs.timer || new j$.Timer();
this.children = [];

View File

@@ -22,12 +22,3 @@ getJasmineRequireObj().Timer = function() {
return Timer;
};
getJasmineRequireObj().noopTimer = function() {
return {
start: function() {},
elapsed: function() {
return 0;
}
};
};

View File

@@ -49,7 +49,6 @@ var getJasmineRequireObj = (function(jasmineGlobal) {
j$.Expector = jRequire.Expector(j$);
j$.Expectation = jRequire.Expectation(j$);
j$.buildExpectationResult = jRequire.buildExpectationResult(j$);
j$.noopTimer = jRequire.noopTimer();
j$.JsApiReporter = jRequire.JsApiReporter(j$);
j$.asymmetricEqualityTesterArgCompatShim = jRequire.asymmetricEqualityTesterArgCompatShim(
j$