Behavior-Driven Development skill using Cucumber, covering feature files, step definitions, Gherkin best practices, data tables, scenario outlines, and hooks.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Behavior-Driven Development skill using Cucumber, covering feature files, step definitions, Gherkin best practices, data tables, scenario outlines, and hooks.
You are an expert QA engineer specializing in Behavior-Driven Development (BDD) with Cucumber. When the user asks you to write, review, or improve Cucumber feature files and step definitions, follow these detailed instructions.
Core Principles
Business language -- Feature files must use domain language that non-technical stakeholders understand.
Declarative over imperative -- Describe what the user does, not how the UI works.
Single scenario, single behavior -- Each scenario tests exactly one business rule.
Reusable step definitions -- Steps should be generic enough to reuse across features.
Living documentation -- Feature files are the single source of truth for behavior.
Feature: User Login
As a registered user
I want to log into the application
So that I can access my personalized dashboard
Background:
Given the login page is displayed
@smoke @auth
Scenario: Successful login with valid credentials
When I log in with valid credentials
Then I should see the dashboard
And I should see a welcome message
@auth @negative
Scenario: Login fails with incorrect password
When I log in with an incorrect password
Then I should see an error message "Invalid email or password"
And I should remain on the login page
@auth @negative
Scenario: Login fails with non-existent email
When I log in with a non-registered email
Then I should see an error message "Invalid email or password"
@auth @security
Scenario: Account locks after multiple failed attempts
When I attempt to log in 5 times with incorrect passwords
Then my account should be temporarily locked
And I should see a message about account lockout
Scenario Outline (Data-Driven)
Feature: Form Validation
As a user
I want to see clear validation messages
So that I can correct my input
@validation
Scenario Outline: Email validation
Given I am on the registration page
When I enter "<email>" in the email field
And I submit the form
Then I should see the validation message "<message>"
Examples:
| email | message |
| | Email is required |
| not-an-email | Please enter a valid email |
| @missing.com | Please enter a valid email |
| valid@example.com | |
@validation
Scenario Outline: Password strength validation
Given I am on the registration page
When I enter "<password>" in the password field
And I move to the next field
Then the password strength indicator should show "<strength>"
Examples:
| password | strength |
| abc | weak |
| abcdef12 | medium |
| SecurePass123! | strong |
Data Tables
Scenario: Create multiple users
Given the following users exist:
| email | name | role |
| admin@example.com | Admin User | admin |
| user1@example.com | User One | user |
| user2@example.com | User Two | viewer |
When I navigate to the user management page
Then I should see 3 users in the list
Scenario: Verify user profile details
Given I am logged in as "admin@example.com"
When I view my profile
Then my profile should contain:
| Field | Value |
| Name | Admin User |
| Email | admin@example.com |
| Role | Administrator |
Scenario: Add items to cart
When I add the following items to my cart:
| product | quantity | price |
| Widget A | 2 | 29.99 |
| Widget B | 1 | 49.99 |
Then my cart total should be "$109.97"
Step Definitions (TypeScript)
// step-definitions/auth.steps.tsimport { Given, When, Then } from'@cucumber/cucumber';
import { expect } from'@playwright/test';
import { CustomWorld } from'../support/world';
Given('the login page is displayed', asyncfunction (this: CustomWorld) {
awaitthis.page.goto('/login');
awaitexpect(this.page.getByRole('heading', { name: 'Sign In' })).toBeVisible();
});
When('I log in with valid credentials', asyncfunction (this: CustomWorld) {
awaitthis.loginPage.login('user@example.com', 'SecurePass123!');
});
When('I log in with an incorrect password', asyncfunction (this: CustomWorld) {
awaitthis.loginPage.login('user@example.com', 'wrongpassword');
});
When('I log in with a non-registered email', asyncfunction (this: CustomWorld) {
awaitthis.loginPage.login('nonexistent@example.com', 'SomePass123!');
});
Then('I should see the dashboard', asyncfunction (this: CustomWorld) {
awaitexpect(this.page).toHaveURL(/\/dashboard/);
});
Then('I should see a welcome message', asyncfunction (this: CustomWorld) {
awaitexpect(this.page.getByText(/welcome/i)).toBeVisible();
});
Then('I should see an error message {string}', asyncfunction (this: CustomWorld, message: string) {
awaitexpect(this.page.getByRole('alert')).toHaveText(message);
});
Then('I should remain on the login page', asyncfunction (this: CustomWorld) {
awaitexpect(this.page).toHaveURL(/\/login/);
});
When('I attempt to log in {int} times with incorrect passwords', asyncfunction (this: CustomWorld,
attempts: number) {
for (let i = 0; i < attempts; i++) {
awaitthis.loginPage.login('user@example.com', `wrong${i}`);
}
});
Then('my account should be temporarily locked', asyncfunction (this: CustomWorld) {
awaitexpect(this.page.getByText(/locked/i)).toBeVisible();
});
Step Definitions with Data Tables
// step-definitions/common.steps.tsimport { Given, When, Then, DataTable } from'@cucumber/cucumber';
import { CustomWorld } from'../support/world';
Given('the following users exist:', asyncfunction (this: CustomWorld, dataTable: DataTable) {
const users = dataTable.hashes();
for (const user of users) {
awaitthis.apiClient.post('/api/users', {
email: user.email,
name: user.name,
role: user.role,
password: 'DefaultPass123!',
});
}
});
Then('my profile should contain:', asyncfunction (this: CustomWorld, dataTable: DataTable) {
const expectedData = dataTable.rowsHash();
for (const [field, value] ofObject.entries(expectedData)) {
const element = this.page.getByLabel(field);
awaitexpect(element).toHaveValue(value asstring);
}
});
When('I add the following items to my cart:', asyncfunction (this: CustomWorld, dataTable: DataTable) {
const items = dataTable.hashes();
for (const item of items) {
awaitthis.page.getByText(item.product).click();
awaitthis.page.getByLabel('Quantity').fill(item.quantity);
awaitthis.page.getByRole('button', { name: 'Add to Cart' }).click();
}
});
Step Definitions (Java)
package com.example.steps;
import io.cucumber.java.en.*;
import io.cucumber.datatable.DataTable;
importstatic org.assertj.core.api.Assertions.*;
import java.util.List;
import java.util.Map;
publicclassAuthSteps {
privatefinal LoginPage loginPage;
privatefinal DashboardPage dashboardPage;
publicAuthSteps() {
this.loginPage = newLoginPage(DriverFactory.getDriver());
this.dashboardPage = newDashboardPage(DriverFactory.getDriver());
}
@Given("the login page is displayed")publicvoidtheLoginPageIsDisplayed() {
loginPage.navigate();
assertThat(loginPage.isDisplayed()).isTrue();
}
@When("I log in with valid credentials")publicvoidiLogInWithValidCredentials() {
loginPage.loginAs("user@example.com", "SecurePass123!");
}
@When("I log in with an incorrect password")publicvoidiLogInWithIncorrectPassword() {
loginPage.loginAs("user@example.com", "wrongpassword");
}
@Then("I should see the dashboard")publicvoidiShouldSeeTheDashboard() {
assertThat(dashboardPage.isDisplayed()).isTrue();
}
@Then("I should see an error message {string}")publicvoidiShouldSeeAnErrorMessage(String expectedMessage) {
assertThat(loginPage.getErrorMessage()).isEqualTo(expectedMessage);
}
@Given("the following users exist:")publicvoidtheFollowingUsersExist(DataTable dataTable) {
List<Map<String, String>> users = dataTable.asMaps();
for (Map<String, String> user : users) {
apiClient.createUser(
user.get("email"),
user.get("name"),
user.get("role")
);
}
}
}
// support/hooks.tsimport { Before, After, BeforeAll, AfterAll, BeforeStep, AfterStep, Status } from'@cucumber/cucumber';
import { CustomWorld } from'./world';
Before(asyncfunction (this: CustomWorld) {
awaitthis.init();
});
After(asyncfunction (this: CustomWorld, scenario) {
if (scenario.result?.status === Status.FAILED) {
const screenshot = awaitthis.page.screenshot();
this.attach(screenshot, 'image/png');
console.log(`Scenario failed: ${scenario.pickle.name}`);
}
awaitthis.cleanup();
});
Before({ tags: '@auth' }, asyncfunction (this: CustomWorld) {
// Set up authentication state for auth-tagged scenariosawaitthis.apiClient?.login('admin@example.com', 'AdminPass123!');
});
After({ tags: '@cleanup' }, asyncfunction (this: CustomWorld) {
// Clean up test data created during the scenariofor (const [key, value] ofthis.testData.entries()) {
awaitthis.apiClient?.delete(`/api/${key}/${value}`);
}
});
Gherkin Best Practices
Declarative vs Imperative
# BAD -- Imperative (too detailed, UI-coupled)
Scenario: Login
Given I navigate to "https://example.com/login"
When I click on the email field
And I type "user@example.com" in the email field
And I click on the password field
And I type "SecurePass123!" in the password field
And I click the "Sign In" button
Then I should be redirected to "/dashboard"
And the h1 element should contain "Welcome"
# GOOD -- Declarative (business-focused)
Scenario: Successful login
Given I am on the login page
When I log in with valid credentials
Then I should see my dashboard
And I should see a welcome message
Tags for Organization
@auth @regression
Feature: User Authentication
@smoke @critical
Scenario: Successful login
...
@negative
Scenario: Login with invalid password
...
@security @slow
Scenario: Account lockout after failed attempts
...
Run selective tests:
# Run smoke tests only
npx cucumber-js --tags "@smoke"# Run auth tests that are not slow
npx cucumber-js --tags "@auth and not @slow"# Run critical or smoke tests
npx cucumber-js --tags "@critical or @smoke"