Sponsored Link
Looking for a unified way to  viewmonitor, and  debug Playwright Test Automation runs?
Try the Playwright Dashboard by today. Use the coupon code PWSOL10 for a 12 month 10% discount.

How to Run a Specific Spec File in Playwright Tests Sequentially

If you've ever been in a scenario where a test you were writing changed the state of the system or user in a way where other tests would fail? This solution may help you. While I am a big fan of running my tests at the same time in parallel there times where this may not be feasible. This is typically when you have a state that needs to be consistent.

Scenario

We'll use the repo linked below and use the account.spec.ts to demonstrate the functionality.

GitHub - playwrightsolutions/playwright-practicesoftwaretesting.com: Example using Playwright against site https://practicesoftwaretesting.com
Example using Playwright against site https://practicesoftwaretesting.com - playwrightsolutions/playwright-practicesoftwaretesting.com

The code we will run is listed below. Notice the below there are 3 tests.

  • In the first test we don't make any changes to any data we only make assertions.
  • In the second test we make a change to the first name, last name, and street 1 address.
  • In the third test we don't make any changes to any data only make an assertion.

The problem here is that the 2nd test changes data that test 1 and test 3 rely on "Jane Doe" first and last name.

//tests/account/account.spec.ts

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

test.describe("Customer 01 my account specs", () => {
  test.use({ storageState: ".auth/customer01.json" });

  test.afterEach(async ({ page }) => {
    await page.goto("/account/profile");
    await page.waitForLoadState("networkidle");
    await page.getByTestId("first-name").fill("Jane");
    await page.getByTestId("last-name").fill("Doe");
    await page.getByTestId("address").fill("101 Testing Way");
    await page.getByTestId("update-profile-submit").click();
    await expect(
      page.getByRole("alert").filter({ hasText: "successfully" })
    ).toBeVisible();
  });

  test("validate customer 01 my account page", async ({ page }) => {
    await page.goto("/account");

    expect(await page.getByTestId("nav-menu").innerText()).toContain(
      "Jane Doe"
    );
    expect(await page.getByTestId("page-title").innerText()).toContain(
      "My account"
    );
    expect(await page.getByTestId("nav-favorites").innerText()).toContain(
      "Favorites"
    );
  });

  test("update customer 01 account", async ({ page }) => {
    await page.goto("account/profile");

    await page.waitForLoadState("networkidle");
    await page.getByTestId("first-name").fill("Testy");
    await page.getByTestId("last-name").fill("McTesterface");
    await page.getByTestId("address").fill("101 Testing Way");

    await page.getByTestId("update-profile-submit").click();
    await expect(
      page.getByRole("alert").filter({ hasText: "successfully" })
    ).toBeVisible();

    // Assert the updated name is displayed in the nav menu
    await page.reload();
    expect(await page.getByTestId("nav-menu").innerText()).toContain(
      "Testy McTesterface"
    );

    await expect(page.getByTestId("first-name")).toHaveValue("Testy");
    await expect(page.getByTestId("last-name")).toHaveValue("McTesterface");
    await expect(page.getByTestId("address")).toHaveValue("101 Testing Way");
  });

  test("validate customer 01 account other", async ({ page }) => {
    await page.goto("/account");

    expect(await page.getByTestId("nav-menu").innerText()).toContain(
      "Jane Doe"
    );
  });
});

Running the tests without options

npx playwright test tests/account/account.spec.ts

When running my tests with my default playwright.config.ts, the test ran with 3 workers 1 test for each, and all tests ran at the same time.

When running the tests you can see that the first test failed, and the 2nd test passed. This is because the afterEach block will actually reset the data for every test. I could make this where it only runs the afterEach based on the title see A Better Way to Control Before and After Blocks with Test Titles article.

Now I could go to my playwright.config.ts file and update the amount of workers that should run and set to 1, or change fullyParallel option to false but this would increase the full time of all of my tests running.

The good news is there is another option, to limit the way our tests run from within a test.describe() block.

Running the tests with "default" configuration option

To configure this add the line test.describe.configure({ mode: "default" }); within your describe block. The docs for this walk through the different options.

//tests/account/account.spec.ts

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

test.describe("Customer 01 my account specs", () => {

  test.describe.configure({ mode: "default" });
...

This default option will allow tests to run one at a time in order within the describe block of a spec file. This allows you to override the default configuration for the rest of your test suite for a specific set of tests.

With this in place your tests are all passing again, and I still get the benefit of having the rest of my automation suite running in parallel.

There is another option for achieving the same result it is setting the test.describe.configure({ mode: "serial" }); The difference with using serial is if any of the tests fail while running in serial mode, the following tests that are apart of the describe block will be skipped. This could be useful if you have tests that build data for other tests, but that is a practice I would not recommend. Each test should create and cleanup it's own test data.

Big Thanks

One thing to note is the option default must be specified in the test if you want to use it, which is a bit counter intuitive as Stefan Judis in a recent LinkedIn post. He also covered this in a recent YouTube video. If you have a youtube account I would highly recommend subscribing to his channel, there has been some great Playwright content shared there!


Thanks for reading! If you found this helpful, reach out and let me know on LinkedIn or consider buying me a cup of coffee. If you want more content delivered to you in your inbox subscribe below, and be sure to leave a ❤️ to show some love.