Writing better tests for your
JavaScript app
Jake Ginnivan
‘Better’ Tests?
Fast
Comprehensive
Reliable
Maintainable
Increased confidence
Enables refactoring
Typical Problems when testing…
• Slow to write
• Slow to run
• Intermittently fail
• Do not fail
• Prevent refactoring
• Don’t catch issues
Why write tests?
Why write tests?
Deploy with confidence
Writing better tests for your
JavaScript app
Jake Ginnivan
TestStack
White
Seleno
ConventionTests
BDDfy
Shouldly
Digital Development Manager @
Some testing scenarios
You don’t have much testing, and want to get as much confidence with
as little work as possible
You have found a bug which is really easy to fix, how do you ensure it
doesn’t happen again
You have a feature which is critical and has a large impact if there are
issues
There is no single testing
strategy!
Unit tests
In process
Isolated
Fast
Test one thing
Module
Function
Fast
Comprehensive
Reliable
Maintainable
Increased confidence
Not restrictive
Unit tests
Pros
• Fast to write
• Fast to run
• Easy to debug
Cons
• Can inhibit refactoring
• Delete them and re-write
• Does not find collaboration
issues between modules
• Need higher level tests to
accompany them
Unit tests – Test runner
Unit testing
DEMO
Unit tests
• Keep modules pure
• Mocks are potential design issues
Higher level unit tests
Also known as acceptance tests, behaviour tests, collaboration tests, boundary
tests and many other things
Unit Tests
In process
Isolated
Fast
Test one thing
Fast
Speed of
development
Reliable
Maintainable
Increased confidence
Not restrictive
Higher level Unit Tests
In process
Isolated
Fast
Test one thing
Fast
Speed of
development
Reliable
Maintainable
Increased confidence
Not restrictive
Higher Level Unit tests
Pros
• Fast to write
• Pretty Fast to run
• Covers module interactions
• Less prone to breaking during
refactoring
Cons
• Harder to debug than unit tests
• Cannot cover all scenarios
• Combinatorial issue
Higher level unit tests – tips / techniques
• An approach to testing single page apps
• Testing an express API
Client SPA Context
• Mock / Polyfill the DOM (JSDom)
• Mock external services (Sockets, HTTP Calls)
• Create a DOM instance and mount your application into it
• State based testing
• Raise events, interact with application, ensure it does what you want
Node web service context
• Create an mockable abstraction for any external systems
• Database
• Other services
• Reduce logic in express middlewares
• If you are not going to start an in memory express server
• Use mediator pattern to introduce middlewares not tied to your http server
• Use subcutaneous style testing
Ports and adapters
Source: http://www.dossier-andreas.net/software_architecture/ports_and_adapters.html
Ports and adapters
export default {
emailSender: function(details) {
eventEmitter.publish(‘sendEmail’, details)
}
}
eventEmitter.on(‘sendEmail’, (details) => {
// actually send email
})
eventEmitter.on(‘sendEmail’, (details) => {
console.log(‘Pretending to send email’)
})
Integration tests
Integration Tests
Out of process communication
Slow
Often shared mutable state
Fast
Speed of
Development
Reliable
Maintainable
Increased confidence
Not restrictive
UI tests
UI Tests
Fragile
Slow
Fast
Speed of
Development
Reliable
Maintainable
Increased confidence
Not restrictive
Useful testing patterns
Defensive tests
The seam
function getCheckins(testDb) {
var db = testDb || connection
return db('checkin')
.select()
}
Arrange, Act, Assert
it('can search for whisky', async () => {
// Arrange
fetchMock.get('http://localhost:3001/whiskys?q=glen', [
{"id":99901,"name":"Glenmorangie Signet","region":""}
])
const app = mount(<App />)
// Act
const input = app.find('#searchBox')
input.simulate('change', { target: { value: 'glenm' }})
await wait(800)
// Assert
expect(app.find('span').text()).toBe('Glenmorangie Signet')
})
Page Object Pattern
class AppPage {
constructor() {
this.app = mount(<App />)
}
async searchForWhisky(term) {
const input = app.find('#searchBox')
input.simulate('change', { target: { value: term }})
}
getResults() {
return this.app.find('span').text()
}
}
Recap
• Test in Node
• Snapshot testing is awesome
• Different tests are a trade off, mix, blend and experiment to get what
you need
• Tests do not have to be painful
• Tests increase confidence so you can deploy and make your customers
happy!
Thanks!
Questions?

Writing better tests for your java script app

Editor's Notes

  • #2 Good afternoon, how has everyones conference been? There has been so many great talks over the past few days, personally I really enjoyed ____ and ____ amongst others. Today we are going to be talking about how to write better tests for your JavaScript app, to do that we need to quality what I mean by ‘better’?
  • #3 Fast / Comprehensive --- Number of tests vs coverage? Reliable / Maintainable --- No race conditions, trusted, easy to maintain and keep up to date Valuable / Non-restrictive --- Do the tests find bugs? Can you refactor without breaking heaps of tests?
  • #5 We are payed to write software, not tests. The reason we write tests is to give us confidence to ship the software we write.
  • #6 We are payed to write software, not tests. The reason we write tests is to give us confidence to ship the software we write.
  • #8 To make your customers happy
  • #9 Good afternoon, how has everyones conference been? There has been so many great talks over the past few days, personally I really enjoyed ____ and ____ amongst others. Today we are going to be talking about how to write better tests for your JavaScript app, to do that we need to quality what I mean by ‘better’?
  • #10 Then…
  • #13 Lets explore this more
  • #16 Use node, way fast to bootstrap and unit tests are not trying to test browser compat
  • #17 searchLatest
  • #19 There is no common taxonomy on types of tests, the important thing to focus on is the characteristics of each type of test!
  • #24 I use React, Redux, but redux is transparent. This approach can be used with most UI libraries and is far far faster than using karma and real browsers, but you are testing in a different environment that your application will actually run in..
  • #40 We are payed to write software, not tests. The reason we write tests is to give us confidence to ship the software we write.