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

REFACTR.Tech Cypress Workshop Intro

REFACTR.Tech Cypress Workshop Intro

Amir Rustamzadeh

June 05, 2019
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. Renaissance of the Web 2005 2006 2014 2013 More complexity

    moved from backend to frontend. @amirrustam 2010
  4. 2005 2006 2014 2013 Renaissance of the Web + Testing

    Automation 2004 @amirrustam 2010
  5. ✋ 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
  6. Fast, easy and reliable testing for anything that runs in

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

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

    is no need to always manipulate the UI to create the desired state.
  9. ⚙ 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
  10. @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') }) })
  11. @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) })
  12. @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 }) })
  13. @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) })
  14. @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) })
  15. @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
  16. @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')
  17. @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) }) })
  18. @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') } }) }
  19. 5 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
  20. 5 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
  21. 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
  22. Previous Spec Test Runs Spec Test Duration History Test Duration

    (seconds) The Future Automatic Load Balancing of Test Specs Duration Forecast @amirrustam
  23. @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.
  24. Thank You npm install -D cypress Free. Open Source. MIT

    License Follow @amirrustam for link to slides.