Learn to manage Playwright timeouts in testing and web scraping with tips on optimizing locators, setting timeouts, mocking endpoints, retries, and splitting tests.
When you're working with Playwright, you'll often come across timeouts that can interrupt your testing or web scraping. In this post, we’ll explore the causes of these timeouts and provide a few tips and solutions to help you overcome them.
What is a timeout in Playwright?
A timeout occurs when an action or a test takes longer than the specified time limit to complete. By default, Playwright sets a test timeout of 30 seconds and an assertion timeout of 5 seconds. If an action exceeds these limits, Playwright throws a timeout error.
Common causes of timeouts
Several factors can cause timeouts in Playwright:
Slow test execution: Tests that perform many actions or interact with complex web elements may take longer to complete.
Incorrect locators: Using incorrect or inefficient locators can slow down the test as Playwright struggles to find the element.
Slow backend responses: If your application relies on backend services, slow responses from these services can delay test execution.
How to change timeout settings
Global timeout
To change the global timeout for all tests, just update your playwright.config.js file:
module.exports = {
globalTimeout: 60000 // Sets global timeout to 60 seconds
};
Specific test timeout
For individual tests, use the test.setTimeout method:
test('example test', async ({ page }) => {
test.setTimeout(45000); // Sets timeout to 45 seconds for this test
// Test code here
});
Assertion timeout
To adjust the timeout for assertions, use the expect function’s timeout option:
For tests that occasionally fail due to timeouts, use retries to give them another chance to pass:
test.describe('Retry mechanism', () => {
test.describe.configure({ retries: 2 }); // Retry the tests in this describe block up to 2 times
test('flaky test', async ({ page }) => {
await page.goto('https://example.com');
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});
});
Split long tests
Divide long tests into smaller, more manageable tests. This helps isolate issues and reduces the chance of hitting timeouts:
// Split the long test into smaller tests
test.describe('Website Navigation Tests', () => {
// Part 1: Navigate to the homepage
test('Navigate to homepage', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example Domain/);
});
// Part 2: Navigate to the about page
test('Navigate to about page', async ({ page }) => {
await page.goto('https://example.com/about');
await expect(page.locator('h1')).toHaveText('About Us');
});
// Part 3: Navigate to the contact page and submit the form
test('Navigate to contact page and submit form', async ({ page }) => {
await page.goto('https://example.com/contact');
await page.fill('#name', 'John Doe');
await page.fill('#email', 'john.doe@example.com');
await page.click('button[type="submit"]');
await expect(page.locator('.success')).toHaveText('Thank you for contacting us!');
});
});
Effectively managing Playwright timeouts
Dealing with Playwright timeouts involves understanding their causes and implementing the right solutions. Optimizing locators, setting appropriate timeouts for different actions, mocking slow endpoints, using retries for flaky tests, and splitting long tests will help you with your tests and make sure that Playwright plays nicely.
Apifier since 2016 so learned about web scraping and automation from the experts. MSc in Computer Science from TCD. Former game designer and newspaper production manager. Now Head of Content at Apify.