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

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')
        .click('#submit-button');
});

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')
        .click('#submit-button')
        .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')
        .click(page.submitButton)
        .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
        .src('test.js')
        .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.

Summary

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.