TestCafe: Easier End-to-end Web App Testing with Node.js

Vasily Strelyaev
Vasily Strelyaev

End-to-end Web App Testing with TestCafe

In this article, TestCafe team member Vasily Strelyaev explains the benefits of this new Node.js-based app testing framework.

Front-end web developers know how difficult it is to set up automated testing for a web app.Even installing a testing framework can be challenging. Many existing solutions require Selenium, which brings browser plugins and JDK with it.

Before you start testing, you also need to set up a test harness, which means dealing with configuration files. Later, you can discover that some parts of the harness — such as reporting — are missing and you need to find and install them separately.

TestCafe is a new, open-source, Node.js-based end-to-end testing framework for web apps.

It takes care of all testing stages: starting browsers, running tests, gathering test results, and generating reports. And it neither needs browser plugins nor has other dependencies: it just works out of the box.

In this article, I’ll show how to

  • write your first test
  • run it on your local machine and in a cloud testing service
  • create a testing task for a task runner

Installing TestCafe

First, you need to have Node.js installed on your machine. If you don’t, go to its website and download it, or consider using a version manager such as nvm.

Once you’re done with Node.js, installing TestCafe is a matter of one command:

npm install -g testcafe

If you’re on Linux/Mac and you find yourself needing to add sudo, you should consider fixing up your npm permissions.

Writing a Test

We’ll write a test for the TestCafe demo page.

Example Page

Open a code editor of your choice and create a new test.js file.

First, add a fixture declaration that targets the demo web page at http://devexpress.github.io/testcafe/example/:

fixture `My first fixture`
    .page `https://devexpress.github.io/testcafe/example`;

Then, add a test:

fixture `My first fixture`
    .page `https://devexpress.github.io/testcafe/example`;

