Step-by-Step Guide to Integrate BDD Behavior in Playwright with POM

This guide explains how to integrate:

  • Playwright
  • BDD (Behavior Driven Development)
  • Cucumber
  • Page Object Model (POM)

using JavaScript/TypeScript.

The framework structure will support:

  • Readable feature files
  • Reusable page objects
  • Clean step definitions
  • Scalable automation framework
  • HTML reports
  • Cross-browser execution

1. What You Will Build

You will create a framework like this:

PlaywrightBDDFramework/

├── features/
│ ├── login.feature
│ └── step-definitions/
│ └── login.steps.ts

├── pages/
│ └── LoginPage.ts

├── hooks/
│ └── hooks.ts

├── utils/
│ └── helper.ts

├── reports/

├── playwright.config.ts
├── cucumber.js
├── package.json
└── tsconfig.json

2. Install Node.js

Install Node.js from:

Node.js Official Website

Verify installation:

node -v
npm -v

3. Create Project

mkdir PlaywrightBDDFramework
cd PlaywrightBDDFramework

Initialize project:

npm init -y

4. Install Required Dependencies

Install Playwright

npm install -D @playwright/test

Install browsers:

npx playwright install

Install Cucumber + TypeScript Support

npm install -D @cucumber/cucumber
npm install -D typescript ts-node
npm install -D @types/node

Install Reporting Packages

npm install -D multiple-cucumber-html-reporter
npm install -D cucumber-html-reporter

5. Configure TypeScript

Create:

tsconfig.json

{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"types": ["node"],
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true
}
}

6. Configure Cucumber

Create:

cucumber.js

module.exports = {
default: {
require: [
"features/step-definitions/*.ts",
"hooks/*.ts"
],
format: [
"progress",
"json:reports/cucumber-report.json"
],
requireModule: ["ts-node/register"],
paths: ["features/*.feature"]
}
};

7. Create Playwright Config

playwright.config.ts

import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './features',
timeout: 60000,
use: {
headless: false,
screenshot: 'only-on-failure',
video: 'retain-on-failure'
}
});

8. Create Feature File

features/login.feature

Feature: Login Functionality

Scenario: Successful Login

Given User launches the application
When User enters username and password
And User clicks on login button
Then User should navigate to dashboard

9. Create Page Object Model (POM)

pages/LoginPage.ts

import { Page } from '@playwright/test';

export class LoginPage {

constructor(private page: Page) {}

username = '#username';
password = '#password';
loginBtn = '#loginBtn';

async launchApplication() {
await this.page.goto('https://example.com');
}

async enterUsername(username: string) {
await this.page.fill(this.username, username);
}

async enterPassword(password: string) {
await this.page.fill(this.password, password);
}

async clickLogin() {
await this.page.click(this.loginBtn);
}
}

10. Create Hooks File

Hooks help initialize browser and cleanup.

hooks/hooks.ts

import {
Before,
After,
BeforeAll,
AfterAll
} from '@cucumber/cucumber';

import { chromium, Browser, Page } from '@playwright/test';

let browser: Browser;
let page: Page;

BeforeAll(async () => {
browser = await chromium.launch({
headless: false
});
});

Before(async function () {
const context = await browser.newContext();
page = await context.newPage();

this.page = page;
});

After(async function () {
await page.close();
});

AfterAll(async () => {
await browser.close();
});

11. Create Step Definitions

features/step-definitions/login.steps.ts

import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from '@playwright/test';

import { LoginPage } from '../../pages/LoginPage';

let loginPage: LoginPage;

Given('User launches the application', async function () {

loginPage = new LoginPage(this.page);

await loginPage.launchApplication();
});

When('User enters username and password', async function () {

await loginPage.enterUsername('admin');

await loginPage.enterPassword('admin123');
});

When('User clicks on login button', async function () {

await loginPage.clickLogin();
});

Then('User should navigate to dashboard', async function () {

await expect(this.page).toHaveURL(/dashboard/);
});

12. Add Scripts in package.json

Update:

package.json

"scripts": {
"test": "cucumber-js",
"test:headed": "cucumber-js --tags '@SmokeTest'",
"report": "node report.js"
}

13. Execute Tests

Run:

npm test

14. Generate HTML Reports

Create:

report.js

const report = require('multiple-cucumber-html-reporter');

report.generate({
jsonDir: 'reports',
reportPath: 'reports/html-report',
metadata: {
browser: {
name: 'chrome',
version: 'latest'
},
device: 'Local Machine',
platform: {
name: 'windows',
version: '11'
}
}
});

Run:

node report.js

15. Add Tags in Feature Files

@SmokeTest
Feature: Login Functionality

Run specific tags:

npx cucumber-js --tags "@SmokeTest"

16. Add Environment Support

Create:

.env

BASE_URL=https://example.com
USERNAME=admin
PASSWORD=admin123

Install dotenv:

npm install dotenv

Use:

import dotenv from 'dotenv';

dotenv.config();

process.env.BASE_URL

17. Best Framework Structure

framework/

├── features/
├── pages/
├── hooks/
├── utils/
├── locators/
├── test-data/
├── reports/
├── screenshots/
├── videos/
├── logs/
└── config/

18. Advanced Improvements

You can enhance the framework with:

FeatureBenefit
Parallel ExecutionFaster execution
CI/CD IntegrationAutomated pipeline
Retry LogicStable execution
API + UI FrameworkHybrid testing
Docker SupportEasy setup
Allure ReportsBetter reporting
Faker DataDynamic test data
Database ValidationEnd-to-end validation

19. Real-Time Industry Best Practices

Use Separate Layers

Page Layer

  • Locators
  • Page actions

Step Definition Layer

  • BDD mapping only

Utility Layer

  • Reusable functions

Test Data Layer

  • JSON/CSV/Excel data

20. Recommended Design Pattern

Hybrid Framework

Combine:

  • POM
  • BDD
  • Data-Driven
  • Utility Helpers
  • API Helpers
  • Reporting
  • CI/CD

21. Sample Execution Flow

Feature File

Step Definition

Page Object

Playwright Actions

Browser Execution

22. Advantages of BDD with POM

BDDPOM
Readable scenariosReusable code
Business friendlyMaintainable
Better collaborationEasy scaling
Easy reportingCleaner structure

23. Common Interview Questions

What is BDD?

BDD is a development approach where application behavior is written in simple language using Gherkin syntax.


Why use POM?

POM improves:

  • Reusability
  • Maintainability
  • Scalability

Difference Between Playwright Test and Cucumber?

Playwright TestCucumber
TechnicalBusiness readable
Fast executionBDD support
Built-in fixturesGherkin support

24. Recommended Learning Path

  1. Playwright Basics
  2. TypeScript Fundamentals
  3. POM Design
  4. BDD Concepts
  5. Cucumber Framework
  6. Reporting
  7. CI/CD
  8. Docker
  9. API Automation
  10. AI-assisted Automation

25. Official Documentation

Leave a Comment