Chapter 14. Writing end-to-end tests

This chapter covers

  • Setting up end-to-end tests with Nightwatch
  • Writing end-to-end tests with the Nightwatch framework
  • Running Nightwatch tests in Chrome and Firefox

As they say, all great things must come to an end. This is the final chapter of the book, and the last part of your quest to create a frontend testing suite. In this closing chapter, you’ll learn how to test a running application by writing end-to-end tests.

In this book you’ve learned how to write unit tests and snapshot tests. They’re both effective at testing individual units, but they have one glaring problem—they don’t check that the units of code work together. End-to-end tests solve this problem by performing tests against a fully operational application.

The first section of this chapter is about what end-to-end tests are, how they fit into a testing workflow, and how to write effective ones. After you’ve learned about end-to-end tests at a high level, I’ll show you how to write them.

You can use a few different tools to write end-to-end tests and automate a browser, but in this book I’ll show you how to write tests with a framework called Nightwatch that uses the WebDriver API under the hood.

In the main part of this chapter, you’ll learn how to write end-to-end tests that cycle through user journeys by automating Chrome. After you have some end-to-end tests running in Chrome, I’ll show you how to set them up to run in multiple browsers.

Before you write any end-to-end tests, you need to know what end-to-end tests are and how they fit into the frontend testing pyramid.

14.1. Understanding end-to-end tests

End-to-end tests check that an application behaves correctly by automating a browser to interact with the running application. In chapter 1, I compared end-to-end testing to manual testing. When you’re testing an app manually, you open the app, click through some actions, and make sure the app responds correctly. End-to-end tests are the same, except a program—not a human—interacts with the app.

Imagine you wanted to test that the Hacker News app renders a new list when you click the New link in the header. If you were testing manually, you would run the application server, open the application in a browser, click the New link, check that the route changes, and check that the list updates. An end-to-end test would automate a browser to perform exactly the same actions.

End-to-end tests are awesome, but they do have some downsides. To overcome the downsides, you need to write these tests effectively.

14.1.1. Using end-to-end tests effectively

End-to-end tests are a vital part of a frontend testing suite. Without end-to-end tests you wouldn’t know that an application was working correctly! But there are some downsides to end-to-end tests: they’re slow, they’re difficult to debug, and they can be flaky.

The key to using end-to-end tests effectively is to use them sparingly. Instead of writing all your tests as end-to-end tests, you should write only a few that run through core user journeys. That’s what the frontend testing pyramid describes (figure 14.1).

Figure 14.1. The frontend testing pyramid

Think of end-to-end tests as supplements for unit tests and snapshot tests. Unit tests and snapshot tests thoroughly check the components and functions that make up an application. End-to-end tests check that these components and functions work together correctly.

Works on my machine!

Works on my machine (WOMM) is an infamous response to a bug report. It happens when a developer fails to reproduce a bug locally. When they can’t reproduce the bug, they reply with the infamous words: I don’t know what’s wrong—it works on my machine.

End-to-end tests are difficult to debug, but the task becomes even more frustrating if you can’t reproduce the bug on your machine.

You can avoid the WOMM problem by running your application and tests in a reproducible environment, like a Docker container. It’s beyond the scope of this book to teach you how to set up and use Docker, but if you want to take your tests to the next level, I recommend learning how to run your application and end-to-end tests in a Docker container.

Now that you understand end-to-end tests at a high level, it’s time to look at how you implement them. In this book, you’ll use Nightwatch and the WebDriver API.

14.1.2. Understanding Nightwatch and WebDriver

Nightwatch is a JavaScript framework for automating browsers. Under the hood, Nightwatch uses WebDriver to control the browser. It’s important to understand WebDriver to be able to set up Nightwatch tests.

WebDriver is an interface for automating browsers. The most popular way to use WebDriver is with Selenium Server—a Java servlet with a REST API for applying the WebDriver protocol.

Note

A REST API is an interface that use HTTP requests to perform actions on a server.

