Automated Testing in Javascript - how to get started with testing in JS using Cypress and Jest. No more excuses, start testing your production code TODAY!
Example project can be found here: https://github.com/nano3labs/example-automated-testing-js
2. About Michael
• Co-Founder @ Nano 3 Labs & PictureThat
• Full-stack Developer Rails/React
• Writing tests since 2010
• Web dev since 2001
• Love UX & apps that just work
• Early co-founder of Winnipeg.js
3. Outline
• Goal: get you started using automated testing
• Why Test?
• How to think of tests?
• Testing tools in Javascript
• Example
• Common Mistakes
• Tips
5. But really…
• Documents functionality
• Proves your code works
• Forces you to think things through
• Gives confidence in new changes
• Shorter feedback loop for devs
• More frequent releases
6. How Testing Saved Me
• Artona - Photography E-Commerce
• 2500 tests for mid-size e-comm app + 300 selenium tests
• 8 year old code base
• Rails Upgraded from 2.3 => 5.2 over last 4 years
• Rewrite of Admin, Desktop from Flash to React
• Launched Mobile Web App rewrite in June without any
major issues
7. Testing tools in JS
• Many test frameworks over the years… most are hard to
configure, brittle and have bad documentation
• But there is hope:
• Jest - simple testing framework for unit-testings and
functional testing
• Cypress - innovative end-to-end web testing
• Detox - react-native testing*
* needs lots of work
8. At what level should I test?
• Generally: Highest abstraction to lowest abstraction
possible
• Start with UI Acceptance Tests (aka End-to-End tests)
• Focus on User Stories and act like user
• Move down to lower tests for more complicated tests
• Integration Tests => Functional Tests => Unit Tests
9. What is a test case?
• A test case is an Assumption or Hypothesis we wish
to verify is true
• There are 4 parts to any test:
• 1) Setup
• 2) Execute code under test
• 3) Matching expectations => Assertions
• 4) Cleanup (Optional)
10. Given-When-Then
• A test can be expressed as follow
• Given I am on the login page
• When I enter my email and password
• And click Login
• Then I should see “Welcome back, Michael”
• Known as Cucumber syntax — it provides us with a
useful way of thinking
12. Why Cypress?
• No timeouts
• Deterministic
• Developer exp - pause, time travel, auto-reload, etc
• Great documentation
• Event based - no crazy async logic — think Redux for
testing
13. When to use “lower-level”
tests?
• Can’t easily write an integration test
• Specific edge cases
• Too much setup for integration test
• Confident in design choice
• e.g. unit test checking user without email address
cannot be saved to DB
14. Common Mistake
• Making test steps too specific => hard to understand
purpose of test
•
it('A User logs in and sees a welcome message', () => {
cy.visit('http://localhost:3000')
cy.get('[name="email"]').type(email)
cy.get('[name="password"]').type(password)
cy.get('button').click()
expect(cy.contains('Successfully submitted')).toBeTruthy
})
// better
it('A User logs in and sees a welcome message', () => {
loginWith('michael@nano3labs.com', 'passsword')
expect(cy.contains('Successfully submitted')).toBeTruthy
})
15. Common Mistakes
• Adding details not under test => unnecessary noise
•
it('A User fills in a signup form, but forgets to enter a password and
sees error message', () => {
cy.get('[name="fullName"').type('Bob Smith')
cy.get('[name="email"]').type('bob@gmail.com')
cy.get('[name="password"]').type('')
cy.get('button').click()
})
// better
it('A User fills in a signup form, but forgets to enter a password and
sees error message', () => {
cy.get('[name="password"]').type('')
cy.get('button').click()
})
16. Common Mistakes
• Testing 3rd party libraries
• e.g. S3 => just mock out and move on, expect
function to be called
• Complicating implementation to make things more
testable… You should add minimal if any production
code to support tests
• e.g. making private members public
17. Tips
• Setup a Continuous Integration Env (CircleCI, Travis,
etc)
• Setup Code Coverage Visualization
• Setup ESLint as a step in your CI build
18. Terms: Cheat Sheet
• TDD - Test Driven Development
• BDD - Behaviour Driven Development
• Matcher - expressing matching criteria for an assertion
• Expectation - func we wrap around test result to setup an assertion using a matcher
• Double - a fake implementation of an object (instance)
• Spy - like a mock, but
• Mock - a fake implementation of a function => allow to test in isolation
• Stub - same as mock
• Fixture - use static objects in a separate file for testing
• Factory - uses Factory pattern to generate objects for testing
19. Questions?
• Share your experience or ask a question…
• twitter: @yagudaev, @nano3labs
• P.S. If you want to come to Vancouver….
We’re Hiring… :)