PY-37711 support behave 1.2.7+

(cherry picked from commit a423dc858b89cb8910f771fda7a3480d3a726ca5)

IJ-MR-172503

GitOrigin-RevId: 847983fe10ec0b48eab7518b516130a98f5ce29a
This commit is contained in:
Pavel Karateev
2025-08-15 18:42:12 +00:00
committed by intellij-monorepo-bot
parent 53967e3b71
commit 9cc3d0dec3
6 changed files with 135 additions and 33 deletions
+47 -33
View File
@@ -15,6 +15,7 @@ import sys
import traceback
from behave.formatter.base import Formatter
from behave.model import Step, ScenarioOutline, Feature, Scenario
from behave.formatter import _registry
from behave.tag_expression import TagExpression
from _jb_django_behave import run_as_django_behave
import _bdd_utils
@@ -238,7 +239,7 @@ class _BehaveRunner(_bdd_utils.BddRunner):
for feature in features_to_run:
assert isinstance(feature, Feature), feature
scenarios = []
for scenario in feature.scenarios:
for scenario in feature.walk_scenarios():
try:
scenario.tags.extend(feature.tags)
except AttributeError:
@@ -252,7 +253,42 @@ class _BehaveRunner(_bdd_utils.BddRunner):
return features_to_run
if __name__ == "__main__":
def _register_null_formatter(format_name):
class _Null(Formatter):
"""
Null formater to prevent stdout output
"""
pass
_registry.register_as(format_name, _Null)
def _register_teamcity_formatter(format_name, base_dir):
custom_messages = tcmessages.TeamcityServiceMessages()
# Not safe to import it in old mode
from teamcity.jb_behave_formatter import TeamcityFormatter
class TeamcityFormatterWithLocation(TeamcityFormatter):
def _report_suite_started(self, suite, suite_name):
location = suite.location
custom_messages.testSuiteStarted(
suite_name,
_bdd_utils.get_location(base_dir, location.filename, location.line)
)
def _report_test_started(self, test, test_name):
location = test.location
custom_messages.testStarted(
test_name,
_bdd_utils.get_location(base_dir, location.filename, location.line)
)
_registry.register_as(format_name, TeamcityFormatterWithLocation)
def main():
# TODO: support all other params instead
command_args = list(filter(None, sys.argv[1:]))
if command_args:
@@ -269,40 +305,14 @@ if __name__ == "__main__":
# New version supports 1.2.6 only
use_old_runner = "PYCHARM_BEHAVE_OLD_RUNNER" in os.environ
from behave.formatter import _registry
FORMAT_NAME = "com.jetbrains.pycharm.formatter"
format_name = "com.jetbrains.pycharm.formatter"
if use_old_runner:
class _Null(Formatter):
"""
Null formater to prevent stdout output
"""
pass
_registry.register_as(FORMAT_NAME, _Null)
_register_null_formatter(format_name)
else:
custom_messages = tcmessages.TeamcityServiceMessages()
# Not safe to import it in old mode
from teamcity.jb_behave_formatter import TeamcityFormatter
_register_teamcity_formatter(format_name, base_dir)
class TeamcityFormatterWithLocation(TeamcityFormatter):
def _report_suite_started(self, suite, suite_name):
location = suite.location
custom_messages.testSuiteStarted(suite_name,
_bdd_utils.get_location(base_dir, location.filename, location.line))
def _report_test_started(self, test, test_name):
location = test.location
custom_messages.testStarted(test_name,
_bdd_utils.get_location(base_dir, location.filename, location.line))
_registry.register_as(FORMAT_NAME, TeamcityFormatterWithLocation)
my_config.format = [FORMAT_NAME] # To prevent output to stdout
my_config.format = [format_name] # To prevent output to stdout
my_config.reporters = [] # To prevent summary to stdout
my_config.stdout_capture = False # For test output
my_config.stderr_capture = False # For test output
@@ -318,5 +328,9 @@ if __name__ == "__main__":
raise Exception("Nothing to run in {0}".format(what_to_run))
# Run as Django if supported, run plain otherwise
if not run_as_django_behave(FORMAT_NAME, what_to_run, command_args):
if not run_as_django_behave(format_name, what_to_run, command_args):
_BehaveRunner(my_config, base_dir, use_old_runner).run()
if __name__ == "__main__":
main()
@@ -0,0 +1,42 @@
Feature: Gherkin v6 Example -- with Rules
Feature description line 1.
Background: Feature.Background
Given feature background step_1
Rule: R1 (with Rule.Background)
Rule R1 description line 1.
Background: R1.Background
Given rule R1 background step_1
When rule R1 background step_2
Example: R1.Scenario_1
When rule R1 scenario_1 step_1
Then rule R1 scenario_1 step_2
Example: R1.Scenario_2
Given rule R1 scenario_2 step_1
Then rule R1 scenario_2 step_2
Rule: R2 (without Rule.Background)
Rule R2 description line 1.
Example: R2.Scenario_1
When rule R2 scenario_1 step_1
Then rule R2 scenario_1 step_2
Rule: R3 (with empty Rule.Background)
Rule R3 description line 1.
Rule R3 description line 2.
Background: R3.EmptyBackground
Scenario Template: R3.Scenario
Given a person named "<name>"
Examples:
| name |
| Alice |
| Bob |
@@ -0,0 +1,16 @@
from behave import step
@step('feature background step_{step_id:d}')
def step_feature_background(ctx, step_id):
print("feature background step_{0}".format(step_id))
@step('rule {rule_id:w} background step_{step_id:d}')
def step_rule_background(ctx, rule_id, step_id):
print("rule {0} background step_{1}".format(rule_id, step_id))
@step('rule {rule_id:w} scenario_{scenario_id:d} step_{step_id:d}')
def step_rule_scenario(ctx, rule_id, scenario_id, step_id):
print("rule {0} scenario_{1} step_{2}".format(rule_id, scenario_id, step_id))
@@ -0,0 +1,6 @@
from behave import given
@given('a person named "{name}"')
def step_given_person_with_name(ctx, name):
pass
@@ -0,0 +1,24 @@
from pathlib import Path
from behave import configuration
from pycharm.behave_runner import _BehaveRunner
from pycharm.behave_runner import _register_null_formatter
def test_scenarios_to_run():
my_config = configuration.Configuration()
helpers_root = Path(__file__).parent.parent.parent
path = helpers_root / "testResources" / "behave_examples" / "feature_with_rules"
my_config.paths = [str(path / "rule.feature")]
base_dir = str(path)
format_name = "com.jetbrains.pycharm.formatter"
_register_null_formatter(format_name)
my_config.format = [format_name]
br = _BehaveRunner(my_config, base_dir, use_old_runner=False)
features = br._get_features_to_run()
assert len(features) == 1
assert len(list(features[0].scenarios)) == 5