Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Next-Generation Web Application End-to-End Testing with Cypress

Next-Generation Web Application End-to-End Testing with Cypress

This talk was originally presented at Devoxx Belgium 2018.
-
We all want to consistently ship quality software. One of the best ways to do that is by end-to-end (E2E) testing our code as it simulates the real actions of our beloved users. Let’s be frank though, E2E testing is notoriously time-consuming, expensive, slow, and often flaky. Unfortunately, these issues lead to developers doing very little to no E2E testing, and taking solace in a plethora of unit-tests that cannot fully test the intended experience of users.

We can do better. We should do better. We will do better.

We’ll explore modern tools and libraries, such as Cypress, that enable us to easily and beautifully write flake-free, reliable, deterministic E2E tests for our web applications. E2E tests will give us confidence in the software we ship down the wire.

Amir Rustamzadeh

November 15, 2018
Tweet

More Decks by Amir Rustamzadeh

Other Decks in Technology

Transcript

  1. @amirrustam ! E2E testing? I spend hours chasing flaky tests!

    " # Too expensive for project budget. In our last project, E2E tests slowed down development.
  2. E2E Integration Unit Visit The Testing Pyramid Easy, developers really

    like to write these. More Difficult, costly, slower… Often completely ignored @amirrustam
  3. Fast, easy and reliable testing for anything that runs in

    a browser. Free. Open Source. MIT License @amirrustam
  4. $ npm install -D cypress ☝ All-in-one tool You get

    everything you need ❤ Familiar tools underneath Mocha, Chia, Sinon @amirrustam
  5. @amirrustam Username Password Login You can mutate state programmatically. There

    is no need to always manipulate the UI to create the desired state.
  6. ⚙ Component Testing cypress-react-unit-testing vue angular angularjs hyper-app svelte cycle

    https://github.com/bahmutov/cypress-vue-unit-test#test-adapters-for-other-frameworks @amirrustam
  7. @amirrustam import mount from 'cypress-vue-unit-test' import MyComponent from './app/components/MyComponent.vue' describe('My

    Component', () => { beforeEach(mount(MyComponent)) it('loads', () => { cy.get('button').should('be.visible') }) })
  8. @amirrustam it('starts with zero items', () => { // start

    Cypress network server // spy on route `GET /todos` // THEN visit the page cy.server() cy.route('GET', '/todos').as('todos') cy.visit('/') cy .wait('@todos') // wait for `GET /todos` response // inspect the server's response .its('response.body') .should('have.length', 0) // then check the DOM cy.get('li.todo').should('have.length', 0) })
  9. @amirrustam it('posts new item to the server', () => {

    cy.server() cy.route('POST', '/todos').as('new-item') cy.visit('/') cy.get(‘.new-todo').type('buy cookies{enter}') cy.wait('@new-item').its('request.body').should('have.contain', { title: 'buy cookies', completed: false }) })
  10. @amirrustam it('starts with zero items (stubbed response)', () => {

    // start Cypress network server // spy on route `GET /todos` // THEN visit the page cy.server() cy.route('GET', '/todos', []).as('todos') cy.visit('/') cy .wait('@todos') // wait for `GET /todos` response // inspect the server's response .its('response.body') .should('have.length', 0) // then check the DOM cy.get('li.todo').should('have.length', 0) })
  11. @amirrustam it('starts with zero items (fixture)', () => { //

    start Cypress network server // stub route `GET /todos`, return data from fixture file // THEN visit the page cy.server() cy.route('GET', '/todos', ‘fixture:sample-todos').as('todos') cy.visit('/') cy .wait('@todos') // wait for `GET /todos` response // inspect the server's response .its('response.body') .should('have.length', 0) // then check the DOM cy.get('li.todo').should('have.length', 0) })
  12. @amirrustam Browser Node Backend cy.exec(…) Execute system commands outside of

    the scope of Cypress. ✅ Seed a database ✅ Running build scripts ✅ Start and kill processes
  13. @amirrustam Browser Node Backend cy.exec(…) cy.exec('rake db:seed').its('code').should('eq', 0) cy.exec('npm run

    my-script’) .its(‘stdout') .should('contain', 'Done running the script')
  14. @amirrustam Browser Node Backend cy.task(…) // in test describe('e2e', ()

    => { beforeEach(() => { cy.task('defaults:db') cy.visit('/') }) it('displays article values', () => { cy.get('.article-list') .should('have.length', 10) }) })
  15. @amirrustam Browser Node Backend cy.task(…) // in plugins/index.js file //

    we require some code in our app that // is responsible for seeding our database const db = require('../../server/src/db') module.exports = (on, config) => { on('task', { 'defaults:db': () => { return db.seed('defaults') } }) }
  16. 4 cypress open Great for everyday development workflow Cypress +

    Editor Side-by-Side TDD Nirvana cypress run Testing in CI/CD Pipeline Headless More efficient for running all your tests @amirrustam
  17. 4 cypress open Great for everyday development workflow Cypress +

    Editor Side-by-Side TDD Nirvana w/ Realtime Reloading cypress run --record Record to Cypress Dashboard @amirrustam
  18. cypress run --parallel cypress run --parallel cypress run --parallel Your

    CI Machines 3x parallelism Ready for work signup.spec.js login.spec.js widget.spec.js @amirrustam
  19. Previous Spec Test Runs Spec Test Duration History Test Duration

    (seconds) The Future Automatic Load Balancing of Test Specs Duration Forecast @amirrustam
  20. @amirrustam Parallelization Tips Do not write all tests in one

    file. Break them up so they can be load balanced on CI machines. Do not write tests that are dependent on each other. Tests should pass in isolation.
  21. Renaissance of the Web 2005 2006 2014 2013 More complexity

    moved from backend to frontend. @amirrustam
  22. ✋ JSDOM or DOM Emulation JSDOM is not a real

    browser. Your users don’t run your app with JSDOM. One of the primary reasons for E2E is to simulate real user actions. @amirrustam
  23. Thank You npm install -D cypress Free. Open Source. MIT

    License Follow @amirrustam for link to slides.