Codementor Events

End to End testing with Testcafe

Published Jun 10, 2019Last updated Dec 06, 2019

End to end testing doesn’t have to be an extreme sport, before now, writing end to end tests, we need to set up  W3C WebDriver API (formerly Selenium WebDriver) and use a test framework like Nightwatch which was built with NodeJS. While this may be amazing, setting up  W3C WebDriver API can be tricky because we have to setup Java SDk on our machine, after which you need to configure Nightwatch using a JSON file full of presets (ranging from selenium presets to browser presets etc). Due to the rate at which Javascript is changing you also need to configure Nightwatch to be able to use ES6 and beyond. After all this a nightwatch.conf.js file needs to be added to the root of the project. Though there may be another approach to setting up all I have stated above, but in my own opinion, this seems to be the easiest approach.

In recent times, there has been a better way to write End to end tests for your application, better frameworks with easier setups. In this tutorial I would be showing you how to write end to end tests using TestCafe to achieve this from the easy setup to writing test suites with basic assertions, take a deep breadth, this is going to be fun.

Setting up test cafe

For the purpose of this tutorial, I will be using a small app I built recently that generates random phone numbers, this app is hosted here (https://moh-random-number-generator.herokuapp.com/).

First we need to install testcafe globally by running in your terminal
$ npm install -g testcafe
If you prefer not to install Testcafe globally on your machine, the alternative approach is to install it as a dependency in your project by running

$ npm install testcafe —save-dev

Link to project repo can be found here. The source code before the tests can be found on the develop branch, I created a test branch, where we can find the test suite codes. Here comes the moment we have been waiting for.

Writing test suites for our project

First we create a directory that is going to house our test files, let’s call the directory e2e, then we create a file called app.test.js in our e2e directory.

The next thing to do is import the testcafe module as stated in the documentation by importing testcafe like so
import { Selector } from ‘testcafe’;

To make our tests cleaner and readable, we need to create a “fixture” . A fixture is basically a category of tests, a test suite can contain one or more fixture(s). Let’s create our fixture

fixture `Random Number Generator tests`
  .page `https://moh-random-number-generator.herokuapp.com/` 

What if we have a much longer URL, this may make our code less readable because it’ll have more than 100 characters on a line so let’s clean that up and create a constant to hold our URL value one or two lines before our fixture, let’s call the constant origin.
const origin = “https://moh-random-number-generator.herokuapp.com/“;

This will make our new fixture look like this

fixture `Random Number Generator tests`
  .page `${origin}`

Let’s proceed by creating our first test suite which is asserting the URL of the home page of our app

test(‘test homepage URL’, async t => {
  await t.expect(); // this is an assertion to check if the URL of our page is the same as what we are expecting
});

Before we assert our URL, there is something else I would like to introduce to us, Client Functions in testcafe. Client Functions is for creating custom functions for test purposes and in this case we need to use it to get our window location but before we do that, let’s import it. Edit line 1 like so

import { Selector, ClientFuntion } from ‘testcafe’;

Let’s proceed to create out Client Function just below our origin constant like so

const getUrl   = ClientFuntion(() => document.location.href);

Once this is done we can now perform our first assertion, our first test suite is now going to look like so

test('Test homepage URL', async t => {
  await t.expect(getUrl()).match(/https:\/\/moh-random-number-generator.herokuapp.com/);
});

Running our tests

Testcafe has a lot of optional parameters for running tests, but I will stick to the easiest one for now, in our package.json file, I will add a new script like so
"test:e2e": "testcafe chrome e2e/app.test.js -e -q --debug-on-fail"

I decided to use chrome as my test browser, other available options are Firefox and Safari, instead of using Chrome I can use all browsers by using the “all” flag instead of Chrome; the -e flag stops test execution when a failure occurs and provides a stack trace; -q flag enables quarantine mode when a test fails, and finally the —debug-on-fail automatically enters debug mode on test failure.

Writing more tests and assertions

Let’s write more tests and assertions

test('test page banner', async t => {
// assertion to check if the only h1 tag on the page contains the required text
  await t.expect(Selector('h1').innerText).contains('Phone Number Generator');
});


test('test page banner', async t => {
// assertion using the class attribute instead of the tag name is also possible
  await t.expect(Selector('.App-subtitle').innerText).contains('How many numbers do you want to generate?');
});

test('test app button', async t => {
  await t.expect(Selector('button').innerText).contains('Generate Phone Number(s)');
});

test('test generate phone number functionality', async t => {
  await t
    .click(Selector('input').withAttribute('placeholder', 'Enter a number'))
    .typeText(Selector('input').withAttribute('placeholder', 'Enter a number'), '3', { replace: true })
    .click(Selector('button').withText('Generate Phone Number(s)'))
    .wait(5000); // So we can see that the numbers where generated

  // Test sorting functionality
  await t
    .click(Selector('select'))
    .click(Selector('option').withText('Ascending'))
    .wait(1000);

  // Test export button functionality
  await t
    .click(Selector('button').withText('Export Numbers'))
    .expect(getUrl()).match(/https:\/\/moh-random-number-generator.herokuapp.com/)
});

Conclusion

This is just a little of what can be achieved with TestCafe, for more question(s) please comment, I would answer as much as I could. For more information the TestCafe documentation is well written, it can be found here.

Feel free to clone the repository and experiment by adding more test suites, please note that since the app is hosted on heroku the dyno maybe asleep when you try running the tests, please load the app in a browser to wake it up before running the tests.

Please drop any more questions you have in the comment section, I will be willing to help.

Discover and read more posts from Mohammed Isioye
get started
post commentsBe the first to share your opinion
Kayode Adeola
4 years ago

Feature test automation at its best, thanks for sharing 👍🏻

Akinola Akinwande
5 years ago

Good insight, will connect with you for more insight

Mohammed Isioye
5 years ago

Sure, thanks!

Henry Otighe
5 years ago

Very helpful.

Show more replies