Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
394 changes: 387 additions & 7 deletions README.md

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions quick_test_gherkin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""Quick test script to parse any .feature file"""

import sys
from pathlib import Path
from gherkin.parser import Parser
from gherkin.token_scanner import TokenScanner
import json


def parse_feature(filepath):
"""Parse a Gherkin feature file and display key information."""
with open(filepath, "r", encoding="utf-8") as f:
feature_text = f.read()

parser = Parser()
scanner = TokenScanner(feature_text)
doc = parser.parse(scanner)

feature = doc["feature"]

print(f"\n{'='*60}")
print(f"Feature: {feature['name']}")
print(f"{'='*60}")

# Count elements
scenarios = [c for c in feature["children"] if "scenario" in c]
backgrounds = [c for c in feature["children"] if "background" in c]

print(f"\nSummary:")
print(f" Backgrounds: {len(backgrounds)}")
print(f" Scenarios: {len(scenarios)}")

print(f"\nScenarios:")
for idx, child in enumerate(scenarios, 1):
scenario = child["scenario"]
tags = [tag["name"] for tag in scenario.get("tags", [])]
steps = scenario.get("steps", [])
examples = scenario.get("examples", [])

scenario_type = "Scenario Outline" if examples else "Scenario"
print(f" {idx}. [{scenario_type}] {scenario['name']}")
print(f" Tags: {', '.join(tags) if tags else 'None'}")
print(f" Steps: {len(steps)}")
if examples:
total_examples = sum(len(ex.get("tableBody", [])) for ex in examples)
print(f" Example rows: {total_examples}")

return doc


if __name__ == "__main__":
if len(sys.argv) > 1:
feature_file = Path(sys.argv[1])
else:
# Default to sample file
feature_file = Path(__file__).parent / "tests" / "test_data" / "FEATURE" / "sample_login.feature"

if not feature_file.exists():
print(f"Error: File not found: {feature_file}")
sys.exit(1)

parse_feature(feature_file)
print(f"\n{'='*60}")
print("✓ Parsing successful!")
print(f"{'='*60}\n")
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
],
include_package_data=True,
install_requires=[
"click>=8.1.0,<8.2.2", # Note: click version 8.2.2 is yanked as of Aug 2, 2025!
"click>=8.1.0,<8.2.2", # Note: click version 8.2.2 is yanked as of Aug 2, 2025!
"pyyaml>=6.0.0,<7.0.0",
"junitparser>=3.1.0,<4.0.0",
"pyserde==0.12.*",
Expand All @@ -24,7 +24,8 @@
"humanfriendly>=10.0.0,<11.0.0",
"openapi-spec-validator>=0.5.0,<1.0.0",
"beartype>=0.17.0,<1.0.0",
"prance" # Does not use semantic versioning
"prance", # Does not use semantic versioning
"gherkin-official>=27.0.0,<28.0.0", # Gherkin/BDD feature file parser
],
entry_points="""
[console_scripts]
Expand Down
7 changes: 6 additions & 1 deletion tests/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ markers =
data_provider: tests for data provider
project_based_client: mark a test as a project-based client test.
proxy: test for proxy feature

cmd_import_gherkin: tests for import_gherkin command
cmd_export_gherkin: tests for export_gherkin command
cmd_parse_gherkin: tests for parse_gherkin command
cmd_parse_cucumber: tests for parse_cucumber command
parse_gherkin: tests for gherkin parser
parse_cucumber: tests for cucumber parser
Loading