LearnCen Docs
Guides 7 min read

Playwright + Cucumber BDD Testing Environment

Enterprise BDD test automation with Playwright, Cucumber.js, Gherkin syntax, TypeScript, cross-browser support, and Allure reporting.

What's Inside

Tool Version Purpose
Node.js 20 LTS JavaScript runtime
TypeScript Latest Type-safe step definitions
Playwright Latest Cross-browser automation engine
Cucumber.js 10.x BDD framework with Gherkin syntax
Chromium Pre-installed Google Chrome browser engine
Firefox Pre-installed Mozilla browser engine
WebKit Pre-installed Safari browser engine
Allure CLI Latest Advanced test reporting
noVNC Latest Watch tests run in a real browser via GUI

Quick Start

# Start the demo e-commerce app
bdd-app &

# Run all BDD scenarios
bdd-run

# Run by tag
bdd-tag smoke

# Run with visible browser (via noVNC)
bdd-headed

# Run + generate HTML report
bdd-report

# Scaffold a new feature
bdd-init checkout

# Show all commands
bdd-help

Helper Commands

Test Execution

Command What it does
bdd-run [file] Run all Cucumber scenarios
bdd-headed [file] Run with visible browser (noVNC)
bdd-tag <tag> Run scenarios by tag (@smoke, @login)
bdd-feature <file> Run a specific feature file
bdd-dry Dry run — check step bindings without executing

Reports

Command What it does
bdd-report Run tests + generate HTML report
bdd-open-report Serve existing report on port 9323

Tools & Scaffolding

Command What it does
bdd-app Start TechMart demo app on port 3000
bdd-init <name> Scaffold new feature file + step definitions
bdd-help Show all available commands

npm Scripts

Command What it does
npm test Run all Cucumber scenarios
npm run test:smoke Run @smoke tagged scenarios
npm run test:regression Run @regression tagged scenarios
npm run test:report Run + generate JSON and HTML reports
npm run test:dry Dry run (validate step bindings)

Project Structure

workspace/
├── features/               # Gherkin .feature files
│   ├── login.feature       # Login scenarios (smoke + regression)
│   ├── api.feature         # API testing scenarios
│   └── steps/              # Step definitions (TypeScript)
│       ├── login.steps.ts
│       └── api.steps.ts
├── pages/                  # Page Object Model classes
│   └── LoginPage.ts
├── support/                # Hooks, world, fixtures
│   ├── world.ts            # Playwright World (browser/page lifecycle)
│   └── hooks.ts            # Before/After hooks with screenshot on failure
├── reports/                # Generated HTML + JSON reports
├── demo-app/               # TechMart e-commerce app (for practice)
├── cucumber.js             # Cucumber configuration
├── tsconfig.json           # TypeScript configuration
├── package.json            # Dependencies and scripts
└── .env                    # Environment variables (BASE_URL, API_URL)

Demo App — TechMart E-Commerce Store

The workspace includes a built-in demo e-commerce app for practicing BDD scenarios:

bdd-app &
# Starts at http://localhost:3000

Practice elements include:

  • Product grid with search, filter, and sort
  • Shopping cart sidebar with quantity controls
  • Checkout form with validation
  • Tabs, modals, toasts, and dropdowns
  • All elements have data-testid attributes for reliable locators

Use this app to write your own Gherkin scenarios without needing an external website.

Tagging Convention

@smoke           # Quick validation tests (run first in CI)
@regression      # Full regression suite
@login @checkout # Feature-specific tags
@api             # API-only tests (no browser needed)
@wip             # Work in progress (skipped in CI)

Run by tag:

bdd-tag smoke         # Runs all @smoke scenarios
bdd-tag @login        # Runs all @login scenarios
bdd-tag "not @wip"    # Runs everything except @wip

Writing Your First Feature

1. Create a feature file

# features/homepage.feature
Feature: Homepage
  As a visitor
  I want to see the homepage
  So that I can navigate the site

  @smoke
  Scenario: Page loads with correct title
    Given I navigate to "https://playwright.dev"
    Then the page title should contain "Playwright"

2. Create step definitions

// features/steps/homepage.steps.ts
import { Given, Then } from "@cucumber/cucumber";
import { expect } from "@playwright/test";
import { BDDWorld } from "../support/world";

Given("I navigate to {string}", async function (this: BDDWorld, url: string) {
  await this.page.goto(url);
});

Then("the page title should contain {string}", async function (this: BDDWorld, title: string) {
  await expect(this.page).toHaveTitle(new RegExp(title));
});

3. Run

bdd-run

Page Object Model (POM)

The workspace includes a LoginPage POM example at pages/LoginPage.ts. Use this pattern to keep step definitions thin and page logic reusable:

