Skip to content

Commit

Permalink
Use higher definition clock for test case run time measurement
Browse files Browse the repository at this point in the history
I noticed that fast tests always reported 0 as the duration, after some
debugging I noticed that we were not using the most accurate clock, so I
changed it for `performance.now` from perf hooks
https://nodejs.org/api/perf_hooks.html#perf_hooks_performance_now
As a side effect, that seems to be a monotonic clock, making the
measurements not affected by leap seconds
  • Loading branch information
joac committed Sep 1, 2021
1 parent 06be59a commit 7c16400
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ See the [migration guide](./docs/migration.md) for details of how to migrate fro
### Added

### Changed
* Use performance timers for test case duration measurement.

### Deprecated

Expand Down
13 changes: 13 additions & 0 deletions features/support/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import FakeTimers, { InstalledClock } from '@sinonjs/fake-timers'
import timeMethods from '../time'

import { After, Before, formatterHelpers } from '../../'
import fs from 'fs'
import fsExtra from 'fs-extra'
Expand Down Expand Up @@ -110,3 +113,13 @@ After(async function (this: World) {
)
}
})

let clock: InstalledClock

Before(async function () {
clock = FakeTimers.withGlobal(timeMethods).install()
})

After(async function () {
clock.uninstall()
})
52 changes: 26 additions & 26 deletions features/usage_formatter.feature
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ Feature: usage formatter
When I run cucumber-js with `--format usage`
Then it outputs the text:
"""
┌────────────────────┬──────────┬───────────────────────────────────────┐
│ Pattern / Text │ Duration │ Location │
├────────────────────┼──────────┼───────────────────────────────────────┤
│ step A │ <d>ms │ features/step_definitions/steps.js:3 │
│ step A │ <d>ms │ features/a.feature:3 │
├────────────────────┼──────────┼───────────────────────────────────────┤
│ /^(slow )?step B$/ │ <d>ms │ features/step_definitions/steps.js:4 │
│ slow step B │ <d>ms │ features/a.feature:5 │
│ step B │ <d>ms │ features/a.feature:4 │
├────────────────────┼──────────┼───────────────────────────────────────┤
│ step C │ <d>ms │ features/step_definitions/steps.js:11 │
│ step C │ <d>ms │ features/a.feature:6 │
├────────────────────┼──────────┼───────────────────────────────────────┤
│ step D │ UNUSED │ features/step_definitions/steps.js:12 │
└────────────────────┴──────────┴───────────────────────────────────────┘
┌────────────────────┬──────────────┬───────────────────────────────────────┐
│ Pattern / Text │ Duration │ Location │
├────────────────────┼──────────────┼───────────────────────────────────────┤
│ step A │ <d>ms │ features/step_definitions/steps.js:3 │
│ step A │ <d>ms │ features/a.feature:3 │
├────────────────────┼──────────────┼───────────────────────────────────────┤
│ /^(slow )?step B$/ │ <d>ms │ features/step_definitions/steps.js:4 │
│ slow step B │ <d>ms │ features/a.feature:5 │
│ step B │ <d>ms │ features/a.feature:4 │
├────────────────────┼──────────────┼───────────────────────────────────────┤
│ step C │ <d>ms │ features/step_definitions/steps.js:11 │
│ step C │ <d>ms │ features/a.feature:6 │
├────────────────────┼──────────────┼───────────────────────────────────────┤
│ step D │ UNUSED │ features/step_definitions/steps.js:12 │
└────────────────────┴──────────────┴───────────────────────────────────────┘
"""

Scenario: only list 5 slowest matches
Expand Down Expand Up @@ -81,15 +81,15 @@ Feature: usage formatter
When I run cucumber-js with `--format usage`
Then it outputs the text:
"""
┌──────────────────┬──────────┬──────────────────────────────────────┐
│ Pattern / Text │ Duration │ Location │
├──────────────────┼──────────┼──────────────────────────────────────┤
│ /^(slow )?step$/ │ <d>ms │ features/step_definitions/steps.js:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ 5 more │ │ │
└──────────────────┴──────────┴──────────────────────────────────────┘
┌──────────────────┬──────────────┬──────────────────────────────────────┐
│ Pattern / Text │ Duration │ Location │
├──────────────────┼──────────────┼──────────────────────────────────────┤
│ /^(slow )?step$/ │ <d>ms │ features/step_definitions/steps.js:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ slow step │ <d>ms │ features/a.feature:3 │
│ 5 more │ │ │
└──────────────────┴──────────────┴──────────────────────────────────────┘
"""
4 changes: 3 additions & 1 deletion src/time.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { performance } from 'perf_hooks'
import * as messages from '@cucumber/messages'

let previousTimestamp: number
Expand All @@ -14,6 +15,7 @@ const methods: any = {
},
setInterval: setInterval.bind(global),
setTimeout: setTimeout.bind(global),
performance,
}

if (typeof setImmediate !== 'undefined') {
Expand All @@ -22,7 +24,7 @@ if (typeof setImmediate !== 'undefined') {
}

function getTimestamp(): number {
return new methods.Date().getTime()
return methods.performance.now()
}

export function durationBetweenTimestamps(
Expand Down

0 comments on commit 7c16400

Please sign in to comment.