Amrou
Amrou

Reputation: 489

Run grouped tests sequentially using Playwright

I'm using Playwright with nodejs and I have grouped a couple of tests together like this

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

test.describe('Add a simple invoice test', () => {
    test('01.Login & add an invoice', async ({ page }) => {
        await page.goto("https://someUrl.com");
        await page.fill('input[id="email"]', "someEmailAddress");
        await page.fill('input[ng-model="ctrl.user.password"]', "somePassword");
        await page.click('button[id="login-btn"]');
    });

    test('02.Add an invoice', async ({ page }) => {
        await page.click('[name="invoice"]');
        await page.click('button[id="addInvoiceButton"]');
        await page.click('a[ng-click="ctrl.goToAddInvoice()"]');
        await page.fill('#invoiceTitle', Math.random().toString(36).substring(7));
        await page.fill('#exampleInputAmount', "120");
        await page.click("#invoiceCategory")
        await page.fill("#invoiceCategory > input", "Car")
        await page.keyboard.press("Enter");
        await page.click('button[id="submitInvoiceButton"]');
    });
});

The problem is that these 2 tests run in parallel whereas 02 is dependant on 01 since there's a required login.

How do I make 2 grouped tests run in the same context?

Upvotes: 20

Views: 33436

Answers (7)

Vishal Aggarwal
Vishal Aggarwal

Reputation: 4171

In order to run grouped tests sequentially , you may use the test.describe.configure method. This ensures that tests within the group run one after another, in the order they are defined as below:

 // Annotate tests as inter-dependent.
test.describe.configure({ mode: 'serial' });
test('runs first', async ({ page }) => {});
test('runs second', async ({ page }) => {});

Upvotes: 0

Ganesh H
Ganesh H

Reputation: 1787

The solution is very simple. It is executing as an independent test since you are passing {page} in each test, so if you want to use the same context for both the test you need to modify the test like below.

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

test.describe('Add a simple invoice test', () => {
  let page: Page;
  test.beforeAll(async ({ browser }) => {
    page = await browser.newPage();
  });

    test('01.Login & add an invoice', async () => { // do not pass page
        await page.goto("https://someUrl.com");
        await page.fill('input[id="email"]', "someEmailAddress");
        await page.fill('input[ng-model="ctrl.user.password"]', "somePassword");
        await page.click('button[id="login-btn"]');
    });

    test('02.Add an invoice', async () => { //do not pass page 
        await page.click('[name="invoice"]');
        await page.click('button[id="addInvoiceButton"]');
        await page.click('a[ng-click="ctrl.goToAddInvoice()"]');
        await page.fill('#invoiceTitle', Math.random().toString(36).substring(7));
        await page.fill('#exampleInputAmount', "120");
        await page.click("#invoiceCategory")
        await page.fill("#invoiceCategory > input", "Car")
        await page.keyboard.press("Enter");
        await page.click('button[id="submitInvoiceButton"]');
    });
});

This should work as you expected You can also refer to the Dzone Article regarding the same.

Note: Playwright doesn't recommend this approach but this answer should fulfill your need.

Upvotes: 18

d2vid
d2vid

Reputation: 2292

Unfortunately, browsers/OSes have global state such as clipboard contents, so you'll get race conditions if testing such features in parallel.

If all your tests are running in parallel, you've probably enabled parallelism in playwright config:

const config: PlaywrightTestConfig = {
  fullyParallel: true,
  ...

This is good - you should leave fullyParallel: true to execute your tests faster, and then opt-out of running the tests in a single file (or single describe block) serially by adding test.describe.configure({ mode: 'serial' }); like this:

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

test.describe('Add a simple invoice test', () => {
  test.describe.configure({ mode: 'serial' });

  test('01.Login & add an invoice', async ({ page }) => {
    await page.goto("https://someUrl.com");
    await page.fill('input[id="email"]', "someEmailAddress");
    await page.fill('input[ng-model="ctrl.user.password"]', "somePassword");
    await page.click('button[id="login-btn"]');
  });

  test('02.Add an invoice', async ({ page }) => {
    await page.click('[name="invoice"]');
    await page.click('button[id="addInvoiceButton"]');
    await page.click('a[ng-click="ctrl.goToAddInvoice()"]');
    await page.fill('#invoiceTitle', Math.random().toString(36).substring(7));
    await page.fill('#exampleInputAmount', "120");
    await page.click("#invoiceCategory")
    await page.fill("#invoiceCategory > input", "Car")
    await page.keyboard.press("Enter");
    await page.click('button[id="submitInvoiceButton"]');
  });
});

Read more in the playwright docs here: https://playwright.dev/docs/next/test-parallel#parallelize-tests-in-a-single-file

Upvotes: 15

michelle_c
michelle_c

Reputation: 1

the dzone article referenced in the checked answer uses typescript, but if you don't use typescript here's an example you can use on the playwright docs: https://playwright.dev/docs/test-parallel#serial-mode

Upvotes: -1

Dave Lee
Dave Lee

Reputation: 516

You can split the file and run it separately too.

  1. test1.ts
import { test, expect } from '@playwright/test';

test('01.Login & add an invoice', async ({ page }) => {
    await page.goto("https://someUrl.com");
    await page.fill('input[id="email"]', "someEmailAddress");
    await page.fill('input[ng-model="ctrl.user.password"]', "somePassword");
    await page.click('button[id="login-btn"]');
});
  1. test2.ts
import { test, expect } from '@playwright/test';

test('02.Add an invoice', async ({ page }) => {
    await page.click('[name="invoice"]');
    await page.click('button[id="addInvoiceButton"]');
    await page.click('a[ng-click="ctrl.goToAddInvoice()"]');
    await page.fill('#invoiceTitle', Math.random().toString(36).substring(7));
    await page.fill('#exampleInputAmount', "120");
    await page.click("#invoiceCategory")
    await page.fill("#invoiceCategory > input", "Car")
    await page.keyboard.press("Enter");
    await page.click('button[id="submitInvoiceButton"]');
});

And then run it like:

npx playwright test test1.ts

npx playwright test test2.ts

or depending on your setting it could also be like:

pnpm -C test test1.ts

pnpm -C test test2.ts

Upvotes: -2

sahmeepee
sahmeepee

Reputation: 532

If you have a bunch of tests that have common setup steps then Playwright Test Runner has some pre-canned features you can use to either run once before all the tests (test.beforeAll) or alternatively before each test (test.beforeEach).

Docs for that are here: https://playwright.dev/docs/test-intro#use-test-hooks

There are similar options for teardown, so they could be something simple like going to the login page and logging in (then logging out at the end?), or something more complex like setting up data and clearing it down after the test.

Upvotes: -1

hardkoded
hardkoded

Reputation: 21597

You shouldn't make your tests depend on each other. For example, I would extract the common login to a function and call that function from both tests. You could even add some asserts to the first test to check that the login worked. But you wouldn't do that on the second one.

Upvotes: 7

Related Questions