To run end-to-end tests, start Selenium Server to listen for incoming HTTP requests. You can automate a browser by sending HTTP requests to Selenium Server. For example, if Selenium Server was listening on port 4444, a POST request to http://localhost:4444/wd/hub/session/1352110219202/element/0/click would cause the Selenium Server to click an element in a browser.

It’s difficult to write tests that communicate with Selenium directly. You need to manage browser sessions, and the request URLs make tests difficult to read. Nightwatch provides an abstraction over the WebDriver API.

In the next listing, you can see an example of using Nightwatch to enter a search in Google and assert that “Nightwatch” is included in the results.

Listing 14.1. Testing that Google displays results
module.exports = {
  'displays result correctly' : function (browser) {    1
    browser
      .url('http://www.google.com')                     2
      .waitForElementVisible('body', 1000)
      .setValue('input[type=text]', 'nightwatch')       3
      .click('button[name=btnG]')                       4
      .pause(1000)
      .assert.containsText('#main', 'Nightwatch')       5
      .end();
  }
};

  • 1 Tests are defined as methods on an object, with the property name used as the specification name.
  • 2 Automates the browser to visit www.google.com
  • 3 Enters a value into an input field
  • 4 Clicks a button
  • 5 Asserts that the page contains the text “Nightwatch”

Nightwatch communicates with Selenium Server using HTTP requests. Selenium Server then forwards commands to the browser to execute (figure 14.2). Luckily, you don’t need to know the REST endpoints for Selenium Server; all you need to do is start a Selenium Server and tell Nightwatch what URL Selenium Server is running on.

Figure 14.2. Clicking an element with Nightwatch

Now that you’ve looked at how Nightwatch works, it’s time to add it to your project.

14.2. Adding Nightwatch to a project

Setting up Nightwatch can seem difficult when you don’t understand what you’re doing. In this section, I’ll walk you through the process of installing the dependencies and configuring Nightwatch to run against the correct port on localhost.

You will do the following four things to get Nightwatch running:

1.  Install Nightwatch dependencies.

2.  Add the Nightwatch configuration.

3.  Add a sanity test.

4.  Write a script to start the server and run Nightwatch.

14.2.1. Installing dependencies

Dependencies can be a nightmare. When I write non-JavaScript apps, I’m always amazed at how difficult it can be to download a project, install its dependencies, and set it running locally. npm takes a lot of this pain away for us lucky JavaScript developers—you run npm install, and the dependencies are installed for you. npm is a natural fit for JavaScript dependencies, but you can use it for non-JavaScript dependencies too.

Nightwatch uses Selenium Server, which is a Java applet. Even though Selenium Server is written in Java, you can install it with npm. This ensures that you can still download a project, run npm install, and have the test and development scripts work correctly. You should always make it a goal of your project that running npm it (aliases for npm install && npm run test) will install all dependencies and run the test script.

Note

You need to have the Java Development Kit (JDK) installed to run Selenium Server; the minimum required version is 7. You can read how to do this in appendix A.

Install Selenium Server and Nightwatch as a dependency with the following command:

npm install --save-dev nightwatch selenium-server

You also need to add browser-specific drivers. Browser drivers are programs used by Selenium Server to execute the tests in the different browsers. For now, you’ll run the tests in Chrome, so you need to download the Chrome driver.

Run the following command to save ChromeDriver as a development dependency:

npm install --save-dev chromedriver

With Selenium Server and the ChromeDriver binary files installed in npm packages, the next step is to configure Nightwatch to start Selenium Server and communicate with it.

14.2.2. Configuring Nightwatch

Nightwatch runs Selenium Server and ChromeDriver for you. For Nightwatch to run these programs, you need to add a Nightwatch configuration file to tell Nightwatch the location of the binary files.

So far in this project, you’ve kept unit tests and snapshot tests in the src directory next to the code that they’re testing. For end-to-end tests, you’ll create a separate e2e directory in the root of the project. The end-to-end tests check the running application—they don’t focus on one particular file, so there’s no need to house them next to a file they are testing as with unit tests and snapshot tests.

Create an e2e directory in the project root. Now create an e2e/nightwatch.conf.js file, and add the code from the next listing.

