Gleb Bahmutov

VP of Engineering

@bahmutov

WEBCAST

Using Code Smells

to

Fix Flaky Cypress Tests

Josh Justice

Web Platform Lead

@codingitwrong

Ask Questions at Sli.do event code #codesmells

The 3 code smells

  1. Unprepared Element

  2. Flickering Element

  3. Impatient Test

Additional info

Q & A

Today's webinar

Two things are true at once:

1. Cypress has made it easier to test modern frontend web apps.

2. It's still hard to test modern frontend web apps.

Asynchrony

The solution is simple:

cy.wait(milliseconds)

cy.wait(1000)

cy.wait(500)

cy.wait(2000)

cy.wait(1000)

cy.wait(100)

cy.wait(500)

NO, DO NOT cy.wait(milliseconds)!

  • It makes your suite too slow
  • Your tests are still flaky
  • It masks real application bugs

If you're a testing nerd you can figure out the flake.

Ask Questions at Sli.do event code #codesmells

Not everyone is a testing nerd. What can everyone else do?

Code Smells

Code Smells:

“…we have learned to look for certain structures in the code that suggest—sometimes, scream for—the possibility of refactoring.”

 

– Martin Fowler and Kent Beck. Refactoring: Improving the Design of Existing Code, Second Edition.

Code smells:

  • Help you identify problem patterns more easily
  • Suggest a solution to the problem
  • Ease communication about the pattern
  • Help you to level up your team

A "code smell" is not a judgment.

Three Examples of Cypress Code Smells

Origin: A Large
Public-Facing React App

Three Cypress Code Smells

Ask Questions at Sli.do event code #codesmells

1. Unprepared Element

Symptom:

An element is present but doesn't behave the way it does in manual testing.

Root Cause:

The element is added to the DOM before the data is ready for it to be interacted with.

Why this is an app bug:

A fast user with a slow device/connection could click on the unprepared element.

Solution:

Don't render the element as interactable until it is prepared.

Not Interactable:

  • Don't render the element at all
  • Render it with the disabled attribute
  • Cover it with an overlay

1. Unprepared Element:

Don't render the element as interactable until it is prepared.

2. Flickering Element

Ask Questions at Sli.do event code #codesmells

Symptom:

"cy.click() failed because this element is detached
from the DOM," but the element is visible on the page.

Root Cause:

The element is added to the DOM, then removed, then a second similar element is added.

Declarative rendering: great.

But it can lead to flicker.

Why this is an app bug:

On a slow device the flicker could be visible.

Solution?

cy.click({ force: true })

Solution:

Rework the flow of data so that the element no longer flickers.

2. Flickering Element:

Rework the flow of data so that the element no longer flickers.

3. Impatient Test

Symptom:

Test fails without waiting for the condition that would cause it to succeed.

Root Cause:

The next element to interact with is already present and Cypress doesn't know to wait.

Solution 1:

Change the app code so the test can proceed immediately.

Solution 2:

Prevent interaction with the element.

Solution 3:

Check a "green light."

Green Light Option 1:

Check an element.

Green Light Option 2:

Check a network response.

The danger of a green light: it doesn't protect you if you forget to check it.

3. Impatient Test:

  1. Enable proceeding immediately
  2. Prevent interaction
  3. Check a "green light"

Review

Ask Questions at Sli.do event code #codesmells

1. Unprepared Element:

Don't render the element as interactable until it is prepared.

2. Flickering Element:

Rework the flow of data so that the element no longer flickers.

3. Impatient Test:

  1. Enable proceeding immediately
  2. Prevent interaction
  3. Check a "green light"

Cypress Code Smells

  1. Unprepared Element
  2. Flickering Element
  3. Impatient Test

Takeaways

  1. Look for these code smells and try the solutions
  2. Share them with your team
  3. Look for other code smells and give them a name

Ask Questions at Sli.do event code #codesmells

Thank you

Josh Justice

Web Platform Lead

@codingitwrong