0% found this document useful (0 votes)
16 views13 pages

Why - Page - Goto - Is Slowing Down Your Playwright Tests

Uploaded by

WonderZaid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views13 pages

Why - Page - Goto - Is Slowing Down Your Playwright Tests

Uploaded by

WonderZaid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

10/10/24, 12:04 Why "page.

goto()" is slowing down your Playwright tests

Login Start for free

/ Blog / Playwright page.goto()

July 10, 2024 (Updated: July 23, 2024)

Why "page.goto()" is slowing down your


Playwright tests
Stefan Judis
Developer Relations

Playwright Synthetic Monitoring

Share on social

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 1/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

Table of contents

When you invest time and effort into creating a well-running end-to-end test
suite or adopt Playwright synthetic monitoring with Checkly, you should focus
on two things.

Your tests must be stable because few things are worse than an unreliable
test suite. But also, your tests must be fast because no one wants to wait
hours to receive the green light when you're on the edge of your seat to
deploy this critical production hotfix.

What if I told you you’re slowing down your tests with the most basic
Playwright action ever — page.goto() ?

Check out this video or read on to learn more. Both include examples and
ways to speed up your Playwright tests.

Why "page.goto()" is slowing down your tests

Ready? Let’s go!

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 2/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

The start of every Playwright script — page.goto()

Here’s a pretty basic Playwright script.

login.spec.js

import { expect, test } from "@playwright/test";

test("Login works", async ({ page }) => {


await page.goto("/");

const loginLink = page.getByRole("link", { name: "Login" });


await loginLink.click();

const loginHeader = page.getByRole("heading", { name: "Login" });


await expect(loginHeader).toBeVisible();

// More things to check after the login link was clicked


// ...
});

It navigates to the root of a baseURL defined in the playwright.config . It


locates a link, clicks it, and then tests whether the site’s UI has been updated
accordingly (I’ve hidden most of the actions and assertions because they
don’t matter for this post).

All this works great, and I’m sure you’ve written similar Playwright code
before. If you inspect your tests and their duration, you might have discovered
that page.goto() execution times can vary greatly.

Let me show you an example.

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 3/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

In the Playwright trace above, page.goto() takes ten seconds! Surprisingly,


the film strip on top of the trace viewer shows that the example site was
visible for almost the entire waiting time.

And this is a single test for a super-speedy local e-commerce site. Testing all
the core functionality of a reasonably sized shop could easily include a
hundred tests, and then such a small delay results in more than 15 minutes
of waiting time in your CI/CD pipeline!

(Of course, you can shorten this waiting time by parallelizing your tests, but
the argument of unnecessary waiting still holds.)

What are we waiting for?

page.goto() and the load event


If you check the Playwright docs, you’ll discover that, by default,
page.goto() waits for the load event.

await page.goto("/");

// is the same as

await page.goto("/", {waitUntil: "load"});

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 4/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

What’s the load event? A quick peek at MDN gives us the answer.

The load event is fired when the whole page has loaded, including all
dependent resources such as stylesheets, scripts, iframes, and images.

Let’s think this through. Whenever you call page.goto() you’re waiting for all
stylesheets, scripts, iframes, and images to be loaded. In summary, you’re
waiting for everything(!) to be loaded before running your test.

When inspecting the network tab of my example trace file, I found an SVG
image delaying all the test actions. Why is this file so slow? I don’t know, but
there’s always a chance of resources taking longer to load.

Now, this is only a small demo application. Consider a full-blown e-commerce


shop; there will be hundreds of images, let alone all the scripts coming from
“somewhere”. For such a site, the page.goto() default configuration will
wait for all the resources to be squeezed through the network before clicking
the first button. Is this the best way?

Your users aren’t waiting for your requests — why


should your tests do it?
Let’s take a step back for a moment…
https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 5/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

Why are you testing and monitoring your sites end-to-end with real browsers?
You want to ensure that your site and infrastructure work properly, sure. But
you also want to do this by mimicking actual user behavior. That’s the entire
point of end-to-end testing, right?

