Continuously Shipping

Web Apps with Confidence

Amir Rustamzadeh

Sr. Engineer

@amirrustam

Continuous & Confidence

@amirrustam

TREND

More teams have some automation process.

@amirrustam

Reduction of 26% to 11% from 2016 to 2017 of teams that do not automate deployment.
Source: O'Reilly & SIG

TREND

Continuously Delivery growth has been relatively small.

@amirrustam

16% in 2017 versus 11% in 2016
Source: O'Reilly & SIG

TREND

Small decline in teams

without regression testing.

@amirrustam

41% in 2017, down from 48% in 2016
Source: O'Reilly & SIG

WHY?

@amirrustam

There is large growth in automation, but relatively slower growth in delivery and testing.

TESTING IS HARD

@amirrustam

Continuous & Confidence

@amirrustam

Remove Friction

Continuous & Confidence

@amirrustam

Remove Friction

Faster & Better Feedback Loops

Continuous & Confidence

@amirrustam

Remove Friction

Faster & Better Feedback Loops

Great developer or QA experience

@amirrustam

@amirrustam

The way we write our apps changed, but our testing tools did not adapt.

What is Cypress?

A tool for reliably testing anything that runs in web browser.

Free & Open Source

MIT License

Our mission is to build a thriving, open source ecosystem that enhances productivity, makes testing an enjoyable experience, and generates developer happiness. We hold ourselves accountable to champion a testing process that actually works.

Growth in Popularity & Adoption

⭐️ 12.7K +

📦 450K +

GitHub Stars

NPM Weekly Downloads

Growth in Popularity & Adoption

Growth in Popularity & Adoption

Sustainable Open Source

Let's Dive In

Setup & Installation

$ npm install -D cypress
$ npm install -D cypress

Desktop App

CLI

$ npx cypress open

Open Desktop App

  • 📦 My Project

    • 📁 ...

    • 📂 cypress

      • 📂 fixtures

      • 📂 integration

      • 📂 plugins

      • 📂 support

Your App

Command Log

Time-Travel

API

Intuitive & English-like

API

cy.<command>

API

cy.get('button')

API

cy.get('button')
  .click()
  .should('have.class', 'active')

API

cy.request('/users/1')
  .its('body')
  .should('deep.eql',{ name:'Amir'})
// cypress/support/commands.js

Cypress.Commands.add('login', (email, password) => {
  cy.get('input[name="email"]').type(email)
  cy.get('input[name="password"]').type(password)
  cy.get('#login-button').click()
})

Custom Commands

context('User setup', () => {
  it('signup and login user', () => {
    cy.visit('http://localhost:8080/signup')

    cy.get('input[name="email"]').type('amir@cypress.io')
    cy.get('input[name="password"]').type('1234')
    cy.get('input[name="confirm-password"]').type('1234')
    cy.get('#signup-button').click()

    cy.location('pathname').should('eq', '/login')

    cy.login('amir@cypress.io', '1234')

    cy.location('pathname').should('eq', '/board')
  })
})

Let's dive deeper

Architecture

Backend

Browser

Your Tests

Your App

Browser Provisioning & System-level tasks

Architecture

🏃🏻‍♂️

Faster test runs

Architecture

⚡️

Direct native Access to the DOM & your application.

🔐 Login Scenario

Architecture

🐞

Better Debuggability

Architecture

👌

Test commands are executed in a deterministic manner. Resulting in flake-free testing.

it('send email with contact form', () => {
    cy.get('#name-input').type('Amir')
    cy.get('#email-input').type('amir@cypress.io')
    cy.get('form').submit()
    cy.get('#success-message').should('be.visible')
})
    cy.get('#name-input').type('Amir')
    cy.get('#email-input').type('amir@cypress.io')
    cy.get('form').submit()
    cy.get('#success-message').should('be.visible')

Architecture

Automatic Waiting

API

cy.get('button')
  .click()
  .should('have.class', 'active')

Cypress will automatically wait for this assertion (4 seconds by default)

API

cy.task

Execute JS on the system (outside of the browser)

// cypress/plugins/index.js

const { clearDatabase } = require('../../server/db')

module.exports = (on, config) => {
  on('task', {
    'clear:db': () => {
      return clearDatabase()
    }
  })
}
context('User setup', () => {
  beforeEach(() => {
    cy.task('clear:db')
  })

  it('signup and login user', () => {
    cy.visit('http://localhost:8080/signup')

    cy.get('input[name="email"]').type('amir@cypress.io')
    cy.get('input[name="password"]').type('1234')
    cy.get('input[name="confirm-password"]').type('1234')
    cy.get('#signup-button').click()

    cy.location('pathname').should('eq', '/login')

    cy.get('input[name="email"]').type('amir@cypress.io')
    cy.get('input[name="password"]').type('1234')
    cy.get('#login-button').click()

    cy.location('pathname').should('eq', '/board')
  })
})
const userSeed = require('../../server/seed/users')

context('User setup', () => {
  beforeEach(() => {
    cy.task('clear:db')
    cy.task('seed:db', userSeed.data)
  })

  it('login user', () => {
    cy.visit('http://localhost:8080/login')

    cy.login('amir@cypress.io', '1234')

    cy.location('pathname').should('eq', '/board')
  })
})

How do you run Cypress in CI?

Headless Mode

$ npx cypress run

Test Run Video Recording

Out-of-the-Box

$ npx cypress run

Record Results to

Cypress Dashboard

$ npx cypress run --record

Cypress Dashboard

Test Run Status & Performance Details

Organized & Shareable Error Reports

Cypress Dashboard

Optimize CI Usage with Parallelization

$ npx cypress run --record --parallel

83%

Upcoming

Test Retries

Reduce pipeline failures and identify true flaky tests.

999

❌ 1

Upcoming

 

Full-Network Stubbing

 

Improved Error Reporting

 

Cross-browser Support

Roadmap

Docs

📚 docs.cypress.io

Example Recipes

🤝

Community

Gitter

on.cypress.io/chat

Thank You

Happy Testing

Amir Rustamzadeh

Sr. Engineer

@amirrustam

Continuously Shipping Web Apps with Confidence

By Amir Rustamzadeh

Continuously Shipping Web Apps with Confidence

In the last decade the web made a drastic shift from simple, minimally interactive pages to highly dynamic applications that rival desktop-class software. During this shift, browsers became more advanced, and we started investing more into patterns and frameworks to helps us build apps that fully realize the potential of these advancements. But building an app is only part of the battle of shipping and maintaining an app. We must also continuously and consistently test our apps, but unfortunately, this is an often neglected step. And for good reason — testing is hard. Testing in real browsers has historically been a non-trivial task. Toolchain setup, writing tests, resolving failures, handling flakiness, and waiting on long CI jobs add layers friction that consume precious time, lower the bar of overall quality, and mitigate continuous delivery of products. However, these difficulties should no longer deter us, as there are now modern open-source tools like Cypress, that enable fast and reliable automated browser testing while providing an unprecedented developer-friendly experience. We’ll explore a new perspective on automated testing, so we can all continuously ship with confidence.

  • 1,052