Feature Flow

Standardization Pipeline

Ops Templates → BDD/Gherkin → Backend + Frontend Tests

Pipeline Overview

1 Ops Templates

  • Non-technical language
  • User perspective flows
  • From support/ops team
  • Captures edge cases
  • Documents known problems

2 BDD/Gherkin

  • .feature files
  • Given/When/Then syntax
  • Human readable specs
  • Single source of truth
  • Maps to both test types

3 Tests

  • Backend: API contracts
  • Backend: Workflows (compositions)
  • Frontend: Page Objects
  • Frontend: E2E specs (Playwright)

1 Ops Templates

Template Structure

### [Flow Name]

User type: Pet Owner / Vet / Admin
Entry point: Page/button/link
Goal: One sentence

Steps:
1. First action
2. Second action
3. ...

Expected result:
- What should happen

Common problems:
- Problem 1

Edge cases:
- Special case 1
        

Source

  • Template: album/template/ops-flow/
  • Reference: def/work_plan/21-plantilla

Who Fills This

  • Support team (daily user contact)
  • Ops team (knows workarounds)
  • Product (requirements)

Output

  • One .md per flow
  • Organized by user type

2 BDD/Gherkin

.feature File

Feature: Turnero - Book appointment

  Scenario: Book vaccination for cat
    Given I am on the turnero page
    When I enter address "Av Santa Fe 1234"
    And I click "Next"
    Then a guest user should be created

    When I add pet "Koshka" type "Cat"
    And I select "Vaccination"
    Then "Clinical consult" is auto-added

  Scenario: Services filtered by pet type
    Given I added a cat
    Then I see cat vaccines
    And I dont see dog vaccines
        

Keywords

  • Feature = one capability
  • Scenario = one behavior
  • Given = precondition
  • When = action
  • Then = expected result

Reference

  • def/work_plan/10-flow-turnero.md
  • Full example with Gherkin, API tests, Page Objects

2b Gherkin File Organization

Correct: One Feature = One File

features/
├── pet-owner/
│   ├── registro.feature      # 6-8 scenarios
│   ├── reservar-turno.feature # 10-15 scenarios
│   ├── gestion-mascotas.feature
│   └── pago.feature
├── veterinarian/
│   └── ...
└── backoffice/
    └── ...
        

Anti-pattern: One Scenario = One File

# DON'T do this
features/pet-owner/registro/
├── registro-exitoso.feature
├── registro-email-invalido.feature
├── registro-password-corto.feature
└── ... (dozens of tiny files)
        

Why Multiple Scenarios per File

  • Feature = Capability - one file describes one capability with all its behaviors
  • Context stays together - Background, Rules share context
  • Tooling expects it - test runners, reports, IDE navigation

When to Split

# Scenarios per file:
 5-20   Normal, keep as is
20-40   Consider splitting
40+     Definitely split
        

Folder Depth

  • Good: 1-2 levels max
  • Avoid: deep nesting

3a Backend Tests

Structure (amar_django_back)

tests/contracts/
├── base.py          # mode switcher
├── endpoints.py     # API paths (single source)
├── helpers.py       # test data
│
├── mascotas/        # app tests
│   ├── test_pet_owners.py
│   ├── test_pets.py
│   └── test_coverage.py
├── productos/
│   ├── test_services.py
│   └── test_cart.py
├── solicitudes/
│   └── test_service_requests.py
│
└── workflows/       # compositions
    └── test_turnero_general.py
        

Two Test Modes

# Fast (Django test client)
pytest tests/contracts/

# Live (real HTTP)
CONTRACT_TEST_MODE=live pytest
        

Workflow = Composition

# Calls endpoints in sequence:
1. Check coverage
2. Create pet owner
3. Create pet
4. Get services
5. Create request
        

Key Files

  • endpoints.py - change paths here only
  • helpers.py - sample data

3b Frontend Tests

Structure (amar_frontend)

tests/e2e/
├── pages/           # Page Objects
│   ├── BasePage.ts
│   ├── LoginPage.ts
│   └── index.ts
│
└── login.spec.ts   # E2E test
        

Page Object Pattern

export class LoginPage extends BasePage {
  get emailInput() {
    return this.page.getByLabel('Email');
  }

  async login(email, password) {
    await this.emailInput.fill(email);
    await this.passwordInput.fill(password);
    await this.submitButton.click();
  }
}
        

Running Tests

# All tests
npx playwright test

# With UI
npx playwright test --ui

# Specific file
npx playwright test login.spec.ts
        

Locator Priority

  • 1. getByRole() - buttons, links
  • 2. getByLabel() - form fields
  • 3. getByText() - visible text
  • 4. getByTestId() - data-testid

Avoid

  • CSS class selectors
  • Complex XPath

Per-Feature Checklist

Full example: def/work_plan/10-flow-turnero.md

Backend README: amar_django_back/tests/contracts/README.md

Frontend README: amar_frontend/tests/README.md