Do your users wait for the little spinner in their URL bar to disappear before
they click on something? I doubt it. I’m pretty sure your average visitor won’t
look at your site’s loading state before clicking the “Add to cart” button.
People click and interact with your site whenever something’s visible. That’s
why the best approach to writing Playwright scripts is to stick to natural
human behavior.

How should you navigate your tests, then?

The page.goto() waiting behavior can be tweaked with the waitUntil


config property. And you can define four waitUntil settings.

// Wait until the HTML starts loading.


await page.goto("/", {waitUntil: "commit"});

// Wait until the HTML is parsed


// and deferred scripts (`<script deferred>` and `<script type="module">`) are loaded.
await page.goto("/", {waitUntil: "domcontentloaded"});

// Wait until all initially included resources are loaded.


await page.goto("/", {waitUntil: "load"});

// Wait until every resource is loaded and the network is silent for 500ms.
await page.goto("/", {waitUntil: "networkidle"});

When you look at these waitUntil options, all but commit heavily rely on
the network and the embedded resources. This means all options but
commit check implementation details, potentially slowing down your tests
when one request is stuck in the network layer.

How do these options compare in speed? Here are the results for my example
test case.

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 6/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

Option "page.goto" execution time

commit 62ms

domcontentloaded 159ms

load 10.1s

networkidle 12.6s

"waitUntil" speed comparison

Of course, I extracted these numbers from a local Playwright test running


against a local site. But the absolutes don’t matter. What’s important is to look
at the differences between the waitUntil options.

Unsurprisingly, the commit waiting option is the fastest goto()


configuration because it does not wait for anything resource-related except
the first bytes of the initial HTML. networkIdle is by far the slowest because
it waits for every resource to be loaded and then adds 500ms of idle network
time on top.

But here’s a funny thing: All these tests succeeded regardless of the
waitUntil option. The overall test duration for this small test case varied
from roughly 10 to 25 seconds, but the tests were all green.

What is going on, and how does this work?

Writing fast tests that don’t rely on the network


In my experience, there are only two reasons for flaky or slow tests: either
your application is untestable, or you fail to follow Playwright's best practices.

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 7/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

If the site you want to test isn’t stable, you won’t succeed in creating a stable
and fast test suite. You can’t write stable tests for a flaky app — end of story.
Similarly, if your site has bad UX and includes poor hydration patterns, your
tests will be full of workarounds to succeed on the happy path. Ideally, you
would fix these application issues, but I know that this is not always possible.

But if you, on the other hand, aren’t putting the user-first hat on your
Playwright scripts, you’ll also be a flakiness offender. The best way to speed
up and fight the flake is to rely on auto-waiting and web-first assertions and
let Playwright figure out the rest.

The example script from the beginning of this post includes a “simple”
click() instruction. And this click() is your best friend because it
executes magic, aka actionability checks.

// this click() will wait for the login to be


// - visible
// - stable, as in not animating or completed animation
// - able to receives events as in not obscured by other elements
// - enabled
await loginLink.click();

Whenever you call click() , fill() or the other actions, Playwright waits
until this element is ready for the user. At this point, the element is rendered,
visible, stable and enabled.

If your app now provides good UX and renders ready-to-use elements,


Playwright will interact with them as quickly as possible. There’s no need to
wait for any network requests.

Similarly, if you rely on web-first assertions, Playwright will wait until the UI
reaches your desired state. There’s no need to wait for HTML or API calls
behind a specific UI state either.

// wait until this element is visible


await expect(loginHeader).toBeVisible();

And if you’re relying on these two core Playwright principles, you can forget
the network layer and test what matters — UI actions and the resulting UI
state. There’s barely a need to wait for network events and requests.
https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 8/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

login.spec.js

import { expect, test } from "@playwright/test";

test("Login works", async ({ page }) => {


// don’t wait for all the resources to be loaded
await page.goto("/", {waitUntil: "commit"});

// let Playwright wait for this link to be visible


const loginLink = page.getByRole("link", { name: "Login" });
await loginLink.click();

const loginHeader = page.getByRole("heading", { name: "Login" });


await expect(loginHeader).toBeVisible();

// More things to check after the login link was clicked


// ...
});

