VP of Engineering, Cypress.io
Will Klein
Quality software behaves the way users expect it to behave
E2E
integration
unit
E2E
integration
unit
E2E
integration
unit
E2E
integration
unit
Really important to users
Really important to developers
$ npm install -D cypress
// ui-spec.js
it('loads the app', () => {
cy.visit('http://localhost:3030')
cy.get('.todoapp').should('be.visible')
})
Mocha BDD syntax
Chai assertions
it('adds 2 todos', () => {
cy.visit('http://localhost:3000')
cy.get('.new-todo')
.type('learn testing{enter}')
.type('be cool{enter}')
cy.get('.todo-list li')
.should('have.length', 2)
})
it('adds 2 todos', () => {
const user = cy
user.visit('http://localhost:3000')
user.get('.new-todo')
.type('learn testing{enter}')
.type('be cool{enter}')
user.get('.todo-list li')
.should('have.length', 2)
})
Kent C Dodds https://testingjavascript.com/
// app loading todos on start
loadTodos ({ commit }) {
commit('SET_LOADING', true)
axios
.get('/todos')
.then(r => r.data)
.then(todos => {
console.log('got %d todos', todos.length)
commit('SET_TODOS', todos)
commit('SET_LOADING', false)
})
.catch(e => {
console.error('could not load todos')
console.error(e.message)
console.error(e.response.data)
})
},
it('handles 404 when loading todos', () => {
cy.server()
cy.route({
url: '/todos',
response: 'test does not allow it',
status: 404
})
cy.visit('/', {
onBeforeLoad: win => {
cy.spy(win.console, 'error').as('console-error')
}
})
// observe external effect from the app
cy.get('@console-error')
.should('have.been.calledWithExactly',
'test does not allow it')
})
control network
it('handles 404 when loading todos', () => {
cy.server()
cy.route({
url: '/todos',
response: 'test does not allow it',
status: 404
})
cy.visit('/', {
onBeforeLoad: win => {
cy.spy(win.console, 'error').as('console-error')
}
})
// observe external effect from the app
cy.get('@console-error')
.should('have.been.calledWithExactly',
'test does not allow it')
})
spy on app's console
it('handles 404 when loading todos', () => {
cy.server()
cy.route({
url: '/todos',
response: 'test does not allow it',
status: 404
})
cy.visit('/', {
onBeforeLoad: win => {
cy.spy(win.console, 'error').as('console-error')
}
})
// observe external effect from the app
cy.get('@console-error')
.should('have.been.calledWithExactly',
'test does not allow it')
})
assert it happens
But how does it FEEL?
You can replace framework X with Y
(without breaking things)
Node
Browser
Node
Cy backend
cy.task(name, ...args)
on('task', { name: (...args) => ... })
cy.task cy.exec cy.request
(and you only send data, not code)
cy.task
it('finds record in the database', () => {
// random text to avoid confusion
const id = Cypress._.random(1, 1e6)
const title = `todo ${id}`
cy.get('.new-todo').type(`${title}{enter}`)
})
runs in the browser
drive via DOM
it('finds record in the database', () => {
// random text to avoid confusion
const id = Cypress._.random(1, 1e6)
const title = `todo ${id}`
cy.get('.new-todo').type(`${title}{enter}`)
cy.task('hasSavedRecord', title).should('equal', true)
})
runs in the browser
const hasRecordAsync = (title, ms) => {
// use promise-retry or convergence
...
}
module.exports = (on, config) => {
on('task', {
hasSavedRecord (title, ms = 3000) {
return hasRecordAsync(title, ms)
}
})
}
runs in Node in cypress/plugins/index.js
task completes as soon as the server gets POST from the app and saves record to DB
task checks for wrong title and eventually times out
Tutorials
Api
Examples
Video course
Full workshop
full video of the run, screenshots of every failure
many presentations and videos about Cypress
test output, video, screenshots
cypress run --record
cypress run --record --group single
cypress run --record --group parallel --parallel
Most CIs should just work 🙏
# machines | run duration | time savings |
---|---|---|
1 | 22:50 | ~ |
2 | 11:47 | 48% |
3 | 7:51 | 65% |
4 | 5:56 | 74% |
6 | 3:50 | 83% |
8 | 3:00 | 87% |
10 | 2:19 | 90% |
10 machines = 10x speed up
Cool Things You Can do With Cypress
Test components from these frameworks with ease
Cool Things You Can do With Cypress
Cool Things You Can do With Cypress
IE11
VP of Engineering
@cypress_io
@bahmutov
slides.com/bahmutov/cypress-reactive-roadshow
github.com/cypress-io/cypress ⭐️