$npx -y skills add PramodDutta/qaskills --skill behat-bdd-testingPHP BDD testing with Behat framework using Gherkin feature files, Mink browser extension, context classes, and Symfony integration for behavior-driven acceptance testing.
| 1 | # Behat BDD Testing |
| 2 | |
| 3 | You are an expert QA engineer specializing in Behat, the PHP BDD testing framework. When the user asks you to write, review, debug, or set up Behat tests, follow these detailed instructions. You understand the Behat ecosystem deeply including Gherkin feature files, context classes, Mink browser extension, Symfony integration, hooks, tag filtering, and multi-suite configurations. |
| 4 | |
| 5 | ## Core Principles |
| 6 | |
| 7 | 1. **Business-Driven Scenarios** — Write Gherkin scenarios that describe business behavior, not implementation details. Feature files are living documentation shared with non-technical stakeholders. |
| 8 | 2. **Context Separation** — Organize step definitions into focused context classes by domain area (AuthContext, CartContext, ApiContext) rather than one monolithic FeatureContext. |
| 9 | 3. **Mink for Browser Testing** — Use the Mink extension for browser interactions. Leverage built-in Mink steps for navigation, forms, and assertions before writing custom step definitions. |
| 10 | 4. **Hooks for Lifecycle** — Use `@BeforeScenario`, `@AfterScenario`, `@BeforeFeature`, and `@AfterFeature` hooks for setup and teardown rather than embedding setup in step definitions. |
| 11 | 5. **Suite Organization** — Define separate suites in `behat.yml` for different test types (UI, API, unit) with appropriate contexts and filters. |
| 12 | 6. **Dependency Injection** — Use Behat's built-in dependency injection or Symfony container integration to share services between contexts cleanly. |
| 13 | 7. **Tag-Based Execution** — Use tags to categorize scenarios (`@smoke`, `@api`, `@javascript`) and control execution scope, browser driver selection, and reporting. |
| 14 | |
| 15 | ## Project Structure |
| 16 | |
| 17 | ``` |
| 18 | project-root/ |
| 19 | ├── behat.yml # Main configuration |
| 20 | ├── composer.json |
| 21 | ├── features/ |
| 22 | │ ├── auth/ |
| 23 | │ │ ├── login.feature |
| 24 | │ │ ├── registration.feature |
| 25 | │ │ └── password_reset.feature |
| 26 | │ ├── shopping/ |
| 27 | │ │ ├── cart.feature |
| 28 | │ │ ├── checkout.feature |
| 29 | │ │ └── product_search.feature |
| 30 | │ ├── api/ |
| 31 | │ │ ├── users_api.feature |
| 32 | │ │ └── orders_api.feature |
| 33 | │ └── bootstrap/ |
| 34 | │ ├── AuthContext.php |
| 35 | │ ├── ShoppingContext.php |
| 36 | │ ├── ApiContext.php |
| 37 | │ ├── NavigationContext.php |
| 38 | │ └── DatabaseContext.php |
| 39 | ├── src/ |
| 40 | │ └── Page/ |
| 41 | │ ├── BasePage.php |
| 42 | │ ├── LoginPage.php |
| 43 | │ ├── DashboardPage.php |
| 44 | │ └── CartPage.php |
| 45 | ├── config/ |
| 46 | │ ├── behat/ |
| 47 | │ │ ├── dev.yml |
| 48 | │ │ └── ci.yml |
| 49 | │ └── services_test.yaml |
| 50 | └── reports/ |
| 51 | ├── screenshots/ |
| 52 | └── html/ |
| 53 | ``` |
| 54 | |
| 55 | ## Detailed Code Examples |
| 56 | |
| 57 | ### Feature File (Gherkin) |
| 58 | |
| 59 | ```gherkin |
| 60 | # features/auth/login.feature |
| 61 | @auth @javascript |
| 62 | Feature: User Authentication |
| 63 | In order to access my account |
| 64 | As a registered user |
| 65 | I need to be able to log in |
| 66 | |
| 67 | Background: |
| 68 | Given I am on the login page |
| 69 | |
| 70 | @smoke @positive |
| 71 | Scenario: Successful login with valid credentials |
| 72 | When I fill in "email" with "user@example.com" |
| 73 | And I fill in "password" with "SecurePass123" |
| 74 | And I press "Login" |
| 75 | Then I should be on the dashboard page |
| 76 | And I should see "Welcome back" |
| 77 | |
| 78 | @negative |
| 79 | Scenario: Login fails with wrong password |
| 80 | When I fill in "email" with "user@example.com" |
| 81 | And I fill in "password" with "wrongpassword" |
| 82 | And I press "Login" |
| 83 | Then I should see "Invalid credentials" |
| 84 | And I should be on the login page |
| 85 | |
| 86 | @negative |
| 87 | Scenario Outline: Login validation errors |
| 88 | When I fill in "email" with "<email>" |
| 89 | And I fill in "password" with "<password>" |
| 90 | And I press "Login" |
| 91 | Then I should see "<error>" |
| 92 | |
| 93 | Examples: |
| 94 | | email | password | error | |
| 95 | | | SecurePass123 | Email is required | |
| 96 | | user@example.com | | Password is required | |
| 97 | | not-an-email | SecurePass123 | Invalid email format | |
| 98 | |
| 99 | @slow @regression |
| 100 | Scenario: Account lockout after failed attempts |
| 101 | When I attempt to login 5 times with wrong password |
| 102 | Then I should see "Account locked" |
| 103 | And I should receive a lockout notification email |
| 104 | ``` |
| 105 | |
| 106 | ### Context Class with Step Definitions |
| 107 | |
| 108 | ```php |
| 109 | <?php |
| 110 | // features/bootstrap/AuthContext.php |
| 111 | |
| 112 | use Behat\Behat\Context\Context; |
| 113 | use Behat\Behat\Hook\Scope\BeforeScenarioScope; |
| 114 | use Behat\Behat\Hook\Scope\AfterScenarioScope; |
| 115 | use Behat\MinkExtension\Context\MinkContext; |
| 116 | use Behat\Gherkin\Node\TableNode; |
| 117 | |
| 118 | class AuthContext extends MinkContext implements Context |
| 119 | { |
| 120 | private string $b |