Modern Integration Testing for JavaScript Applications

Dr Gleb Bahmutov PhD

VP of Eng

C / C++ / C# / Java / CoffeeScript / JavaScript / Node / Angular / Vue / Cycle.js / functional


virtual tours


MatLab on the web


finance dashboards

Testing sucks

It is too hard

It takes too long

It is not that useful

Testing is

a drag

Testing Pyramid

Unit tests pass...

We write more unit tests because our tools make it EASY

$ npm install -D jest
const add = require('./add')
describe('addition', () => {
  it('adds numbers', () => {
    expect(add(1, 2)).toBe(3)
$ npm test

How test end to end

  1. During a full moon sacrifice two goats

  2. Install Selenium

  3. Quickly write E2E tests and throw them into Selenium before it gets angry

E2E should be easy

  • Easy to install

  • Easy to write tests

  • Simple to run

Easy to debug when a test fails

$ npm install -D cypress

Tip: cache "node_modules" folder on CI

Let's test "TodoMVC"!

Is the app focused on "New Todo" input?

this looks close

it('is focused on new item', () => {

that's result of "cy.focused()"

it('is focused on new item', () => {
  cy.focused().should('have.class', 'new-todo')

I know exactly what happens

it('is focused on new item', () => {
  cy.focused().should('have.class', 'new-todo')

Every command

outputs detailed info

in DevTools

Making Assertions

Chai, Chai-jQuery, Sinon-Chai

Default Assertions

  • cy.visit() expects the page to send text/html content with a 200 status code
  • cy.get() expects the element to eventually exist in the DOM
  • .type() expects the element to eventually be in a typeable state

and many more ...

Failing Test

The first time one of your

tests fails in Cypress

will be one of your best days

as a developer

zero elements found


Trying to type into a list item element

Cypress team

carefully hand crafts

each and every

error message

Giant API

80 commands + events + utilities (lodash, moment, jQuery) + assertions

Every command is described in excruciating detail

  • Syntax
  • Correct usage
  • Incorrect usage
  • Options
  • What it logs
  • Examples and best practices

Test whatever you want

const url = ''
  "baseUrl: ""
$ export CYPRESS_baseUrl=
$ $(npm bin)/cypress run

Need for Speed

Cypress is VERY FAST


var webdriverio = require('webdriverio');
var options = { desiredCapabilities: { browserName: 'chrome' } };
var client = webdriverio.remote(options);
    .setValue('#search_form_input_homepage', 'WebdriverIO')
    .getTitle().then(function(title) {
        console.log('Title is: ' + title);
        // outputs:
        // "Title is: WebdriverIO (Software) at DuckDuckGo"
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
       .withTimeout(30, SECONDS)
       .pollingEvery(5, SECONDS)

Timeouts, timeouts everywhere!


Test continues as soon as DOM updates

But wait, there is more ...

  • Add your commands

  • Server stubbing

  • Screenshots and videos

  • Chromium-based browsers

  • Easy CI setup

Is there is a catch?

  • Multi-browser support is coming

  • Windows support is coming

  • Plugin system is coming

This week đŸ¤”

Giving Cypress Away

This week đŸ¤”

Cypress Dashboard

See, share, and fix failing tests.

Cypress Dashboard

  • Is a paid Saas complement to Cypress app
  • Perfect place to store test results, screenshots and videos
  • Helps find why and when a test started failing

Thank you

$ npm install -D cypress

Modern Integration Testing for JavaScript Applications

By Gleb Bahmutov

Modern Integration Testing for JavaScript Applications

Unit testing is hard and time consuming; and worse - the users and the customers do not care! They only want the features working in the production system, everything else is development overhead. If this is the case, how do we improve the web application quality? How do we catch the bugs early? How can we test the deployed system effectively? And finally, how do we get rid of Selenium? This presentation tries to answer many of these questions in a web framework agnostic way. BostonJS meetup. Video at

  • 5,755