E2E
integration
unit
Mocha, Ava, Jest, Jasmine, QUnit, Tape
E2E
integration
unit
import add from './add'
it('adds', () => {
expect(add(2,3)).to.equal(5)
})
E2E
integration
unit
Mocha, Ava, Jest, Jasmine, QUnit, Tape
+
Karma, JsDom, Sinon
E2E
integration
unit
import api from './api'
nock('server.com')
.get('/foo')
.respond(200, 42)
it('responds', () =>
api.foo()
.then(result =>
expect(result).to.equal(42)
)
)
E2E
integration
unit
Example:
React with Enzyme
Full rendering
Shallow rendering
E2E
integration
unit
Cypress, TestCafe, Selenium, Protractor
+ stubbing
E2E
integration
unit
it('logs user in', () => {
cy.visit('page.com')
cy.get('#login')
.click()
cy.contains('Enter username')
.type('joe@joe.com')
cy.contains('Enter password')
.type('password{enter}')
cy.contains('Welcome Joe!')
})
E2E
integration
unit
E2E
integration
unit
E2E
integration
unit
WAIT A MINUTE!
E2E
integration
unit
it('logs user in', () => {
cy.visit('page.com')
cy.get('#login').click()
})
E2E
integration
unit
import LoginComponent from './src/login'
it('logs user in', () => {
mount(LoginComponent)
cy.get('#login').click()
})
import mount from 'cypress-<X>-unit-test'
E2E
integration
unit
import LoginComponent from './src/login'
it('logs user in', () => {
mount(LoginComponent)
cy.get('#login').click()
})
import mount from 'cypress-<X>-unit-test'
E2E
integration
unit
export LoginComponent
E2E
integration
unit
export LoginComponent
Full browser
E2E
integration
unit
import LoginComponent from './src/login'
it('logs user in', () => {
mount(LoginComponent)
cy.get('#login').click()
})
import mount from 'cypress-<X>-unit-test'
storybook.js.org
E2E
integration
unit
Why are they called
cypress-<X>-unit-test ?!
function add(a, b) {
return a + b
}
add(a, b)
outputs
inputs
a, b
returned value
it('adds', () => {
expect(add(2,3)).to.equal(5)
})
function add(a, b) {
const el = document.getElementById('result')
el.innerText = a + b
}
add(a, b)
outputs
inputs
a, b
DOM
it('adds', () => {
add(2,3)
const el = document.getElementById('result')
expect(el.innerText).to.equal(5)
})
function add() {
const {a, b} =
JSON.parse(localStorage.getItem('inputs'))
const el = document.getElementById('result')
el.innerText = a + b
}
add(a, b)
outputs
inputs
localStorage
DOM
it('adds', () => {
localStorage.setItem('inputs') =
JSON.stringify({a: 2, b: 3})
add()
const el = document.getElementById('result')
expect(el.innerText).to.equal(5)
})
component
outputs
inputs
DOM,
localStorage,
location,
HTTP,
cookies
WW, SW,
...
DOM,
localStorage,
location,
HTTP,
cookies
WW, SW,
...
component
outputs
inputs
DOM,
localStorage,
location,
HTTP,
cookies
WW, SW,
...
DOM,
localStorage,
location,
HTTP,
cookies
WW, SW,
...
Set up
Assert
Mount
E2E
unit
it('logs user in', () => {
cy.visit('page.com')
cy.get('#login').click()
})
E2E
unit
it('logs user in', () => {
mount(LoginComponent)
cy.get('#login').click()
})
E2E
unit
Use same syntax, life cycle and Cypress API
πππππππππππ
E2E
unit
E2E
unit
linters
static
types
Ramda, _
E2E
crash
reporting
linters
static
types
unit
Ramda, _
Jest / Ava / snap-shot-it
E2E Snapshots in Cypress
PASS ./test.js
add
β adds numbers (7ms)
sub
β subs numbers (1ms)
Snapshot Summary
βΊ 2 snapshots written in 1 test suite.
it('adds numbers', () => {
expect(add(1, 2)).toMatchSnapshot()
expect(add(100, -50)).toMatchSnapshot()
})
$ cat __snapshots__/test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`add adds numbers 1`] = `3`;
exports[`add adds numbers 2`] = `50`;
Saved snapshot files
expect(value).toMatchSnapshot()
Received value does not match stored snapshot 1.
- 3
+ 21
it('adds numbers', () => {
expect(add(1, 20)).toMatchSnapshot()
expect(add(100, -50)).toMatchSnapshot()
})
compares current value with "good" saved value
expect(value).toMatchSnapshot()
Received value does not match stored snapshot 1.
- 3
+ 21
Showing β and π values works for simple values
it('compares objects', () => {
const o = {
inner: {
a: 10,
b: 20
},
foo: 'foo (changed)',
newProperty: 'here'
}
snapshot(o)
})
changed value
new value
it('compares multi line strings', () => {
snapshot(`
this is a line
and a second line (changed)
with number 42
`)
})
changed line
it('looks the same', () => {
expect(cy.screenshot()).toMatchSnapshot()
})
it('looks the same', () => {
expect(cy.screenshot()).toMatchSnapshot()
})
[FF, FF, FF] [FF, FF, FF] [FF, FF, FF]
[FF, FE, FF] [FF, FF, FF] [FF, FF, FF]
[FF, FE, FF] [FF, FE, FF] [FF, FF, FF]
[FF, FF, FF] [FF, FE, FF] [FF, FF, FF]
...
it('looks the same', () => {
expect(cy.screenshot()).toMatchSnapshot()
})
[FF, FF, FF] [FF, FF, FF] [FF, FF, FF]
[FF, FE, FF] [FF, FF, FF] [FF, FE, FF]
[FF, FE, FF] [FF, FE, FF] [FF, FE, FF]
[FF, FF, FF] [FF, FE, FF] [FF, FF, FF]
...
it('looks the same', () => {
expect(cy.screenshot()).toMatchSnapshot()
})
[FF, FF, FF] [FF, FF, FF] [FF, FF, FF]
[FF, FE, FF] [FF, FF, FF] [FF, FE, FF]
[FF, FE, FF] [FF, FE, FF] [FF, FE, FF]
[FF, FF, FF] [FF, FE, FF] [FF, FF, FF]
...
[FF, FF, FF] [FF, FF, FF] [FF, FF, FF]
[FF, FE, FF] [FF, FF, FF] [FF, FE, FF]
[FF, FE, FF] [FF, FE, FF] [FF, FE, FF]
[FF, FF, FF] [FF, FE, FF] [FF, FF, FF]
...
Shows us WHAT has changed
Shows us WHAT has changed
Welcome!
screenshot difference
DOM
difference
Welcome!
screenshot difference
.logo {
- background-color: #ffffff;
+ background-color: #fefefe;
}
+ <div>Welcome!</div>
app.css
index.html
Welcome!
screenshot difference
.logo {
- background-color: #ffffff;
+ background-color: #fefefe;
}
+ <div>Welcome!</div>
app.css
index.html
DOM diff tells HOW page has changed
.logo {
- background-color: #ffffff;
+ background-color: #fefefe;
}
+ <div>Welcome!</div>
app.css
index.html
Application behavior difference
HTML, styles, code, cookies, storage, API calls, user interaction
test timeline
pixel + DOM difference
API call returned different greeting text
successful test run
failed test run
test timeline
Test history diff explains WHYΒ the page has changed
successful test run
failed test run
HAR on steroids
network + DOM + custom
Error, stack trace, screenshot diff
Know what happened
automatically
End to end testing should do the things a user would do
End to end test tools can do pretty good job in unit testing
Diffing is the new "it"
@cypress_io
@be_mann
@bahmutov
Come join us!Β Β www.cypress.io/jobs