Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Automated testing in javascript

63 views

Published on

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

Published in: Software
  • Be the first to comment

Automated testing in javascript

  1. 1. Automated Testing in JS by Michael Yagudaev
  2. 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. 3. Outline • Goal: get you started using automated testing • Why Test? • How to think of tests? • Testing tools in Javascript • Example • Common Mistakes • Tips
  4. 4. Why Write Tests? Because it’s 2018!
  5. 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. 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. 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. 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. 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. 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
  11. 11. Demo Cypress • E2E Testing
  12. 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. 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. 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. 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. 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. 17. Tips • Setup a Continuous Integration Env (CircleCI, Travis, etc) • Setup Code Coverage Visualization • Setup ESLint as a step in your CI build
  18. 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. 19. Questions? • Share your experience or ask a question… • twitter: @yagudaev, @nano3labs • P.S. If you want to come to Vancouver…. 
 We’re Hiring… :)

×