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-testidattributes 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:
- Run
bdd-headed - Open the noVNC URL (port 10000) — append
/vnc.html?autoconnect=true - 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.featurefile and matching.steps.ts— saves setup time- Cucumber auto-discovers step files from
features/steps/— no imports needed - The
BDDWorldclass gives every step access tothis.page,this.context, andthis.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-dryvalidates 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").