test('My first test', async t => {
    // We will add test code later

Now let our test type text into the Developer Name input and click the Submit button:

fixture `My first fixture`
    .page `https://devexpress.github.io/testcafe/example`;

test('My first test', async t => {
    await t
        .typeText('#developer-name', 'Peter Parker')

Here we used the typeText and click test actions. TestCafe provides a dozen of them, from hover to file upload.

Let’s get back to our test. The Submit button redirects you to a page that says ‘Thank you, %username%!’.

Thank You Page

We’ll check that text on this page contains the right name:

import { Selector } from 'testcafe';

fixture `My first fixture`
    .page `https://devexpress.github.io/testcafe/example`;

const articleHeader = Selector('#article-header');

test('My first test', async t => {
    await t
        .typeText('#developer-name', 'Peter Parker')
        .expect(articleHeader.innerText).eql('Thank you, Peter Parker!');

To do this, we create a selector that identifies the article header. After test actions, we add an assertion that checks if the text says ‘Thank you, Peter Parker!’

Page Object

The TestCafe team encourages using the Page Object pattern in tests. With this pattern, you introduce object representation of the tested page and use it in test code. Let’s look at how we do this.

Create a new page-object.js file and declare a Page class:

export default class Page {
    constructor () {

Our test interacts with three page elements so far: the Developer Name input, the Submit button, and the ‘Thank you’ header. So, we add three selectors to the Page class:

import { Selector } from 'testcafe';

export default class Page {
    constructor () {
        this.nameInput     = Selector('#developer-name');
        this.submitButton  = Selector('#submit-button');
        this.articleHeader = Selector('#article-header');

In the test file, reference page-object.js, create an instance of the Page class, and use its fields in test actions:

import Page from './page-object';

fixture `My first fixture`
    .page `https://devexpress.github.io/testcafe/example`;

const page = new Page();

test('My first test', async t => {
    await t
        .typeText(page.nameInput, 'Peter Parker')
        .expect(page.articleHeader.innerText).eql('Thank you, Peter Parker!');

With the page object pattern, you keep all selectors in one place. When the tested web page changes, you will need only to update one file — page-object.js.

Running Tests Locally

To run this test on a local machine, you need only one command:

testcafe chrome test.js

TestCafe will automatically find and launch Google Chrome and run the test.

In the same manner, you can run this test in, say, Safari or Firefox by simply specifying their name.

You can use the testcafe --list-browsers command to see the list of browsers TestCafe detects on your machine:

TestCafe lists detected browsers

Test Run Report

After testing is finished, TestCafe outputs a report to the console:

Successful test run report

If a test fails, TestCafe provides a call site with callstack that shows where the error occurred:

Unsuccessful test run report

You can choose from five built-in report formats or search for a plugin that adds support for a different format.

Launching Tests from an IDE

You can run TestCafe tests from popular IDEs like VS Code or SublimeText using a dedicated plugin:

Launching Tests from VS Code

Running Tests in a Cloud Testing Service

While TestCafe can run tests in any popular modern desktop or mobile browser out of the box, it also has an ecosystem of plugins that work with cloud testing services, headless and other non-conventional browsers.

In this section, we’ll run tests on SauceLabs, a popular automated testing cloud. It hosts hundreds of virtual machines with different operating systems and browsers.

To run tests on SauceLabs, you need a SauceLabs account. If you don’t have one, visit https://saucelabs.com/ and create a new account. You’ll be given the necessary credentials: a username and an access key.

Now you need to install the TestCafe plugin that works with SauceLabs:

npm install --save-dev testcafe-browser-provider-saucelabs

Since this plugin is installed to a local directory, you also need to have TestCafe installed locally:

npm install --save-dev testcafe

Before using the SauceLabs plugin, save the username and access key to environment variables SAUCE_USERNAME and SAUCE_ACCESS_KEY as described in SauceLabs documentation.

Now you can run your test on SauceLabs virtual machines in the cloud:

testcafe "saucelabs:Chrome@beta:Windows 10" test.js

You can view the full list of browsers and virtual machines available on SauceLabs by running

testcafe -b saucelabs

Add a Task to a Task Runner

Task runners are quite useful when you need to automate routine tasks in your development workflow.

Integration with a task runner is a good solution to run TestCafe tests at development time. That’s why the TestCafe community developed plugins that integrate it with the most popular Node.js task runners.

In this tutorial, we’ll use Gulp.js.

If you don’t have Gulp.js installed on your machine, use the following commands to install it both globally and locally to the project:

npm install -g gulp
npm install --save-dev gulp

Install a Gulp plugin that integrates TestCafe with Gulp.js:

npm install --save-dev gulp-testcafe

If you have a Gulpfile.js file in your project, add the following task to it. Otherwise, create a new Gulpfile.js with this task:

const gulp     = require('gulp');
const testcafe = require('gulp-testcafe');

gulp.task('run-testcafe-tests', () => {
    return gulp
        .pipe(testcafe({ browsers: ['chrome', 'firefox'] }));

This task runs tests from the test.js file in Chrome and Firefox. To learn more about the Gulp plugin API, see its GitHub page.

You can now run this task from the command line as follows:

gulp run-testcafe-tests

Testing on a Continuous Integration Platform

TestCafe provides powerful command line and programming interfaces that make it easy to work with most of modern CI systems.

Test run reports can be presented in the JSON, xUnit and NUnit formats understood by most of the popular CI systems.

TestCafe documentation contains a recipe that describes how to set up testing for a GitHub project on Travis CI.


In this article, I’ve shown how to start from your first TestCafe test and end up with e2e testing integrated into your project’s workflow. You could see for yourself how easy it is to test web applications with TestCafe.

If you have questions about TestCafe, post a comment below, ask on the forum or visit the GitHub page.

Frequently Asked Questions (FAQs) about TestCafe

How does TestCafe differ from other end-to-end testing tools?

TestCafe is a unique end-to-end testing tool because it doesn’t require WebDriver or any other testing software. It runs on Node.js and uses a proxy to inject scripts into the browser. This allows it to automate user actions and assert that elements on the page behave as expected. It supports testing in multiple browsers and platforms, including mobile. It also provides features like automatic waiting, real-time diagnostics, and concurrent test execution.

Can I use TestCafe for mobile testing?

Yes, TestCafe supports mobile testing. It can run tests on iOS and Android devices, as well as in mobile simulators and emulators. You can also emulate mobile devices in your desktop browsers. This makes it a versatile tool for testing responsive web applications.

How does TestCafe handle asynchronous operations?

TestCafe has a built-in automatic waiting mechanism. This means you don’t need to manually add waits or sleeps to your tests. TestCafe automatically waits for page loads and XHRs before it starts the test and after each action. It also waits for elements to become visible before interacting with them.

Can I run tests in multiple browsers concurrently with TestCafe?

Yes, TestCafe allows you to run tests concurrently in multiple browsers. This can significantly speed up your testing process. You can specify the number of concurrent test runs when you start testing.

How can I debug tests in TestCafe?

TestCafe provides several ways to debug your tests. It includes a debug mode that pauses the test and allows you to see the tested page’s state at that moment. It also provides real-time test status reporting, screenshots, and video recording of test sessions.

Can I use TestCafe for cross-browser testing?

Yes, TestCafe supports cross-browser testing. It can run tests in multiple browsers concurrently, both on your local machine and on remote devices. It supports all popular browsers, including Chrome, Firefox, Safari, and Internet Explorer.

How does TestCafe handle page navigation?

TestCafe handles page navigation automatically. It waits for the page to load before it starts the test and after each action that leads to a new page. This means you don’t need to add any special code to handle page navigation.

Can I use TestCafe with continuous integration systems?

Yes, TestCafe can be integrated with popular continuous integration systems like Jenkins, TeamCity, Travis, and others. It can generate reports in multiple formats, including xUnit, which can be used by these systems.

How can I handle file uploads in TestCafe?

TestCafe provides a special action for file uploads. You can use the t.setFilesToUpload action to upload files. This action takes a selector that identifies the file input and a string that specifies the path to the file to upload.

Can I use TestCafe for performance testing?

While TestCafe is primarily designed for functional testing, it can also be used for performance testing. You can use it to measure the time it takes for actions to complete, for pages to load, and for AJAX requests to finish. However, for more detailed performance testing, you might need to use a dedicated performance testing tool.