// pages/CheckoutPage.ts
import { Page, Locator, expect } from "@playwright/test";

export class CheckoutPage {
  private readonly nameInput: Locator;
  private readonly submitBtn: Locator;

  constructor(private readonly page: Page) {
    this.nameInput = page.getByLabel("Full Name");
    this.submitBtn = page.getByRole("button", { name: "Place Order" });
  }

  async fillName(name: string) {
    await this.nameInput.fill(name);
  }

  async submit() {
    await this.submitBtn.click();
  }
}

Then use it in steps:

import { CheckoutPage } from "../../pages/CheckoutPage";

When("I fill in the checkout form", async function (this: BDDWorld) {
  const checkout = new CheckoutPage(this.page);
  await checkout.fillName("John Doe");
  await checkout.submit();
});

Scenario Outlines (Data-Driven Testing)

Use Scenario Outlines with Examples tables for parameterized tests:

Scenario Outline: Login with multiple credentials
  Given I am on the login page
  When I enter username "<username>" and password "<password>"
  And I click the login button
  Then I should see "<result>"

  Examples:
    | username  | password              | result        |
    | tomsmith  | SuperSecretPassword!  | secure area   |
    | invalid   | wrong                 | error message |

Each row becomes a separate test — great for covering multiple data combinations.

API Testing with Cucumber

The environment supports API testing using Playwright's request context:

@api
Scenario: GET all posts
  Given the API base URL is "https://jsonplaceholder.typicode.com"
  When I send a GET request to "/posts"
  Then the response status should be 200
  And the response should contain more than 0 items

API tests use Playwright's built-in HTTP client — no extra dependencies needed.

Watching Tests Run (noVNC)

To see tests execute in a real browser:

  1. Run bdd-headed
  2. Open the noVNC URL (port 10000) — append /vnc.html?autoconnect=true
  3. Watch Chromium execute your BDD scenarios in real-time

noVNC is especially useful for debugging visual steps (clicks, fills, navigations) that don't work as expected.

noVNC Troubleshooting

Issue Solution
Failed to connect Xvfb or x11vnc not running — restart the workspace
Address already in use pkill -9 x11vnc; pkill -9 Xvfb; pkill -9 websockify
Black screen Restart Xvfb: Xvfb :99 -screen 0 1920x1080x24 &

Reports

HTML Report (built-in)

bdd-report
# Output: reports/cucumber-report.html

Serve Report

bdd-open-report
# Opens on port 9323

Allure Report

The workspace has allure-cucumberjs configured. Allure generates rich reports with:

  • Step-by-step breakdowns
  • Screenshots on failure (auto-captured via hooks)
  • Duration analytics
  • Retry history

Environment Configuration

The workspace uses .env files for environment-specific settings:

# .env
BASE_URL=https://the-internet.herokuapp.com
API_URL=https://jsonplaceholder.typicode.com
HEADLESS=true

Override for different environments by editing .env or passing env vars:

BASE_URL=https://staging.myapp.com bdd-run

VS Code Extensions (Pre-installed)

Extension Purpose
Cucumber Official Gherkin syntax highlighting + step navigation
Cucumber Autocomplete Auto-complete for step definitions
Python (ms-python) General IDE support

Keyboard shortcuts:

  • Ctrl+Shift+B — Run tests + report (default build task)
  • Ctrl+Shift+T — Run all tests (default test task)

Mastery Framework

Each workspace includes a Mastery.md file with:

  • Engineering standards — BDD best practices, Gherkin anti-patterns to avoid, step definition conventions
  • AI assistant rules — OpenCode acts as a Principal BDD Engineer, enforces Given/When/Then discipline
  • Prompt templates — Examples of effective prompts for generating features and step definitions
  • Lab checklist — Concrete tasks to prove mastery (e.g., write a Scenario Outline, use Background keyword, implement hooks with screenshot-on-failure)

Open Mastery.md in your workspace to see the full framework.

Tips

  • bdd-init <name> scaffolds both a .feature file and matching .steps.ts — saves setup time
  • Cucumber auto-discovers step files from features/steps/ — no imports needed
  • The BDDWorld class gives every step access to this.page, this.context, and this.browser
  • Screenshots are auto-captured on failure via the hooks in support/hooks.ts
  • Use {string}, {int}, {float} parameter types in step definitions for type safety
  • bdd-dry validates all steps are bound without executing tests — useful for CI pre-checks

Security

  • Root access is restricted. Use sudo apt install <package> for system packages.
  • npm, npx, and yarn are whitelisted for sudo access.
  • Node.js memory is capped at 4GB (NODE_OPTIONS="--max-old-space-size=4096").