PlayWright is a Web UI automation testing framework developed by Microsoft.
It aims to provide a cross-platform, cross-language, cross-browser automation testing framework that also supports mobile browsers.
As described on its official homepage:
- Automatic waiting, intelligent assertions for page elements, and execution tracing make it highly effective in handling the instability of web pages.
- It controls browsers in a process different from the one running the test, eliminating the limitations of in-process test runners and supporting Shadow DOM penetration.
- PlayWright creates a browser context for each test. A browser context is equivalent to a brand-new browser profile, enabling zero-cost full test isolation. Creating a new browser context takes just a few milliseconds.
- Provides features like code generation, step-by-step debugging, and trace viewer.
PlayWright vs. Selenium vs. Cypress
What are the best Web UI automation testing frameworks available today? The standout options include the decade-old Selenium, the recently popular Cypress, and the one we’re introducing here—PlayWright. How do they differ? Below is a summarized comparison for your reference
Feature | PlayWright | Selenium | Cypress |
---|---|---|---|
Supported Languages | JavaScript, Java, C#, Python | JavaScript, Java, C#, Python, Ruby | JavaScript/TypeScript |
Supported Browsers | Chrome, Edge, Firefox, Safari | Chrome, Edge, Firefox, Safari, IE | Chrome, Edge, Firefox, Safari |
Testing Framework | Frameworks for supported languages | Frameworks for supported languages | Frameworks for supported languages |
Usability | Easy to use and configure | Complex setup with a learning curve | Easy to use and configure |
Code Complexity | Simple | Moderate | Simple |
DOM Manipulation | Simple | Moderate | Simple |
Community Maturity | Improving gradually | Highly mature | Fairly mature |
Headless Mode Support | Yes | Yes | Yes |
Concurrency Support | Supported | Supported | Depends on CI/CD tools |
iframe Support | Supported | Supported | Supported via plugins |
Driver | Not required | Requires a browser-specific driver | Not required |
Multi-Tab Operations | Supported | Not supported | Supported |
Drag and Drop | Supported | Supported | Supported |
Built-in Reporting | Yes | No | Yes |
Cross-Origin Support | Supported | Supported | Supported |
Built-in Debugging | Yes | No | Yes |
Automatic Wait | Yes | No | Yes |
Built-in Screenshot/Video | Yes | No video recording | Yes |
Key Comparisons:
- Supported Languages: PlayWright and Selenium support Java, C#, and Python, making them more popular among test engineers who may not be familiar with JavaScript/TypeScript.
- Technical Approach: Both PlayWright and Selenium use Google’s Remote Debugging Protocol to control Chromium-based browsers. For browsers like Firefox, without such protocols, they use JavaScript injection. Selenium encapsulates this in a Driver, while PlayWright directly calls it. Cypress, on the other hand, uses JavaScript to control browsers.
- Browser Support: Selenium supports Internet Explorer, which is irrelevant as IE is being phased out.
- Ease of Use: All three frameworks have a learning curve. However, PlayWright and Cypress are more user-friendly for simple scenarios compared to Selenium.
Getting Started
Although PlayWright supports multiple languages, it heavily relies on Node.js. Regardless of whether you use the Python or Java version, PlayWright requires a Node.js environment during initialization, downloading a Node.js driver. Hence, we’ll focus on JavaScript/TypeScript for this guide.
Installation and Demo
- Ensure Node.js is installed.
- Initialize a PlayWright project using
npm
oryarn
:
# Using npm
npm init playwright@latest
# Using yarn
yarn create playwright
- Follow the prompts:
- Choose TypeScript or JavaScript (default: TypeScript).
- Specify the test directory name.
- Decide whether to install PlayWright-supported browsers (default: True).
If you choose to download browsers, PlayWright will download Chromium, Firefox, and WebKit, which may take some time. This process occurs only during the first setup unless the PlayWright version is updated.
Project Structure
After initialization, you’ll get a project template:
playwright.config.ts # PlayWright configuration file
package.json # Node.js configuration file
package-lock.json # Node.js dependency lock file
tests/ # Your test directory
example.spec.ts # Template test case
tests-examples/ # Example tests directory
demo-todo-app.spec.ts # Example test case
Run the example test case:
npx playwright test
The tests execute silently (in headless mode), and results are displayed as:
Running 6 tests using 6 workers
6 passed (10s)
To open the last HTML report run:
npx playwright show-report
Example Source Code
Here’s the example.spec.ts
test case:
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page).toHaveURL(/.*intro/);
});
- First Test: Verifies the page title contains "Playwright".
- Second Test: Clicks the "Get started" link and verifies the URL.
Each test
method has:
- A test name (e.g.,
'has title'
). - A function to execute the test logic.
Key methods include:
-
page.goto
: Navigates to a URL. -
expect(page).toHaveTitle
: Asserts the page title. -
page.getByRole
: Locates an element by its role. -
await
: Waits for asynchronous operations to complete.
Running Tests from the Command Line
Here are common commands:
- Run all tests:
npx playwright test
- Run a specific test file:
npx playwright test landing-page.spec.ts
- Debug a test case:
npx playwright test --debug
Code Recording
Use the codegen
feature to record interactions:
npx playwright codegen https://leapcell.io/
Recorded code can be copied into your files. Note: The recorder might not handle complex actions like hovering.
In-Depth Playwright Guide
Actions and Behaviors
This section introduces some typical Playwright actions for interacting with page elements. Note that the locator
object introduced earlier does not actually locate the element on the page during its creation. Even if the element doesn't exist on the page, using the element locator methods to get a locator
object won't throw any exceptions. The actual element lookup happens only during the interaction. This differs from Selenium's findElement
method, which directly searches for the element on the page and throws an exception if the element isn't found.
Text Input
Use the fill
method for text input, mainly targeting <input>
, <textarea>
, or elements with the [contenteditable]
attribute:
// Text input
await page.getByRole('textbox').fill('Peter');
Checkbox and Radio
Use locator.setChecked()
or locator.check()
to interact with input[type=checkbox]
, input[type=radio]
, or elements with the [role=checkbox]
attribute:
await page.getByLabel('I agree to the terms above').check();
expect(await page.getByLabel('Subscribe to newsletter').isChecked()).toBeTruthy();
// Uncheck
await page.getByLabel('XL').setChecked(false);
Select Control
Use locator.selectOption()
to interact with <select>
elements:
// Select by value
await page.getByLabel('Choose a color').selectOption('blue');
// Select by label
await page.getByLabel('Choose a color').selectOption({ label: 'Blue' });
// Multi-select
await page.getByLabel('Choose multiple colors').selectOption(['red', 'green', 'blue']);
Mouse Clicks
Basic operations:
// Left click
await page.getByRole('button').click();
// Double click
await page.getByText('Item').dblclick();
// Right click
await page.getByText('Item').click({ button: 'right' });
// Shift+click
await page.getByText('Item').click({ modifiers: ['Shift'] });
// Hover
await page.getByText('Item').hover();
// Click at specific position
await page.getByText('Item').click({ position: { x: 0, y: 0 } });
For elements covered by others, use force click:
await page.getByRole('button').click({ force: true });
Or trigger the click event programmatically:
await page.getByRole('button').dispatchEvent('click');
Typing Characters
The locator.type()
method simulates typing character-by-character, triggering keydown
, keyup
, and keypress
events:
await page.locator('#area').type('Hello World!');
Special Keys
Use locator.press()
for special keys:
// Enter key
await page.getByText('Submit').press('Enter');
// Ctrl+Right Arrow
await page.getByRole('textbox').press('Control+ArrowRight');
// Dollar key
await page.getByRole('textbox').press('$');
Supported keys include Backquote
, Minus
, Equal
, Backslash
, Backspace
, Tab
, Delete
, Escape
, ArrowDown
, End
, Enter
, Home
, Insert
, PageDown
, PageUp
, ArrowRight
, ArrowUp
, F1-F12
, Digit0-Digit9
, and KeyA-KeyZ
.
File Upload
Use locator.setInputFiles()
to specify files for upload. Multiple files are supported:
// Upload a file
await page.getByLabel('Upload file').setInputFiles('myfile.pdf');
// Upload multiple files
await page.getByLabel('Upload files').setInputFiles(['file1.txt', 'file2.txt']);
// Remove files
await page.getByLabel('Upload file').setInputFiles([]);
// Upload from buffer
await page.getByLabel('Upload file').setInputFiles({
name: 'file.txt',
mimeType: 'text/plain',
buffer: Buffer.from('this is test')
});
Focus Element
Use locator.focus()
to focus on an element:
await page.getByLabel('Password').focus();
Drag and Drop
The drag-and-drop process involves four steps:
- Hover the mouse over the draggable element.
- Press the left mouse button.
- Move the mouse to the target position.
- Release the left mouse button.
You can use the locator.dragTo()
method:
await page.locator('#item-to-be-dragged').dragTo(page.locator('#item-to-drop-at'));
Alternatively, manually implement the process:
await page.locator('#item-to-be-dragged').hover();
await page.mouse.down();
await page.locator('#item-to-drop-at').hover();
await page.mouse.up();
Dialog Handling
By default, Playwright automatically cancels dialogs like alert
, confirm
, and prompt
. You can pre-register a dialog handler to accept dialogs:
page.on('dialog', dialog => dialog.accept());
await page.getByRole('button').click();
Handling New Pages
When a new page pops up, you can use the popup
event to handle it:
const newPagePromise = page.waitForEvent('popup');
await page.getByText('Click me').click();
const newPage = await newPagePromise;
await newPage.waitForLoadState();
console.log(await newPage.title());
The Best Platform for Playwright: Leapcell
Leapcell is a modern cloud computing platform designed for distributed applications. It adopts a pay-as-you-go model with no idle costs, ensuring you only pay for the resources you use.
Unique Benefits of Leapcell for Playwright Applications
-
Cost Efficiency
- Pay-as-you-go: Avoid resource waste during low traffic and scale up automatically during peak times.
- Real-world example: For example, on getdeploying.com’s calculations, renting a 1 vCPU and 2 GB RAM virtual machine in traditional cloud services costs around $25 per month. On Leapcell, $25 can support a service handling 6.94 million requests with an average response time of 60 ms, giving you better value for money.
-
Developer Experience
- Ease of use: Intuitive interface with minimal setup requirements.
- Automation: Simplifies development, testing, and deployment.
- Seamless integration: Supports Go, Python, Node.js, Rust, and more.
-
Scalability and Performance
- Auto-scaling: Dynamically adjusts resources to maintain optimal performance.
- Asynchronous optimization: Handles high-concurrency tasks with ease.
- Global reach: Low-latency access supported by distributed data centers.
For more deployment examples, refer to the documentation.
Top comments (0)