Listing 14.2. Nightwatch configuration file
module.exports = {
  src_folders: ['e2e/specs'],                                    1
  output_folder: 'e2e/reports',                                  2
  selenium: {
    start_process: true,
    server_path: require('selenium-server').path,                3
    host: '127.0.0.1',
    port: 4444,                                                  4
    cli_args: {
      'WebDriver.chrome.driver': require('chromedriver').path    5
    }
  },
test_settings: {
    chrome: {                                                    6
      desiredCapabilities: {
        browserName: 'chrome'
      }
    }
  }
}

  • 1 The directory that the test files are in
  • 2 The directory to which Nightwatch should output test reports
  • 3 The Selenium Server binary path; this is exported by the selenium-server npm package.
  • 4 4444 is the default Selenium Server port.
  • 5 Sets Nightwatch to start the Selenium process with the ChromeDriver path. You’re using the path exported by the chromedriver package, which handles the installation of ChromeDriver.
  • 6 Settings for the chrome test environment. The test environment is configured by passing the --env argument to Nightwatch.

Now that Nightwatch is configured, you can write a sanity test to make sure the setup is working.

14.2.3. Adding a sanity test

When you finish cooking a delicious soup, it’s always a good idea to try a spoonful before you serve it to your guests, just to make sure it tastes fine. In the same way, you should always add a sanity test when you add a new test setup. You don’t want to spend hours debugging a test only to find out your setup was wrong.

Like other tests you’ve written in this book, you should split the end-to-end tests into their own script. Open the package.json file, and add a test:e2e script to run Nightwatch using the Nightwatch configuration file, as follows:

"test:e2e": "nightwatch --config e2e/nightwatch.conf.js --env chrome",

You should include the test:e2e script in the complete test script. Open package.json, and update the test script to run the end-to-end tests like so:

"test": "npm run lint && npm run test:unit && npm run test:integration && npm run
     test:e2e",

This is a momentous occasion! You finally have a complete test script to run against the application.

Next you need to add the sanity test to check that the runner and configuration are set up correctly. Create a new file e2e/specs/journeys.js. Open the file, and add the following code.

Listing 14.3. Nightwatch test that visits localhost:8080
module.exports = {
  'sanity test': function(browser) {
    browser
      .url('http://localhost:8080')
      .waitForElementVisible('.item-list', 2000)
      .end();
  }
}

To run Nightwatch tests against your app locally, the application must be running. Enter the following command in the command line to build the JavaScript files and start the server:

npm run build && npm run start

Open a new tab in the command line, and run the test script with the command npm run test:e2e. Nightwatch will find the test file, open a browser, navigate to localhost :8080, and wait for the .item-list element to be visible.

Note

On Windows you might see a warning dialog asking you to allow Selenium to run. You should accept.

The test should pass. This is great, except there’s a problem with this setup. You had to run two processes in two separate terminal tabs for the server and the tests to run.

Note

If the test isn’t passing, it will be because the server isn’t running on port 8080. You might need to stop another process from listening to port 8080 for the server to run.

The test suite should run from a single script. You can’t rely on somebody starting the server manually. The solution is to create a runner script that starts the server for you and then runs Nightwatch in a separate process.

14.2.4. Writing an end-to-end test script

You’re going to write a file that starts the server and then spawns a child process that runs Nightwatch with the correct arguments. That way, you can run one script to start the server and run Nightwatch.

Note

If you aren’t familiar with child processes, you can read about them at https://nodejs.org/api/child_process.html.

The runner file will import the project’s Express app; then it will start the server listening by calling the listen method. When a server starts listening, the process will run until it’s stopped by either a signal or an error. You’ll use Node event emitters to attach to these events and stop the process if the server exits.

Note

If you aren’t familiar with Node event emitters, you can read about them at https://nodejs.org/api/events.html#events_events.

When the server has started listening, you’ll create a child process to run Nightwatch. When the tests finish running, you will close the server and exit the script. Create a file called e2e/runner.js, and add the following code to the file.

