Examples¶
Real-world usage patterns for behave-model.
Example 1: Project health report¶
Generate a comprehensive health report for your Behave project.
from behave_model import load_project, Validator
from collections import Counter
project = load_project("features/")
# Statistics
stats = project.statistics()
print("=== Project Statistics ===")
print(f" Features: {stats['features']}")
print(f" Rules: {stats['rules']}")
print(f" Scenarios: {stats['scenarios']}")
print(f" Scenario Outlines: {stats['scenario_outlines']}")
print(f" Steps: {stats['steps']}")
print(f" Tags: {stats['tags']}")
print(f" Avg steps/scenario: {stats['average_steps_per_scenario']:.1f}")
# Validation
print("\n=== Validation ===")
issues = Validator().validate(project)
errors = [i for i in issues if i.severity == "error"]
warnings = [i for i in issues if i.severity == "warning"]
print(f" Errors: {len(errors)}")
print(f" Warnings: {len(warnings)}")
for issue in issues:
print(f" [{issue.severity}] {issue.rule_name}: {issue.message}")
# Tag distribution
print("\n=== Tag Distribution ===")
tag_counts = Counter(tag.name for tag in project.all_tags())
for tag, count in tag_counts.most_common():
print(f" {tag:20s} ({count})")
# Features without tags
print("\n=== Features Without Tags ===")
for f in project.features:
if not f.tags:
print(f" {f.name}")
Example 2: Clean and export features¶
Normalize, sort, and re-export all feature files.
from behave_model import (
load_project,
normalize_whitespace,
sort_tags,
sort_features,
sort_scenarios,
PrettyPrinter,
)
project = load_project("features/")
# Clean up
normalize_whitespace(project)
sort_tags(project)
sort_features(project)
sort_scenarios(project)
# Export
printer = PrettyPrinter()
for feature in project.features:
text = printer.print_feature(feature)
with open(feature.location.filename, "w") as f:
f.write(text)
print(f"Cleaned: {feature.location.filename}")
Example 3: Find duplicate scenario names¶
from behave_model import load_project
from collections import Counter
project = load_project("features/")
names = Counter(s.name for s in project.all_scenarios())
duplicates = {n: c for n, c in names.items() if c > 1}
if duplicates:
print("Duplicate scenario names found:")
for name, count in sorted(duplicates.items()):
print(f" '{name}' — {count} times")
for s in project.find_scenarios(name=name):
print(f" at {s.location}")
else:
print("No duplicates found.")
Example 4: Export to JSON for API consumption¶
from behave_model import load_project, JsonSerializer
import json
project = load_project("features/")
json_text = JsonSerializer().serialize_project(project)
# Pretty-print and save
data = json.loads(json_text)
with open("project_export.json", "w") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print(f"Exported {len(data['features'])} features to project_export.json")
Example 5: Custom visitor for step analysis¶
from behave_model import load_project, Visitor
from collections import Counter
class StepAnalyzer(Visitor):
def __init__(self):
self.keyword_counts = Counter()
self.longest_step = None
self._max_len = 0
def visit_step(self, step):
kw = step.keyword.strip()
self.keyword_counts[kw] += 1
if len(step.name) > self._max_len:
self._max_len = len(step.name)
self.longest_step = step
project = load_project("features/")
analyzer = StepAnalyzer()
project.accept(analyzer)
print("Step keyword distribution:")
for kw, count in analyzer.keyword_counts.most_common():
print(f" {kw:10s} {count}")
if analyzer.longest_step:
s = analyzer.longest_step
print(f"\nLongest step ({len(s.name)} chars):")
print(f" {s.full_text}")
print(f" at {s.location}")
Example 6: CI/CD validation gate¶
import sys
from behave_model import load_project, Validator
project = load_project("features/")
issues = Validator().validate(project)
errors = [i for i in issues if i.severity == "error"]
if errors:
print(f"\n❌ {len(errors)} validation errors found:")
for issue in errors:
loc = str(issue.location) if issue.location else "unknown"
print(f" [{issue.rule_name}] {issue.message}")
print(f" at {loc}")
sys.exit(1)
else:
print("✅ All validation checks passed")
Example 7: Migrate tags from v1 to v2¶
from behave_model import load_project, rename_tag, remove_tag, PrettyPrinter
project = load_project("features/")
# Migrate old tag naming convention to new one
tag_mappings = {
"@wip": "@draft",
"@deprecated": "@to-remove",
"@manual": "@needs-manual-check",
}
for old, new in tag_mappings.items():
rename_tag(project, old, new)
print(f"Renamed: {old} → {new}")
# Remove tags that are no longer needed
for tag in ["@old-test", "@legacy"]:
remove_tag(project, tag)
print(f"Removed: {tag}")
# Export updated features
printer = PrettyPrinter()
for feature in project.features:
text = printer.print_feature(feature)
with open(feature.location.filename, "w") as f:
f.write(text)
Example 8: Count scenarios per Rule¶
from behave_model import load_project
project = load_project("features/")
for feature in project.features:
if feature.rules:
print(f"\n{feature.name}:")
for rule in feature.rules:
scenario_count = len(rule.scenarios)
has_bg = "yes" if rule.background else "no"
tags = ", ".join(rule.tag_names) or "(none)"
print(f" Rule: {rule.name}")
print(f" Scenarios: {scenario_count}")
print(f" Background: {has_bg}")
print(f" Tags: {tags}")