Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reverse mode: auto-generate BDD scenarios #30

Open
vitalets opened this issue Jun 29, 2023 · 3 comments
Open

Reverse mode: auto-generate BDD scenarios #30

vitalets opened this issue Jun 29, 2023 · 3 comments
Labels

Comments

@vitalets
Copy link
Owner

In Playwright there is a codegen feature that generates test-code while you perform actions in browser. What I'm thinking about is to generate BDD code in some similar way.

Imagine the following scenario:

  1. open todo app
  2. create two todos
  3. mark the first todo as completed
  4. filter only completed todos

In codegen mode Playwright will generate the test:

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

test('test', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc/#/');
  await page.getByPlaceholder('What needs to be done?').fill('todo 1');
  await page.getByPlaceholder('What needs to be done?').press('Enter');
  await page.getByPlaceholder('What needs to be done?').fill('todo 2');
  await page.getByPlaceholder('What needs to be done?').press('Enter');
  await expect(page.getByTestId('todo-title')).toHaveCount(2); // <- added manually
  await page.getByRole('listitem').filter({ hasText: 'todo 1' }).getByRole('checkbox', { name: 'Toggle Todo' }).check();
  await page.getByRole('link', { name: 'Completed' }).click();
  await expect(page.getByTestId('todo-title')).toHaveCount(1); // <- added manually
});

The code looks rather structured and it would be possible to convert it into BDD scenario:

Scenario: Scenario 1
    Given I am on page "https://demo.playwright.dev/todomvc/#/"
    When I fill "todo 1" and press Enter
    And I fill "todo 2" and press Enter
    Then Count of "todo-title" equals to 2
    When I enable checkbox for "todo 1"
    And I click on "Completed"
    Then Count of "todo-title" equals to 1

Necessary step definitions can be generated as well:

Given('I am on page {string}', async ({ page }, url: string) => {
  await page.goto(url);
});

When('I fill {string} and press Enter', async ({ page }, text: string) => {
  await page.getByPlaceholder('What needs to be done?').fill(text);
  await page.getByPlaceholder('What needs to be done?').press('Enter');
});

Then('Count of {string} equals to {int}', async ({ page }, testId: string, count: number) => {
  await expect(page.getByTestId(testId)).toHaveCount(count);
});

When('I enable checkbox for {string}', async ({ page }, hasText: string) => {
  await page.getByRole('listitem').filter({ hasText }).getByRole('checkbox', { name: 'Toggle Todo' }).check();
});

When('I click on {string}', async ({ page }, name: string) => {
  await page.getByRole('link', { name }).click();
});

If I record second scenario existing step definitions can be reused.

I feel that there can be edge cases, but developer can always fix it manually.
In general having such easy way to generate BDD scenarios looks useful to define project requirements and behavior.

Would appreciate your thoughts on that :)

@vitalets
Copy link
Owner Author

I've also found that there is jsonl output for Playwright's codegen, that can be turned into BDD steps with less effort.
for the scenario above jsonl output is the following:

{"browserName":"chromium","launchOptions":{"headless":false},"contextOptions":{}}
{"name":"openPage","url":"about:blank","signals":[],"pageAlias":"page"}
{"name":"navigate","url":"https://demo.playwright.dev/todomvc/","signals":[],"pageAlias":"page"}
{"name":"navigate","url":"https://demo.playwright.dev/todomvc/#/","signals":[],"pageAlias":"page"}
{"name":"fill","selector":"internal:attr=[placeholder=\"What needs to be done?\"i]","signals":[],"text":"todo 1","pageAlias":"page","locator":{"kind":"placeholder","body":"What needs to be done?","options":{"exact":false}}}
{"name":"press","selector":"internal:attr=[placeholder=\"What needs to be done?\"i]","signals":[],"key":"Enter","modifiers":0,"pageAlias":"page","locator":{"kind":"placeholder","body":"What needs to be done?","options":{"exact":false}}}
{"name":"fill","selector":"internal:attr=[placeholder=\"What needs to be done?\"i]","signals":[],"text":"todo 2","pageAlias":"page","locator":{"kind":"placeholder","body":"What needs to be done?","options":{"exact":false}}}
{"name":"press","selector":"internal:attr=[placeholder=\"What needs to be done?\"i]","signals":[],"key":"Enter","modifiers":0,"pageAlias":"page","locator":{"kind":"placeholder","body":"What needs to be done?","options":{"exact":false}}}
{"name":"check","selector":"internal:role=listitem >> internal:has-text=\"todo 1\"i >> internal:role=checkbox[name=\"Toggle Todo\"i]","signals":[],"pageAlias":"page","locator":{"kind":"role","body":"listitem","options":{"attrs":[]},"next":{"kind":"has-text","body":"todo 1","options":{"exact":false},"next":{"kind":"role","body":"checkbox","options":{"attrs":[],"exact":false,"name":"Toggle Todo"}}}}}
{"name":"click","selector":"internal:role=link[name=\"Completed\"i]","signals":[{"name":"navigation","url":"https://demo.playwright.dev/todomvc/#/completed"}],"button":"left","modifiers":0,"clickCount":1,"pageAlias":"page","locator":{"kind":"role","body":"link","options":{"attrs":[],"exact":false,"name":"Completed"}}}

@NikkTod
Copy link
Sponsor

NikkTod commented Jun 30, 2023

This feature looks really nice, unfortunatelly not every project/webpage have good locators, so could be tricky for implementation.

@PavanMudigonda
Copy link

Really awesome idea but could be tough to develop

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants