Skip to content

Latest commit

 

History

History
326 lines (174 loc) · 6.57 KB

testing-e2e.md

File metadata and controls

326 lines (174 loc) · 6.57 KB
marp theme html
true
ctheme
true

width:600px


Types of testing

  • static checks - via TypeScript, linters, jsdoc, etc
  • unit tests - ensure smallest parts of application work as intended
  • integration tests - widgets, forms, etc work correctly
  • e2e tests - check app as if a user, from auth till checkout

Types of testing

it is a blurry line between types of tests, often you will not be able to distinguish integration vs e2e test


Mocking

  • Unit tests
    • everything except for this particular function or class is mocked
    • in practice, it is too tedious to mock everything
  • Integration tests
    • input data is mocked
  • E2E
    • ideally, nothing is mocked
    • in practice it is more convenient to mock some things (e.g. Feature Toggles, language, timezone, third-party providers)

Types of testing

  • static checks - saves time as you write code
  • unit tests - helps to design your code, prevents regressions as you refactor
  • integration tests - ensures widgets and pages work as expected together
  • e2e tests - ensures app works as expected

I want to be confident that the code I'm writing for the future won't break the app that I have running in production today — Kent C Dodds


E2E tests

A helper robot that behaves like a user to click around the app and verify that it functions correctly.


width:600


Cypress.io

  • Automatic waiting
  • Automatic retries
  • Network traffic control
  • Screenshots and videos
  • Spies, stubs and clocks
  • Debuggability
  • Time travel
  • Parallelization
  • Component Testing
  • Superb documentation!

Cypress.io

npm install cypress --save-dev
npx cypress open

height:400


Cypress.io

describe('My First Test', () => {
  it('clicking "type" navigates to a new url', () => {
    cy.visit('https://example.cypress.io');

    cy.contains('type').click();

    // Should be on a new URL which includes '/commands/actions'
    cy.url().should('include', '/commands/actions');
  });
});

AAA


  • Arrange - prepare UI you want to test
  • Act - interact with your UI
  • Assert - check that UI correctly behaves after actions

AAA

  • Load login page <- Arrange
  • Type 'umbrella' to "password" input <- Act
  • Check that user sees a "Weak password" message <- Assert

AAA

describe('Authorization', () => {

    it('should encourage more protected passwords', () => {
        cy.visit('/login'); // <- Arrange

        cy.get('[name="password"]').type('umbrella'); // <- Act

        cy.contains('Weak password'); // <- Assert
    });
});


Most used commands

https://docs.cypress.io/api/commands


Write tests. Not too many. Mostly integration.

— Guillermo Rauch (@rauchg) December 10, 2016
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Not too many?

Rule of diminishing returns

  • the first test gives confidence your app does not crash
  • first couple of test scenarios will make sure happy flows work
  • all the edge cases are hard to come up with and cover in advance

Code coverage

width:1200


Code coverage

is just a starting point and a helper tool, not a goal


Not too many?

=============================== Coverage summary ===============================
Statements   : 96.23% ( 919/955 )
Branches     : 87.75% ( 308/351 )
Functions    : 93.71% ( 268/286 )
Lines        : 96.16% ( 877/912 )
================================================================================

Not too many?

A highly unlikely error, writing test for it isn't hard, but just not necessary


Notes

  • Flaky tests are OK
  • Believe in your e2e
  • You should very rarely have to change tests when you refactor code
  • Avoid testing implementation details, focus on results
  • Almost never use cy.wait(1000)
  • Do not rely on style classes, use dedicated selectors cy.get([data-qa="submit-button"])
  • Avoid writing custom cy.commands
  • Avoid “reusing” parts of tests via abstractions, unless those are true abstractions
  • Copy paste is ok, tests should be as simple as possible
  • Don’t skip tests, fix them or remove them
  • "thenables" are not Promises cy.get(button).then(() => {})

Resources