"""pytest-bdd exporter for pytest projects.""" from typing import Dict, List from nl2gherkin.exporters.base import BaseExporter class PytestBDDExporter(BaseExporter): """Exporter for pytest-bdd (Python).""" def __init__(self) -> None: """Initialize the pytest-bdd exporter.""" pass def export(self, features: List[str]) -> str: """Export features to pytest-bdd format. Args: features: List of Gherkin feature strings. Returns: pytest-bdd-compatible feature file content. """ combined = "\n\n".join(features) return combined def get_step_definitions_template(self) -> str: """Get pytest-bdd step definitions template. Returns: Step definitions template string. """ return '''"""pytest-bdd step definitions.""" import pytest from pytest_bdd import given, when, then, scenarios scenarios('features') @given("a setup condition") def setup_condition(): """Given step implementation.""" return {} @when("an action occurs") def action_occurs(): """When step implementation.""" pass @then("an expected result") def expected_result(): """Then step implementation.""" pass ''' def get_configuration_template(self) -> Dict[str, str]: """Get pytest-bdd configuration files. Returns: Dictionary mapping filenames to content. """ return { "conftest.py": '''"""pytest configuration and fixtures.""" import pytest from pytest_bdd import scenarios scenarios('features') @pytest.fixture def context(): """Shared test context.""" return {} def pytest_configure(config): """Configure pytest.""" pass ''', "pytest.ini": '''[pytest] bdd_features_base_dir = features/ ''', } def generate_step_definitions(self, scenarios: List[str], feature_name: str = "features") -> str: """Generate step definitions for given scenarios. Args: scenarios: List of scenario texts. feature_name: Name of the feature file. Returns: Step definitions Python code. """ step_defs = [] for scenario in scenarios: lines = scenario.split("\n") scenario_name = "" for line in lines: stripped = line.strip() if stripped.startswith("Scenario:"): scenario_name = stripped[9:].strip().replace(" ", "_") break for line in lines: stripped = line.strip() if stripped.startswith(("Given ", "When ", "Then ", "And ")): step_text = " ".join(stripped.split()[1:]) step_def = stripped.split()[0].lower() params = self._extract_parameters(step_text) param_str = ", ".join(f'"{p}"' for p in params) if params else "" if params: step_impl = f'''@pytest.{step_def}("{step_text}") def {step_def}_{scenario_name}({", ".join(params)}): """{stripped.split()[0]} step implementation.""" pass ''' else: step_impl = f'''@{step_def}("{step_text}") def {step_def}_{scenario_name}(): """{stripped.split()[0]} step implementation.""" pass ''' step_defs.append(step_impl) return "\n".join(step_defs) def _extract_parameters(self, step_text: str) -> List[str]: """Extract parameters from a step text.""" import re return re.findall(r"<([^>]+)>", step_text)