Listing 14.4. Starting a server and running Nightwatch
const app = require('../server')
const spawn = require('cross-spawn')

const PORT = process.env.PORT || 8080                                    1

const server = app.listen(PORT, () => {                                  2
  const opts = ['--config', 'e2e/nightwatch.conf.js', '--env', 'chrome']
  const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio:
     'inherit' })                                                        3

  runner.on('exit', function (code) {                                    4
    server.close()
    process.exit(code)
  })

  runner.on('error', function (err) {                                    5
    server.close()
    throw err
  })
})

  • 1 Gets the port number from the environment variable if it’s set, or defaults to 8080
  • 2 Starts the server listening on the port, and calls the callback once the server is running
  • 3 Spawns a subprocess that runs the nightwatch binary with the config path and env set to chrome. This is the equivalent of running nightwatch --config e2e/nightwatch.conf.js --env chrome in an npm script. This spawns a child process that runs that command, which will start Nightwatch running. The stdio inherit option tells the subprocess to log everything to the main process, so you will see the output in the terminal when you run the script.
  • 4 spawn creates a stream. You can use the on method to listen to events from the process and close the server and the process when Nightwatch finishes running.
  • 5 This callback will run when the server creates an error. You should close the server and create the error in this process.

Now you have the runner file you need to update the test:e2e script. Open the package.json file, and update the script to run the runner file with Node:

"test:e2e": "node e2e/runner.js",

Run the test script: npm run test:e2e. This will start the server, run the test, open a browser that navigates to the app, wait until the .item-list element is visible, close the browser, and report whether the test passed or failed.

You’ve seen how to add Nightwatch to server-side projects. The next step is to write some tests.

Running tests on a client-side rendered project

Adding a script to run Nightwatch end-to-end tests to a client-side project is slightly more complicated than it is for a server-side rendered project.

The difference between a client-side rendered project and a SSR project is that an SSR project already includes a server that can serve your app locally. With client-side projects, you normally don’t have a server in the project to run the application.

Luckily, most client-side rendered Vue projects use webpack to bundle the code. Webpack has a development server package that runs a Node server to serve a project. You can use the webpack development server in the runner script to serve your file and run the tests against the file running on the development server.

14.3. Writing end-to-end tests with Nightwatch

It’s time to get your hands dirty and write some end-to-end tests in Nightwatch. Before you write the code, you need to decide which tests you are going to write.

14.3.1. Deciding which end-to-end tests to write

Deciding which tests to write and which not to write is a fine art. It’s important to write as few end-to-end tests as possible, because an end-to-end test script quickly becomes slow and flaky.

It’s not realistic to write end-to-end tests for every possible user journey. There are too many combinations of actions that the user could take. Instead, you need to be selective and write tests that check only core user journeys.

The key to effective end-to-end tests is to use them mainly to perform actions. A common mistake I see is people checking page HTML. For example, they will check that a page renders a list with the correct items. This is an expensive duplication of unit tests and snapshot tests. If you wrote tests for each piece of HTML on a page, your test suite would take years to run. Of course, sometimes you will need to check HTML, but keep it to a minimum.

In the Hacker News application, you have several lists. There are the top, new, show, ask, and jobs lists. You could write end-to-end tests for each of these lists, but that would mean testing the same functionality five times.

In tests, time is a valuable resource. You should be frugal about the number of end-to-end tests you write. With that in mind, the following are a few core journeys for the Hacker News app that you will test:

  • Clicking Comments takes the user to the item page.
  • Clicking a username redirects to a user page.
  • Clicking a list in the header refreshes the list items.
  • The page paginates correctly.

The first tests you write will check that the app routing is working correctly.

14.3.2. Writing end-to-end tests for routes

Routing is difficult to test with unit tests, which makes it a good candidate to write end-to-end tests for. One of the difficulties of end-to-end tests is deciding what you should assert to tell you that a journey is working correctly. If you manually tested that clicking Comments takes the user to the item page, you would open the browser, click a Comments link, and check with your eyes that the page updated. You would see visually that the page was correct, but how do you tell a program that the page is correct? You could make sure that each of the correct elements was rendered, but that would lead to long tests. Instead, you need to compromise and choose something that gives you enough confidence that the code is working correctly. For example, you could check that a single element is rendered that’s unique to the new page.

