Upgrade to Pro — share decks privately, control downloads, hide ads and more …

It's a (testing) trap! - Common end-to-end pitfalls and how to solve them

It's a (testing) trap! - Common end-to-end pitfalls and how to solve them

“It’s a trap” - a call or feeling we all might be familiar with, not only when it comes to Star Wars. It signalizes a sudden moment of noticing imminent danger. This situation is an excellent allegory for an unpleasant realization in testing. Imagine having the best intentions regarding testing but still ending up with tests failing to deliver any value. Tests who are feeling like a pain to deal with?

When writing frontend tests, there are lots of pitfalls on the way. In sum, they can lead to lousy maintainability, slow execution time, and - in the worst-case - tests you cannot trust. But it doesn’t have to be that way. In this session, I will talk about developers’ common mistakes (including mine) in tests using Jest and Cypress, at least from my experience. And, of course, how to avoid them using best practices. Testing doesn’t need to be painful, after all.

Ramona Schwering

October 20, 2023
Tweet

More Decks by Ramona Schwering

Other Decks in Programming

Transcript

  1. . describe('do stuff in my Onlineshop', () => { beforeEach(()

    => { // Login user using their credentials cy.login('user', 'pass'); }); // … tests will start below })
  2. . describe('do stuff in my Onlineshop', () => { beforeEach(()

    => { cy.get('#sw-field--username').type('username'); cy.get('#sw-field--password').type('pass'); cy.get('.sw-login-login').submit(); cy.contains('Dashboard'); }); // … tests will start below })
  3. Use shortcuts: Lösung mit Abkürzung . describe('do stuff in my

    Onlineshop', () => { beforeEach(() => { cy.request( 'POST', '/api/oauth/token', { // payload: Send all data you need } ).then(() => { cy.contains('Dashboard'); }); }): // … tests will start below })
  4. describe('Context menu', () => { it('should open the context menu

    on click', async () => { const wrapper = createWrapper(); expect(wrapper.vm).toBeTruthy(); await wrapper.trigger('click'); const selector = '.sw-context-menu'; expect(wrapper.find(selector).isVisible()).toBeTruthy(); }); });
  5. describe('E2E with AAA pattern‘, () => { it('should open the

    context menu on click', () => { }); }); // Act // All the steps you need to come to the // scenario to test // Assert // Checks and assertions of your test beforeEach(() => { // Arrange // All the preparations you need });
  6. “…arrange my test == what I’m given.” “…act in my

    test == when something happens.” “…assert the results == something happens then this is what I expect as the outcome.”
  7. describe('E2E with Given When Then', () => { it('should use

    Given When Then', () => { }); }); // When // All the steps +assertions you need to come to the // scenario to test // Then // Scenario to test beforeEach(() => { // Given // All the preparations you need });
  8. Isolated test data . describe('Customer login', () => { let

    customer = {}; beforeEach(() => { // Set application to clean state cy.setInitialState() .then(() => { // Create test data return cy.setFixture('customer'); }) }): // … tests will start below })
  9. it('should create and read product', () => { … cy.get('.sw-field—product-name').type('T-Shirt

    Ackbar'); cy.get('.sw-select-product__select_manufacturer') .type('Space Company’); … });
  10. describe('Example test', () => { // Source Cypress docs it('Just

    doing things', () => { cy.visit('/my/resource/path'); cy.get('.awesome- selector’).click(); let el = Cypress.$('.new-el'); if (el.length) { cy.get('.another-selector'); } else { cy.get('.optional-selector'); } }); });
  11. describe(‚Example Test', () => { // Source: Cypress docs it('Doing

    things right'‚ () => { cy.visit('/my/resource/path') cy.get('.awesome-selector') .click() .then(() => { let el = Cypress.$('.new-el'); if (el.length) { cy.get(‚.another-selector'); } else { cy.get(‚.optional-selector'); }; }); }); });