ºÝºÝߣ

ºÝºÝߣShare a Scribd company logo
Testingat
Both
Endsofthe
Triangle
heyhihello
derek graham
@deejaygraham
@deejaygraham@hachyderm.io
Testing at Both Ends of the Triangle.
https://nebytes.net
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
/deejaygraham
/testing-at-both-ends-of-the-triangle
If you want to play along¡­
The.
Testing.
Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testcodeiscode
Testcodeiscode
th@t wE d0n;t ³Ù±ð²õ°Õ¡¯
Microtests
A test is not a unit test if:
* It talks to the database
* It communicates across the network
* It touches the file system
* It can't run at the same time as any of your
other unit tests
* You have to do special things to your
environment (such as editing config files) to
run it.
Michael Feathers - A Set of Unit Testing Rules
EndtoEndTests
IntegratedTests
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Web2.0
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
S
cr
ipt
Testing at Both Ends of the Triangle.
CypressGood:)
? Runs ¡°inside¡± browser
? Automatic waiting
? Debuggability
? Snapshots
? Spies
? Network interception
? Screenshots & videos
? Hot reload
? Auto retry
CypressBad:(
? No multiple tabs
? Not established like Se
? JS only
? No Safari
? Iframes limited
? Multi-site not allowed
? Login still an issue
npminstallcypress
https://docs.cypress.io
npxcypressopen
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
? application
? src
? cypress
? components
? e2e
? support
Let¡¯stalk
about
Jest(maybe)
describe('The thing I am testing', () => {
it('should do this', () => {
expect(1 + 1).toBe(2);
});
it('ought not to do that', () => {
expect('red').toBe('green');
});
});
cy.*
E2Etests
Arrange
Act
Assert
Arrange
Act
Assert
cy.visit('https://google.com');
before(() => {
cy.clearLocalStorage();
cy.visit(examplePage);
});
Arrange
Act
Assert
cy.get(¡®.username');
cy.get(¡®#password');
cy.get('input[type=submit]');
cy.get('#password')
.type('random password');
? Use data-cy
attribute
? Visible text
? Element ids
? Class name
? Generic
control
name
https://docs.cypress.io/guides/references/best-practices
Arrange
Act
Assert
cy.contains('Google');
cy.contains('google', { matchCase: false });
cy.title().should(¡®contain', ¡®TotT');
cy.get(¡®#password')
.should('not.contain', 'swordfish');
cy.get('#password')
.should('not.contain', 'passw0rd')
.and('not.contain', 'swordfish');
cy.get('#password')
.type('random password')
.should('have.value', 'random password');
Should
cy.get('h1')
.invoke('attr', 'class')
.should('eq', 'title');
? be.visible
? have.attr
? have.value
? have.text
? not.exist
So,areyou
feeling
lucky?
describe('Google', () => {
it('Knows about Tech on the Tyne', () => {
cy.viewport(1280, 720);
cy.intercept(¡®https://www.google.com/search*')
.as('google');
cy.visit('https://www.google.com/');
// find reject all button...
cy.get('#W0wltc').click();
cy.get('input[name="q"]')
.type('Tech on the Tyne');
cy.get('form').submit();
cy.wait('@google');
});
});
E2EDemo
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
MoreExamples
cy.window().then((win) => {
win.navigator
.clipboard
.readText().then((text) => {
expect(text)
.to
.contain(¡®Hello this is in the clipboard');
});
});
const block = cy.get('#content')
.find('.notification');
block.should('be.visible');
block.within(() => {
cy.get('p').contains('Hello World');
});
cy.get('.article').within(($article) => {
if ($article.find('img').length > 0) {
cy.get('img').each(($img) => {
cy.wrap($img).scrollIntoView()
.should('be.visible');
expect($img[0].naturalWidth)
.to.be.greaterThan(0);
expect($img[0].naturalHeight)
.to.be.greaterThan(0);
});
}
});
it('Web API works with Cypress', () => {
cy.request({
url: 'https://swapi.dev/api/people/1',
method: 'GET'
}).its('body')
.should('deep.contain', {
name: 'Anakin Skywalker'
})
})
it('Website talks to fake Star Wars API', () => {
cy.intercept(
'GET',
'https://swapi.dev/api/people/1', {
statusCode: 200,
body: {
name: 'Peter Pan',
},
})
})
Componenttests
https://github.com/
deejaygraham/calendar
ComponentDemo
npxcypressrun
? Component Level Tests
? Sandboxed
? Time travel
? Before and After
? Same dev experience as e2e
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Testing at Both Ends of the Triangle.
Debugging
cy.log('hello world¡¯);
cy.debug();
Its&invoke
// access session storage
cy.window().its('sessionStorage');
// get access to the redux store
cy.window().its('store');
// dispatch an object to redux
cy.window()
.its('store')
.invoke('dispatch',
{
type: 'description',
value: 'smol'
});
CustomCommands
Cypress.Commands.add('store', () => {
return cy.log('Redux - Store')
.window({ log: false })
.its('store', { log: false });
});
Cypress.Commands.add('dispatch', (obj) => {
const { type, ...data } = obj;
return cy.log(`Redux - Dispatch: ${type}`,
data)
.window({ log: false })
.its('store', { log: false })
.invoke('dispatch', obj);
});
cy.store()
.dispatch(
{
type: 'description',
value: 'smol'
});
Spies&Stubs
const onChangeSpy =
cy.spy().as('onChangeSpy');
cy.mount(<Counter onChange={onChangeSpy} />);
cy.get('[data-cy=increment]').click();
cy.get('@onChangeSpy')
.should('have.been.calledWith', 1);
const onClick = cy.stub();
cy.mount(<Counter onClick={onClick} />);
cy.get('[data-cy=increment]')
.click()
.then(() => {
expect(onClick).to.be.called
// expect(onClick).to.not.be.called
});
@deejaygraham
Testing at Both Ends of the Triangle.

More Related Content

Testing at Both Ends of the Triangle.