In the test to check that clicking Comments takes the user to the item page, you’ll check that the URL has updated and that an element with the class item-view is visible after you click a Comments link. Replace the sanity test in e2e/specs/journeys.js with the code from the next listing.

Listing 14.5. Testing that a link navigates correctly
'takes user to the item page': function(browser) {
  browser
    .url('http://localhost:8080')                    1
    .waitForElementVisible('.news-item',  1)         2
    .click('.comments-link')                         3
    .assert.urlContains(`/item`)                     4
    .waitForElementVisible('.item-view',  15000)     5
    .end();
}

  • 1 Navigates to the running app
  • 2 Waits for an item with the news-item class. This makes sure the items are rendered before you try to click the Comments link.
  • 3 Clicks the Comments link
  • 4 Asserts that the URL now contains /item. This means the route has worked correctly.
  • 5 Asserts that the item-view component is visible

Run the tests: npm run test:e2e. The test will fail. The problem is that the items did not load fast enough, so the waitForElementVisible command failed. You can fix the problem by increasing the time that waitForElementVisible waits. The second argument in waitForElementVisible is the number of milliseconds it should wait before throwing an error. In the file, increase the time of the first waitForElementVisible call to 15000 (15 seconds) as follows:

.waitForElementVisible('.news-item',  15000)

Now run the tests again; they will pass if your internet connection is fast enough. If you have a poor connection, you can increase the milliseconds value that waitForElementVisible will wait.

Flaky tests

End-to-end tests suffer from a problem known as flaky tests. Flaky tests are tests that fail regularly even though the code is working correctly. Tests can become flaky for many reasons. For example, if part of the user journey calls an API that takes a long time to respond, the test will time out and fail.

When you have a flaky test in your test suite, you will start to ignore failing tests. It’s easy to slip into a habit of thinking a failing test suite is just another flaky test. This makes your test suite much less effective. In an effective test suite, any failing test tells you there’s a bug in the application.

You can avoid flaky tests by adding long timeouts to your end-to-end tests. If an API call takes longer than expected, the test won’t fail. It’s difficult to completely avoid flaky tests. The best way is to write as few end-to-end tests as possible, while still testing core journeys.

The next test to write checks that clicking a username redirects to a user page. This test will be similar to the previous test. You’ll open the app in the browser, wait until the items have loaded, click a user link, and then assert that the browser navigates to the correct route.

To check that the browser navigates to the next route, the test will check that the route has updated and that an element with a user-view class is visible. Add the test from the next listing to the object in e2e/specs/journeys.js.

Listing 14.6. Checking that a route has updated
'clicking on a user redirects to  the user page': function(browser) {
  browser
    .url('http://localhost:8080')
    .waitForElementVisible('.news-item',  15000)
    .click('.by a')                                  1
    .assert.urlContains(`/user`)                     2
    .waitForElementVisible('.user-view',  30000)     3
    .end();
}

  • 1 Clicks the link
  • 2 Asserts that the URL now contains /user in the path
  • 3 Asserts that the user-view element is rendered

Run the tests to watch them pass: npm run test:e2e. As long as you have a good internet connection, the test will pass.

The tests you just wrote checked that the URL was updated and that the app rendered the correct element. You didn’t check that the values are correct. Checking values can be difficult when the page has dynamic data.

14.3.3. Writing end-to-end tests for dynamic data

It’s difficult to check apps that use dynamic data. For example, the Hacker News app will display different items over time. You can’t hardcode a value into a test; if you assert that an item has the title Some HN item title, when you run the test a week later, the title will have changed and the test will fail.

In the Hacker News app, you need to test that pagination works correctly. You can do this by asserting that the URL updates when you click a pagination link. But that isn’t a rigorous test. It doesn’t verify that the page content has changed.