Looking at the adjusted script, we’re not waiting for network events but for UI
state. Playwright will wait until the “Login” link is visible and click it as fast as
possible. And with this minor tweak, we made our test 10s quicker while still
covering the core login functionality. Win-win!

But... There’s always a but…


All that said, there are scenarios when you want to keep an eye on the
network.

When you adopt end-to-end testing, it’s very common to test preview
deployments to avoid core feature regressions. Ideally, your preview and
staging environments are production replicas. Unfortunately, that’s rarely the
case. Staging is often deployed to a different infrastructure, and the frontend
often loads different resources for tracking, user engagement and
monitoring.

And these differences might be okay because you only want to test your new
feature and avoid regressions. But when you go the extra mile and adopt
Playwright to monitor your sites, keeping an eye on all the loaded resources
will help you avoid production issues. I’ve seen a third-party script take down
production more than once.

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 9/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

For example, we at Checkly monitor checklyhq.com with Playwright, and like


every marketing site, we include Intercom and analytics there. One day, all our
synthetic Playwright checks failed because Intercom failed to load in a
reasonable time. page.goto() took more than a minute because of a timing-
out JavaScript snippet.

Was checklyhq.com broken? No, everything was still functioning. Was it


good to know that Intercom was having issues? You bet!

Monitoring the network layer can give you valuable insights into your site's
overall health and performance.

// fail when all resources aren’t loaded after 10 seconds


await page.goto("/", { waitUntil: "load", timeout: 10_000 });

Pro tip: Checkly aggregates Core Web Vitals in your Playwright scripts for
you.

Conclusion
Should you now flip every page.goto() action to commit or
domcontentloaded to save some time in CI/CD? The answer is the usual "It
depends".

If you value test execution speed, run many tests, and rely on user-first
testing with auto-waiting, not waiting for all resources to be loaded will save
you minutes, if not hours, in CI/CD. Give it a try, Playwright is very good at
figuring out when and what to click.

But remember that a green preview deployment light isn’t giving you a proper
safety net. The only thing that matters is a well-running production
environment. To ensure that there are no production issues, you must
continuously test your live product. This is when synthetic monitoring shines.

And when you're then testing and monitoring your site with Playwright,
keeping an eye on slow network dependencies can be very beneficial
because you’ll be the first to know when something’s off with your
infrastructure, the loaded third-party resources or your application code.
That’s the real safety net you need to sleep well at night.
https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 10/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

But as always, deciding what makes the most sense is up to you.

If you have any questions or comments, come and say hi in the Checkly
community. We’re a lovely bunch — I promise. And I’ll see you there!

Stefan Judis
Developer Relations

Share on social

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 11/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

Product Company Monitoring as code Learn


Monitoring as code About Checkly CLI Docs
Synthetic monitoring Careers Pulumi Provider Checkly Guides
API monitoring Blog Terraform Provider Playwright Tips
Alerting Security
Private locations Terms of use
Integrations Privacy
Dashboards
Live Checkly
dashboard
Changelog
Pricing
Status
Articles Connect How we compare
What is Synthetic Contact Us Alternative to
Monitoring? Support Datadog
What is API Slack Community Alternative to New
monitoring? Relic
Twitter @ChecklyHQ
What is Playwright? Alternative to
YouTube Dynatrace
A guide to
Monitoring as Code LinkedIn Alternative to
Why Monitoring as Public roadmap Pingdom
Code?
Cypress vs
Selenium vs
Playwright speed
comparison
n iz a t io n s
Or g a
ic e
rv
Se

OC |
fo r ns
S e rv t io
ic e Org a n iz a

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 12/13
10/10/24, 12:04 Why "page.goto()" is slowing down your Playwright tests

Copyright © 2024 Checkly Inc. All rights reserved.

https://www.checklyhq.com/blog/why-page-goto-is-slowing-down-your-playwright-test/ 13/13

You might also like