Playwright Tutorial 2025 : Writing Your First Tests

February 24, 2025

In this module we're looking at writing our first tests in Playwright. We'll look at the structure of a a Playwright script and see learn about the basic functions used to construct tests.

Keep in mind though, that in many respects Playwright is no different to any other automation tool. Everything always boils down to three parts. You need to…

1. identify objects      (use locators to identify an element)
2. interact with objects (use a method to interact)
3. inspect objects       (inspect properties to verify)

For example you'll want to use selectors to identify an object. Then use object methods to interact with an object. For example click a button. Then you'll need to Inspect an object to check it's in the right state. For example check a property of the object.

I like to think of this as the I³ (I cubed) of Test Automation:

Identify x Interact x Inspect = I³

Let's see how this applies to Playwright then.

Test Specification Structure

If drill into one of the tests folders in a project and look at an example test.

Playwright Tests Folder

Then pick out a test specification like this one:

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

test('has title', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');

  // Click the get started link.
  await page.getByRole('link', { name: 'Get started' }).click();

  // Expects page to have a heading with the name of Installation.
  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
    
});

You'll see that the structure of a test specification can be broken down into a number of areas. We have:

  • Import Statements used to import modules from the playwright packages (more on this in a moment)
  • Method declarations that start with the word “test" that are used to define what your test does.

So each test that we create will start with a “test" statement. You'll see that we've got two tests in this particular example. If we look at this second test example then, we've got the name of the test, “get started link", and we've got an async statement (more about “async" later).

Basic Playwright Test Structure

Now you'll notice that each test conforms to this I³ concept. Identify, interact, and inspect.

Test Specification I³ concept

For example in the 2nd test, shown above, we:

- IDENTIFY an object - a link object with the name get started. 
- INTERACT with that object - using the click method. 
- INSPECT that object - using the expect statement.

The Playwright Testing Running

In short – we're expecting the heading, with the name “Installation" to be visible.

Writing Your First Test

To write your first test follow these steps. In our new test we're going to open a new chrome browser and click the “Accept All" button

Writing Your First Playwright Test

To do this follow these steps…
1. Create your “Test Specification" file in the “Tests" directory

Create your Specification File

Or alternatively, open an existing spec file.

2. the import statement at the top of the file

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

This statement makes the “test" and “expect" methods available to your test specification file by importing the “@playwright/test" package.

test('Google Search', async ({ page }) => {

    // your test steps will go here

});

Your test() method takes two parameters. The title for the test and the test steps. We'll explain how this async function is used as a parameter to your test in later sessions.

For now though just make sure that you're clear that you're calling the Playwright “test" method with two parameters:

test(param1, param2)

Where param1 is the name of the test and param2 contains the test steps.

4. Build up your test by adding your navigation test step

test('Google Search', async ({ page }) => {

  await page.goto('https://google.com/');

});

Here we're using the goto() navigation method with the “page" fixture. For now think of a fixture as just an object that your test needs. In this example we need the 'page' object.

5. **Identify an object and Interact with it

Now we need to use a locator along with a method to click a button

test('Google Search', async ({ page }) => {

  await page.goto('https://google.com/');

  await page.getByRole('button', { name: 'Accept all' }).click();
    
});

Here we're using the 'page' fixture again but calling the getByRole() method to Identify and find the “Accept all" button. Then we're chaining in the click() method to interact and click the button.

6. Inspect an object to confirm a condition is met

Next we need to check the expected outcome after we've completed the previous steps.

test('Google Search', async ({ page }) => {

  await page.goto('https://google.com/');

  await page.getByRole('button', { name: 'Accept all' }).click();
    
  await expect(page.getByRole('img', { name: 'Google'})).toBeVisible();
    
});

Here we find the image with the name “Google" and use the expect() method chained to the toBeVisible() method to confirm that the Google logo image has been displayed. The expect() method has one parameter which is the object you want to confirm some condition of. In our case that condition is that the logo is visible.

And that's it. Your first test written.

Running Your First Test

There are many ways to run your tests in Playwright. For now though let's keep it simple. Just right click and select run from the line number bar next to your code

Running Your Playwright Test

We're going to look in much more detail at test execution in a future lesson.

In the next lesson, we're going to be looking at the Test Generator and recording tests using the Playwright recorder.