One way to test that page content has changed is by saving the previous page content as a variable and comparing it against the new page content. This test still isn’t perfect, but it does tell you that the content has changed.

You’ll write a test that saves the list text as a variable. Then you’ll navigate with the pagination links and assert that the current list text has changed from the previous value. That way, you can know that the list values have been updated.

Add the following code to e2e/specs/journeys.js.

Listing 14.7. Changing the list by clicking through the navigation
'paginates items correctly': function(browser) {
let originalItemListText;
browser
  .url('http://localhost:8080')
  .waitForElementVisible('.news-item',  15000)       1
  .getText('.item-list', function(result)            2
    originalItemListText = result.value
  })
  .click('.item-list-nav a:nth-of-type(2 )')         3
  .waitForElementNotPresent('.progress',  15000)     4
  .perform(() => {                                   5
    browser.expect.element('.item-
     list').text.to.not.equal(originalItemListText)
  })
  .getText('.item-list', function(result) {          6
    originalItemListText = result.value
  })
  .click('.item-list-nav a')                         7
  .waitForElementNotPresent('.progress',  15000)
  .perform(() => {                                   8
    browser.expect.element('.item-
     list').text.to.not.equal(originalItemListText)
  })
},

  • 1 Waits until the items have loaded
  • 2 Gets the text of the .item-list element, and stores it in the originalItemListText variable
  • 3 Clicks the More link
  • 4 Waits until the progress bar has disappeared (until the new items have loaded)
  • 5 Perform is a command that gives you a callback in which to execute commands. Here, you’re using the callback to perform an expect assertion to make sure the text in the .item-list element is not the same as the original text. This assertion checks that the .item-list has updated.
  • 6 Updates the originalText value
  • 7 Clicks the Prev link
  • 8 Asserts that the text has changed again

You can use the same technique to check that the list is updated when the user clicks different list types in the navigation. Add the following code to e2e/specs/journeys.js.

Listing 14.8. Checking a user journey with an end-to-end test
'changes list by clicking through nav': function(browser) {
  let originalItemListText;
  browser
.url('http://localhost:8080')
    .waitForElementVisible('.news-item',  15000)            1
    .getText('.item-list', function(result) {               2
      originalItemListText = result.value
    })
    .click('.inner a:nth-of-type(2)')                       3
    .waitForElementNotPresent('.progress',  15000)
    .perform(() => {
      browser.expect.element('.item-
     list').text.to.not.equal(originalItemListText)         4
    })
    .getText('.item-list', function(result) {               5
      originalItemListText = result.value
    })
    .click('.inner a:nth-of-type(4)')                       6
    .waitForElementNotPresent('.progress',  15000)
    .perform(() => {
      browser.expect.element('.item-
     list').text.to.not.equal(originalItemListText)        7
    })
  },

  • 1 Waits until the items have loaded
  • 2 Gets the text of the .item-list element, and stores it in the originalItemListText variable
  • 3 Clicks a link to load a new list
  • 4 Asserts that the .item-list has updated by comparing the new text to the old text before loading a new list
  • 5 Stores the current list text
  • 6 Loads a new list by clicking a link
  • 7 Asserts that item-list has updated

Run the test script: npm run test:e2e. You’ve written tests to check the core use journeys. The tests will fail if the units of the app aren’t connected correctly. These end-to-end tests are implicitly testing that the application is configured correctly.

Now that you’ve got end-to-end tests written and passing in Chrome, it’s time to run them in another browser. You can do this without editing the test code. All you need to do is add some extra configuration.

14.4. Running end-to-end tests in multiple browsers

Cross-browser testing is an important part of any large application, but it’s time-consuming. One of the benefits of writing end-to-end tests with Nightwatch is you can run them in multiple browsers with a little extra configuration. In this section, you’ll look at how to run tests in Firefox as well as Chrome.

Note

Remember, Nightwatch uses the WebDriver API, which is a W3C standard. That means most browsers support the WebDriver protocol.

You’re going to run your tests in Firefox, so you need to download the Firefox driver—geckodriver. Remember, drivers are WebDriver implementations for different browsers. You’ll use an npm package to manage the downloading of the driver binary, so the first step is to install geckodriver and save it as a dependency. Run the following command in the command line:

npm install --save-dev geckodriver

You need to set Nightwatch to pass the geckodriver binary path to the Selenium process. You do this in the Nightwatch config file. Open the e2e/nightwatch.conf.js file, and, in the selenium.cli_args object, add the following extra line:

'WebDriver.gecko.driver' : require('geckodriver').path

Now you can update the runner script to call Nightwatch with a new environment. That way, Nightwatch will run tests in both the Chrome and Firefox environments. Open the e2e/runner.js file. In this file is an opts array that contains the command-line options you pass when you call the Nightwatch process. You need to update the line to pass chrome,firefox as the env argument. Replace the line with the following code:

const opts = ['--config', 'e2e/nightwatch.conf.js', '--env', 'chrome,firefox']

When you run the runner script, Nightwatch will run tests in the Chrome environment and the Firefox environment. If you run the test:e2e script, you’ll get an error that Nightwatch is passed an invalid test environment—you need to add the Firefox environment in the Nightwatch config file.

You’ll add the option in the e2e/nightwatch.conf.js file. This option tells Nightwatch to use the Firefox browser when running the Firefox environment. Open e2e/nightwatch.conf.js, and add the code from the next listing to the test_settings object.

Listing 14.9. Defining a Firefox environment Nightwatch config
firefox: {
  desiredCapabilities: {
    browserName: 'firefox'       1
  }
}

  • 1 Sets Nightwatch to use the Firefox browser when running the Firefox environment

That’s all the setup you need to run tests in Firefox. Run the end-to-end script: npm run test:e2e. You’ll see that Nightwatch now runs the tests in Firefox and Chrome.

You can add extra browsers by following the same steps, although you will need to use an operating system that supports the browser. For example, you must be using Windows 10+ to run tests in Edge.

Great—now you have tests running in Chrome and Firefox with Nightwatch, which uses the WebDriver API.

Alternative end-to-end testing frameworks

Most end-to-end testing frameworks use WebDriver. The reason I’ve taught you how to use Nightwatch is that WebDriver is the most popular solution. But there are alternatives to WebDriver. The two most promising are TestCafe and Cypress.io. They are both faster than WebDriver solutions and require less configuration to set up. The downside to these alternative frameworks is that they are new and have a smaller community than the WebDriver API.

The best place to learn about TestCafe is its Getting Started Guide: http://mng.bz/nxn5. Cypress.io also has a good Getting Started guide at http://mng.bz/vOgp.

Now you have unit tests, snapshot tests, integration tests, and end-to-end tests running against the Hacker News application. You can run them all from the following script:

npm t

Congratulations! You’ve finished the Hacker News application, and you’ve developed a test suite that effectively tests that the application is behaving correctly.

Summary

  • You can write end-to-end tests to test that user journeys work correctly.
  • You can use the Nightwatch framework to write end-to-end tests.
  • You can set up Nightwatch to run for SSR apps and for client-side rendered apps,

Where to go from here

Your testing quest has come to an end. You’ve gained experience points, leveled up your skills, and achieved the sought-after title of Vue Test Master.

It’s been a long journey from the first test back in chapter 2. You’ve learned to write unit tests for Vue components. You’ve learned to use snapshot tests to test static output of components. Finally, you’ve learned to write end-to-end tests to check that a running application behaves correctly.

Of course, like a student graduating from college, your Vue testing journey has only just begun. Out there in the wide world you’ll encounter innovative code bases and unforeseen problems that will challenge your testing prowess. But I’m confident that, armed with the techniques you learned in this book, you will find solutions and overcome these unknown challenges.

As you increase your testing skills and experience, you may decide to contribute to the Vue testing community. There are many ways that you can help push the community forward. You could create a library, write a blog post, or teach other developers. You’ll be surprised at the impact your actions can have and the good they can bring other developers.

Whatever your future holds, I’m glad that I could teach you my approach to testing and that there’s one more Vue testing master in the world.

Happy testing!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.204.201