Skip to content
Timing / performance information for your TestCafe test tasks.
Branch: master
Clone or download
Latest commit 2644716 Apr 14, 2017
Type Name Latest commit message Commit time
Failed to load latest commit information.
src Release stable with README Apr 14, 2017
.babelrc Release stable with README Apr 14, 2017
.gitignore Add babel transpilation Apr 14, 2017 Cleanup readme Apr 14, 2017
package.json Release stable with README Apr 14, 2017
yarn.lock Release stable with README Apr 14, 2017


Timing / performance information for your TestCafe test tasks.

TestCafe does a great job but it unfortunately only gives you timing for the entire run and not per task. Task timing is especially important when looking for performance regressions.

It might seem if this was as simple as adding a beforeEach and afterEach with a timer but unfortunately in TestCafe the afterEach fires very late and does not give you an accurate view of timing. TimeCafe allows you to use beforeEach while allowing you to manually stop the timers at the end of your tests. This method provides more accurate results.

Other gotchas are that sometimes we want to perform reset operations between tests. For example, you might want to go back to the login screen between tests. With that said, we don't want to test this part of the operation, only the part that happens on once the actual test begins. For this reason we provide a few helpers so that you can provide your own reset function without it counting against your performance metrics. Essentially a reset function gets a free pass from a performance standpoint since it really isn't part of the feature under test.


  • Install testcafe locally in your project.
  • Install timecafe yarn add timecafe --dev # or: npm install --save-dev timecafe


You must do three to use TimeCafe:

  • Provide a reset function (to be run untimed between timed tests)
  • Add some code tests that you want timed
  • Run the test command!

The reset function

The reset function is probably the hardest part of setting up TimeCafe but once it is done, you'll use it in all your tests.

Create a file to hold your reset functionality. Remember that this is the untimed functionality that will run between timed tests. It can still have assertions in it of course. Let's call this login.js (note that we don't include .test.js as the extension since it will be imported into our tests). All our reset function is doing is saying that between tests we want the browser to go back to the login page.

import { Selector } from 'testcafe';
import timecafe from 'timecafe';

const login = async t => {
  await t.navigateTo('http://localhost:9000/login');
  const contentArea = await Selector('.content-area').find('h1');

  await t
    .contains('Login:', 'The login header is shown');

export default login;
export const time = timecafe(login);

Notice that there are two exports, one is the original login function. The second is variable called time. By wrapping your reset function in timecafe() you're making sure that any tests you'd like to time will be able to do so. We're almost done but there is one important part left. Let's look at how you would actually time a test using the reset function that we previously defined in login.js.

Your tests that you want timed

Ok, we've got login.js done so now we just need to use it in our tests.

First, if you don't already have a file to put your tests in, let's do so now. Create index.test.js and add something resembling the following. Note the selectors being used are based on an Angular 1 app so you should swap them out with your own:

import { Selector } from "testcafe";
import {time} from './login';

fixture `Admin Testing`
  .page `http://localhost:9000/login`

test("App builder", async t => {
  // Action

  // Query
  const subHeader = await Selector(".content-area").find("ui-view").find("h5");

  // Test
  await t
    .contains("app builder", "The app builder header is displayed");

  // Always return to the login screen (manually this time) when done to stop the counter
  await time.finish(t);

Please note that time.start() does not require you to pass in a test explicitly, however time.finish(t) does require it because it needs to know which test to actually register as finished.

Run the tests

You can execute your tests with $(npm bin)/testcafe chrome ./index.test.js -e

And you should expect output that looks like this:

Running tests in:
- Chrome 57.0.2987 / Mac OS X 10.12.4

Admin Testing

  Done in 0.422129062s.
✓ App builder

1 passed (2s)

Note that due to current limitations the time actually is recorded directly before the test name.

Additional notes

Internally we use node's high resolution timing function process.hrtime().

Ironically tests don't exist.


Jim Cummins (@jimthedev)

You can’t perform that action at this time.