busser-behave 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.cane +0 -0
- data/.gitignore +17 -0
- data/.tailor +4 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +3 -0
- data/LICENSE +15 -0
- data/README.md +41 -0
- data/Rakefile +68 -0
- data/busser-behave.gemspec +30 -0
- data/features/plugin_install_command.feature +11 -0
- data/features/plugin_list_command.feature +8 -0
- data/features/support/env.rb +13 -0
- data/features/test_command.feature +31 -0
- data/lib/busser/behave/version.rb +26 -0
- data/lib/busser/runner_plugin/behave.rb +37 -0
- data/vendor/behave/CHANGES.rst +483 -0
- data/vendor/behave/LICENSE +23 -0
- data/vendor/behave/MANIFEST.in +37 -0
- data/vendor/behave/PROJECT_INFO.rst +21 -0
- data/vendor/behave/README.rst +112 -0
- data/vendor/behave/VERSION.txt +1 -0
- data/vendor/behave/behave.ini +22 -0
- data/vendor/behave/behave/__init__.py +30 -0
- data/vendor/behave/behave/__main__.py +187 -0
- data/vendor/behave/behave/_stepimport.py +185 -0
- data/vendor/behave/behave/_types.py +134 -0
- data/vendor/behave/behave/api/__init__.py +7 -0
- data/vendor/behave/behave/api/async_step.py +283 -0
- data/vendor/behave/behave/capture.py +227 -0
- data/vendor/behave/behave/compat/__init__.py +5 -0
- data/vendor/behave/behave/compat/collections.py +20 -0
- data/vendor/behave/behave/configuration.py +788 -0
- data/vendor/behave/behave/contrib/__init__.py +0 -0
- data/vendor/behave/behave/contrib/scenario_autoretry.py +73 -0
- data/vendor/behave/behave/formatter/__init__.py +12 -0
- data/vendor/behave/behave/formatter/_builtins.py +39 -0
- data/vendor/behave/behave/formatter/_registry.py +135 -0
- data/vendor/behave/behave/formatter/ansi_escapes.py +91 -0
- data/vendor/behave/behave/formatter/base.py +200 -0
- data/vendor/behave/behave/formatter/formatters.py +57 -0
- data/vendor/behave/behave/formatter/json.py +253 -0
- data/vendor/behave/behave/formatter/null.py +12 -0
- data/vendor/behave/behave/formatter/plain.py +158 -0
- data/vendor/behave/behave/formatter/pretty.py +351 -0
- data/vendor/behave/behave/formatter/progress.py +287 -0
- data/vendor/behave/behave/formatter/rerun.py +114 -0
- data/vendor/behave/behave/formatter/sphinx_steps.py +372 -0
- data/vendor/behave/behave/formatter/sphinx_util.py +118 -0
- data/vendor/behave/behave/formatter/steps.py +497 -0
- data/vendor/behave/behave/formatter/tags.py +178 -0
- data/vendor/behave/behave/i18n.py +614 -0
- data/vendor/behave/behave/importer.py +102 -0
- data/vendor/behave/behave/json_parser.py +264 -0
- data/vendor/behave/behave/log_capture.py +233 -0
- data/vendor/behave/behave/matchers.py +402 -0
- data/vendor/behave/behave/model.py +1737 -0
- data/vendor/behave/behave/model_core.py +416 -0
- data/vendor/behave/behave/model_describe.py +105 -0
- data/vendor/behave/behave/parser.py +615 -0
- data/vendor/behave/behave/reporter/__init__.py +0 -0
- data/vendor/behave/behave/reporter/base.py +45 -0
- data/vendor/behave/behave/reporter/junit.py +473 -0
- data/vendor/behave/behave/reporter/summary.py +94 -0
- data/vendor/behave/behave/runner.py +753 -0
- data/vendor/behave/behave/runner_util.py +417 -0
- data/vendor/behave/behave/step_registry.py +112 -0
- data/vendor/behave/behave/tag_expression.py +111 -0
- data/vendor/behave/behave/tag_matcher.py +465 -0
- data/vendor/behave/behave/textutil.py +137 -0
- data/vendor/behave/behave/userdata.py +130 -0
- data/vendor/behave/behave4cmd0/__all_steps__.py +12 -0
- data/vendor/behave/behave4cmd0/__init__.py +5 -0
- data/vendor/behave/behave4cmd0/__setup.py +11 -0
- data/vendor/behave/behave4cmd0/command_shell.py +216 -0
- data/vendor/behave/behave4cmd0/command_shell_proc.py +256 -0
- data/vendor/behave/behave4cmd0/command_steps.py +532 -0
- data/vendor/behave/behave4cmd0/command_util.py +147 -0
- data/vendor/behave/behave4cmd0/failing_steps.py +49 -0
- data/vendor/behave/behave4cmd0/log/__init__.py +1 -0
- data/vendor/behave/behave4cmd0/log/steps.py +395 -0
- data/vendor/behave/behave4cmd0/note_steps.py +29 -0
- data/vendor/behave/behave4cmd0/passing_steps.py +36 -0
- data/vendor/behave/behave4cmd0/pathutil.py +146 -0
- data/vendor/behave/behave4cmd0/setup_command_shell.py +24 -0
- data/vendor/behave/behave4cmd0/textutil.py +304 -0
- data/vendor/behave/bin/behave +44 -0
- data/vendor/behave/bin/behave.cmd +10 -0
- data/vendor/behave/bin/behave.junit_filter.py +85 -0
- data/vendor/behave/bin/behave.step_durations.py +163 -0
- data/vendor/behave/bin/behave2cucumber_json.py +63 -0
- data/vendor/behave/bin/behave_cmd.py +44 -0
- data/vendor/behave/bin/convert_i18n_yaml.py +77 -0
- data/vendor/behave/bin/explore_platform_encoding.py +24 -0
- data/vendor/behave/bin/i18n.yml +621 -0
- data/vendor/behave/bin/invoke +8 -0
- data/vendor/behave/bin/invoke.cmd +9 -0
- data/vendor/behave/bin/json.format.py +167 -0
- data/vendor/behave/bin/jsonschema_validate.py +122 -0
- data/vendor/behave/bin/make_localpi.py +279 -0
- data/vendor/behave/bin/project_bootstrap.sh +30 -0
- data/vendor/behave/bin/toxcmd.py +270 -0
- data/vendor/behave/bin/toxcmd3.py +270 -0
- data/vendor/behave/conftest.py +27 -0
- data/vendor/behave/docs/Makefile +154 -0
- data/vendor/behave/docs/_static/agogo.css +501 -0
- data/vendor/behave/docs/_static/behave_logo.png +0 -0
- data/vendor/behave/docs/_static/behave_logo1.png +0 -0
- data/vendor/behave/docs/_static/behave_logo2.png +0 -0
- data/vendor/behave/docs/_static/behave_logo3.png +0 -0
- data/vendor/behave/docs/_themes/LICENSE +45 -0
- data/vendor/behave/docs/_themes/kr/layout.html +17 -0
- data/vendor/behave/docs/_themes/kr/relations.html +19 -0
- data/vendor/behave/docs/_themes/kr/static/flasky.css_t +480 -0
- data/vendor/behave/docs/_themes/kr/static/small_flask.css +90 -0
- data/vendor/behave/docs/_themes/kr/theme.conf +7 -0
- data/vendor/behave/docs/_themes/kr_small/layout.html +22 -0
- data/vendor/behave/docs/_themes/kr_small/static/flasky.css_t +287 -0
- data/vendor/behave/docs/_themes/kr_small/theme.conf +10 -0
- data/vendor/behave/docs/api.rst +408 -0
- data/vendor/behave/docs/appendix.rst +19 -0
- data/vendor/behave/docs/behave.rst +640 -0
- data/vendor/behave/docs/behave.rst-template +86 -0
- data/vendor/behave/docs/behave_ecosystem.rst +81 -0
- data/vendor/behave/docs/comparison.rst +85 -0
- data/vendor/behave/docs/conf.py +293 -0
- data/vendor/behave/docs/context_attributes.rst +66 -0
- data/vendor/behave/docs/django.rst +192 -0
- data/vendor/behave/docs/formatters.rst +61 -0
- data/vendor/behave/docs/gherkin.rst +673 -0
- data/vendor/behave/docs/index.rst +57 -0
- data/vendor/behave/docs/install.rst +60 -0
- data/vendor/behave/docs/more_info.rst +184 -0
- data/vendor/behave/docs/new_and_noteworthy.rst +18 -0
- data/vendor/behave/docs/new_and_noteworthy_v1.2.4.rst +11 -0
- data/vendor/behave/docs/new_and_noteworthy_v1.2.5.rst +814 -0
- data/vendor/behave/docs/new_and_noteworthy_v1.2.6.rst +255 -0
- data/vendor/behave/docs/parse_builtin_types.rst +59 -0
- data/vendor/behave/docs/philosophy.rst +235 -0
- data/vendor/behave/docs/regular_expressions.rst +71 -0
- data/vendor/behave/docs/related.rst +14 -0
- data/vendor/behave/docs/test_domains.rst +62 -0
- data/vendor/behave/docs/tutorial.rst +636 -0
- data/vendor/behave/docs/update_behave_rst.py +100 -0
- data/vendor/behave/etc/json/behave.json-schema +172 -0
- data/vendor/behave/etc/junit.xml/behave_junit.xsd +103 -0
- data/vendor/behave/etc/junit.xml/junit-4.xsd +92 -0
- data/vendor/behave/examples/async_step/README.txt +8 -0
- data/vendor/behave/examples/async_step/behave.ini +14 -0
- data/vendor/behave/examples/async_step/features/async_dispatch.feature +8 -0
- data/vendor/behave/examples/async_step/features/async_run.feature +6 -0
- data/vendor/behave/examples/async_step/features/environment.py +28 -0
- data/vendor/behave/examples/async_step/features/steps/async_dispatch_steps.py +26 -0
- data/vendor/behave/examples/async_step/features/steps/async_steps34.py +10 -0
- data/vendor/behave/examples/async_step/features/steps/async_steps35.py +10 -0
- data/vendor/behave/examples/async_step/testrun_example.async_dispatch.txt +11 -0
- data/vendor/behave/examples/async_step/testrun_example.async_run.txt +9 -0
- data/vendor/behave/examples/env_vars/README.rst +26 -0
- data/vendor/behave/examples/env_vars/behave.ini +15 -0
- data/vendor/behave/examples/env_vars/behave_run.output_example.txt +12 -0
- data/vendor/behave/examples/env_vars/features/env_var.feature +6 -0
- data/vendor/behave/examples/env_vars/features/steps/env_var_steps.py +38 -0
- data/vendor/behave/features/README.txt +12 -0
- data/vendor/behave/features/background.feature +392 -0
- data/vendor/behave/features/capture_stderr.feature +172 -0
- data/vendor/behave/features/capture_stdout.feature +125 -0
- data/vendor/behave/features/cmdline.lang_list.feature +33 -0
- data/vendor/behave/features/configuration.default_paths.feature +116 -0
- data/vendor/behave/features/context.global_params.feature +35 -0
- data/vendor/behave/features/context.local_params.feature +17 -0
- data/vendor/behave/features/directory_layout.advanced.feature +147 -0
- data/vendor/behave/features/directory_layout.basic.feature +75 -0
- data/vendor/behave/features/directory_layout.basic2.feature +87 -0
- data/vendor/behave/features/environment.py +53 -0
- data/vendor/behave/features/exploratory_testing.with_table.feature +141 -0
- data/vendor/behave/features/feature.description.feature +0 -0
- data/vendor/behave/features/feature.exclude_from_run.feature +96 -0
- data/vendor/behave/features/formatter.help.feature +30 -0
- data/vendor/behave/features/formatter.json.feature +420 -0
- data/vendor/behave/features/formatter.progress3.feature +235 -0
- data/vendor/behave/features/formatter.rerun.feature +296 -0
- data/vendor/behave/features/formatter.steps.feature +181 -0
- data/vendor/behave/features/formatter.steps_catalog.feature +100 -0
- data/vendor/behave/features/formatter.steps_doc.feature +140 -0
- data/vendor/behave/features/formatter.steps_usage.feature +404 -0
- data/vendor/behave/features/formatter.tags.feature +134 -0
- data/vendor/behave/features/formatter.tags_location.feature +183 -0
- data/vendor/behave/features/formatter.user_defined.feature +196 -0
- data/vendor/behave/features/i18n.unicode_problems.feature +445 -0
- data/vendor/behave/features/logcapture.clear_handlers.feature +114 -0
- data/vendor/behave/features/logcapture.feature +188 -0
- data/vendor/behave/features/logcapture.filter.feature +130 -0
- data/vendor/behave/features/logging.no_capture.feature +99 -0
- data/vendor/behave/features/logging.setup_format.feature +157 -0
- data/vendor/behave/features/logging.setup_level.feature +168 -0
- data/vendor/behave/features/logging.setup_with_configfile.feature +137 -0
- data/vendor/behave/features/parser.background.sad_cases.feature +129 -0
- data/vendor/behave/features/parser.feature.sad_cases.feature +144 -0
- data/vendor/behave/features/runner.abort_by_user.feature +305 -0
- data/vendor/behave/features/runner.continue_after_failed_step.feature +136 -0
- data/vendor/behave/features/runner.default_format.feature +175 -0
- data/vendor/behave/features/runner.dry_run.feature +184 -0
- data/vendor/behave/features/runner.feature_listfile.feature +223 -0
- data/vendor/behave/features/runner.hook_errors.feature +382 -0
- data/vendor/behave/features/runner.multiple_formatters.feature +285 -0
- data/vendor/behave/features/runner.scenario_autoretry.feature +131 -0
- data/vendor/behave/features/runner.select_files_by_regexp.example.feature +71 -0
- data/vendor/behave/features/runner.select_files_by_regexp.feature +84 -0
- data/vendor/behave/features/runner.select_scenarios_by_file_location.feature +403 -0
- data/vendor/behave/features/runner.select_scenarios_by_name.feature +289 -0
- data/vendor/behave/features/runner.select_scenarios_by_tag.feature +225 -0
- data/vendor/behave/features/runner.stop_after_failure.feature +122 -0
- data/vendor/behave/features/runner.tag_logic.feature +67 -0
- data/vendor/behave/features/runner.unknown_formatter.feature +23 -0
- data/vendor/behave/features/runner.use_stage_implementations.feature +126 -0
- data/vendor/behave/features/scenario.description.feature +171 -0
- data/vendor/behave/features/scenario.exclude_from_run.feature +217 -0
- data/vendor/behave/features/scenario_outline.basics.feature +100 -0
- data/vendor/behave/features/scenario_outline.improved.feature +177 -0
- data/vendor/behave/features/scenario_outline.name_annotation.feature +157 -0
- data/vendor/behave/features/scenario_outline.parametrized.feature +401 -0
- data/vendor/behave/features/scenario_outline.tagged_examples.feature +118 -0
- data/vendor/behave/features/step.async_steps.feature +225 -0
- data/vendor/behave/features/step.duplicated_step.feature +106 -0
- data/vendor/behave/features/step.execute_steps.feature +59 -0
- data/vendor/behave/features/step.execute_steps.with_table.feature +65 -0
- data/vendor/behave/features/step.import_other_step_module.feature +103 -0
- data/vendor/behave/features/step.pending_steps.feature +128 -0
- data/vendor/behave/features/step.undefined_steps.feature +307 -0
- data/vendor/behave/features/step.use_step_library.feature +44 -0
- data/vendor/behave/features/step_dialect.generic_steps.feature +189 -0
- data/vendor/behave/features/step_dialect.given_when_then.feature +89 -0
- data/vendor/behave/features/step_param.builtin_types.with_float.feature +239 -0
- data/vendor/behave/features/step_param.builtin_types.with_integer.feature +305 -0
- data/vendor/behave/features/step_param.custom_types.feature +134 -0
- data/vendor/behave/features/steps/behave_active_tags_steps.py +86 -0
- data/vendor/behave/features/steps/behave_context_steps.py +67 -0
- data/vendor/behave/features/steps/behave_model_tag_logic_steps.py +105 -0
- data/vendor/behave/features/steps/behave_model_util.py +105 -0
- data/vendor/behave/features/steps/behave_select_files_steps.py +83 -0
- data/vendor/behave/features/steps/behave_tag_expression_steps.py +166 -0
- data/vendor/behave/features/steps/behave_undefined_steps.py +101 -0
- data/vendor/behave/features/steps/use_steplib_behave4cmd.py +12 -0
- data/vendor/behave/features/summary.undefined_steps.feature +114 -0
- data/vendor/behave/features/tags.active_tags.feature +385 -0
- data/vendor/behave/features/tags.default_tags.feature +104 -0
- data/vendor/behave/features/tags.tag_expression.feature +105 -0
- data/vendor/behave/features/userdata.feature +331 -0
- data/vendor/behave/invoke.yaml +21 -0
- data/vendor/behave/issue.features/README.txt +17 -0
- data/vendor/behave/issue.features/environment.py +97 -0
- data/vendor/behave/issue.features/issue0030.feature +21 -0
- data/vendor/behave/issue.features/issue0031.feature +16 -0
- data/vendor/behave/issue.features/issue0032.feature +28 -0
- data/vendor/behave/issue.features/issue0035.feature +74 -0
- data/vendor/behave/issue.features/issue0040.feature +154 -0
- data/vendor/behave/issue.features/issue0041.feature +135 -0
- data/vendor/behave/issue.features/issue0042.feature +230 -0
- data/vendor/behave/issue.features/issue0044.feature +51 -0
- data/vendor/behave/issue.features/issue0046.feature +77 -0
- data/vendor/behave/issue.features/issue0052.feature +66 -0
- data/vendor/behave/issue.features/issue0059.feature +29 -0
- data/vendor/behave/issue.features/issue0063.feature +102 -0
- data/vendor/behave/issue.features/issue0064.feature +97 -0
- data/vendor/behave/issue.features/issue0065.feature +18 -0
- data/vendor/behave/issue.features/issue0066.feature +80 -0
- data/vendor/behave/issue.features/issue0067.feature +90 -0
- data/vendor/behave/issue.features/issue0069.feature +64 -0
- data/vendor/behave/issue.features/issue0072.feature +32 -0
- data/vendor/behave/issue.features/issue0073.feature +228 -0
- data/vendor/behave/issue.features/issue0075.feature +18 -0
- data/vendor/behave/issue.features/issue0077.feature +89 -0
- data/vendor/behave/issue.features/issue0080.feature +49 -0
- data/vendor/behave/issue.features/issue0081.feature +138 -0
- data/vendor/behave/issue.features/issue0083.feature +69 -0
- data/vendor/behave/issue.features/issue0084.feature +69 -0
- data/vendor/behave/issue.features/issue0085.feature +119 -0
- data/vendor/behave/issue.features/issue0092.feature +66 -0
- data/vendor/behave/issue.features/issue0096.feature +173 -0
- data/vendor/behave/issue.features/issue0099.feature +130 -0
- data/vendor/behave/issue.features/issue0109.feature +60 -0
- data/vendor/behave/issue.features/issue0111.feature +53 -0
- data/vendor/behave/issue.features/issue0112.feature +64 -0
- data/vendor/behave/issue.features/issue0114.feature +118 -0
- data/vendor/behave/issue.features/issue0116.feature +71 -0
- data/vendor/behave/issue.features/issue0125.feature +49 -0
- data/vendor/behave/issue.features/issue0127.feature +64 -0
- data/vendor/behave/issue.features/issue0139.feature +67 -0
- data/vendor/behave/issue.features/issue0142.feature +37 -0
- data/vendor/behave/issue.features/issue0143.feature +54 -0
- data/vendor/behave/issue.features/issue0145.feature +63 -0
- data/vendor/behave/issue.features/issue0148.feature +105 -0
- data/vendor/behave/issue.features/issue0152.feature +52 -0
- data/vendor/behave/issue.features/issue0159.feature +74 -0
- data/vendor/behave/issue.features/issue0162.feature +86 -0
- data/vendor/behave/issue.features/issue0171.feature +16 -0
- data/vendor/behave/issue.features/issue0172.feature +51 -0
- data/vendor/behave/issue.features/issue0175.feature +91 -0
- data/vendor/behave/issue.features/issue0177.feature +40 -0
- data/vendor/behave/issue.features/issue0181.feature +36 -0
- data/vendor/behave/issue.features/issue0184.feature +144 -0
- data/vendor/behave/issue.features/issue0186.feature +12 -0
- data/vendor/behave/issue.features/issue0188.feature +60 -0
- data/vendor/behave/issue.features/issue0191.feature +178 -0
- data/vendor/behave/issue.features/issue0194.feature +215 -0
- data/vendor/behave/issue.features/issue0197.feature +11 -0
- data/vendor/behave/issue.features/issue0216.feature +129 -0
- data/vendor/behave/issue.features/issue0226.feature +51 -0
- data/vendor/behave/issue.features/issue0228.feature +41 -0
- data/vendor/behave/issue.features/issue0230.feature +46 -0
- data/vendor/behave/issue.features/issue0231.feature +77 -0
- data/vendor/behave/issue.features/issue0238.feature +52 -0
- data/vendor/behave/issue.features/issue0251.feature +15 -0
- data/vendor/behave/issue.features/issue0280.feature +118 -0
- data/vendor/behave/issue.features/issue0288.feature +95 -0
- data/vendor/behave/issue.features/issue0300.feature +49 -0
- data/vendor/behave/issue.features/issue0302.feature +91 -0
- data/vendor/behave/issue.features/issue0309.feature +52 -0
- data/vendor/behave/issue.features/issue0330.feature +124 -0
- data/vendor/behave/issue.features/issue0349.feature +9 -0
- data/vendor/behave/issue.features/issue0361.feature +79 -0
- data/vendor/behave/issue.features/issue0383.feature +76 -0
- data/vendor/behave/issue.features/issue0384.feature +103 -0
- data/vendor/behave/issue.features/issue0385.feature +109 -0
- data/vendor/behave/issue.features/issue0424.feature +66 -0
- data/vendor/behave/issue.features/issue0446.feature +116 -0
- data/vendor/behave/issue.features/issue0449.feature +42 -0
- data/vendor/behave/issue.features/issue0453.feature +42 -0
- data/vendor/behave/issue.features/issue0457.feature +65 -0
- data/vendor/behave/issue.features/issue0462.feature +38 -0
- data/vendor/behave/issue.features/issue0476.feature +39 -0
- data/vendor/behave/issue.features/issue0487.feature +92 -0
- data/vendor/behave/issue.features/issue0506.feature +77 -0
- data/vendor/behave/issue.features/issue0510.feature +51 -0
- data/vendor/behave/issue.features/requirements.txt +12 -0
- data/vendor/behave/issue.features/steps/ansi_steps.py +20 -0
- data/vendor/behave/issue.features/steps/behave_hooks_steps.py +10 -0
- data/vendor/behave/issue.features/steps/use_steplib_behave4cmd.py +13 -0
- data/vendor/behave/more.features/formatter.json.validate_output.feature +37 -0
- data/vendor/behave/more.features/steps/tutorial_steps.py +16 -0
- data/vendor/behave/more.features/steps/use_steplib_behave4cmd.py +7 -0
- data/vendor/behave/more.features/tutorial.feature +6 -0
- data/vendor/behave/py.requirements/README.txt +5 -0
- data/vendor/behave/py.requirements/all.txt +16 -0
- data/vendor/behave/py.requirements/basic.txt +21 -0
- data/vendor/behave/py.requirements/develop.txt +28 -0
- data/vendor/behave/py.requirements/docs.txt +6 -0
- data/vendor/behave/py.requirements/json.txt +7 -0
- data/vendor/behave/py.requirements/more_py26.txt +8 -0
- data/vendor/behave/py.requirements/testing.txt +10 -0
- data/vendor/behave/pytest.ini +24 -0
- data/vendor/behave/setup.cfg +29 -0
- data/vendor/behave/setup.py +118 -0
- data/vendor/behave/setuptools_behave.py +130 -0
- data/vendor/behave/tasks/__behave.py +45 -0
- data/vendor/behave/tasks/__init__.py +55 -0
- data/vendor/behave/tasks/__main__.py +70 -0
- data/vendor/behave/tasks/_setup.py +135 -0
- data/vendor/behave/tasks/_vendor/README.rst +35 -0
- data/vendor/behave/tasks/_vendor/invoke.zip +0 -0
- data/vendor/behave/tasks/_vendor/path.py +1725 -0
- data/vendor/behave/tasks/_vendor/pathlib.py +1280 -0
- data/vendor/behave/tasks/_vendor/six.py +868 -0
- data/vendor/behave/tasks/clean.py +246 -0
- data/vendor/behave/tasks/docs.py +97 -0
- data/vendor/behave/tasks/requirements.txt +17 -0
- data/vendor/behave/tasks/test.py +192 -0
- data/vendor/behave/test/__init__.py +0 -0
- data/vendor/behave/test/_importer_candidate.py +3 -0
- data/vendor/behave/test/reporters/__init__.py +0 -0
- data/vendor/behave/test/reporters/test_summary.py +240 -0
- data/vendor/behave/test/test_ansi_escapes.py +73 -0
- data/vendor/behave/test/test_configuration.py +172 -0
- data/vendor/behave/test/test_formatter.py +265 -0
- data/vendor/behave/test/test_formatter_progress.py +39 -0
- data/vendor/behave/test/test_formatter_rerun.py +97 -0
- data/vendor/behave/test/test_formatter_tags.py +57 -0
- data/vendor/behave/test/test_importer.py +151 -0
- data/vendor/behave/test/test_log_capture.py +29 -0
- data/vendor/behave/test/test_matchers.py +236 -0
- data/vendor/behave/test/test_model.py +871 -0
- data/vendor/behave/test/test_parser.py +1590 -0
- data/vendor/behave/test/test_runner.py +1074 -0
- data/vendor/behave/test/test_step_registry.py +96 -0
- data/vendor/behave/test/test_tag_expression.py +506 -0
- data/vendor/behave/test/test_tag_expression2.py +462 -0
- data/vendor/behave/test/test_tag_matcher.py +729 -0
- data/vendor/behave/test/test_userdata.py +184 -0
- data/vendor/behave/tests/README.txt +12 -0
- data/vendor/behave/tests/__init__.py +0 -0
- data/vendor/behave/tests/api/__ONLY_PY34_or_newer.txt +0 -0
- data/vendor/behave/tests/api/__init__.py +0 -0
- data/vendor/behave/tests/api/_test_async_step34.py +130 -0
- data/vendor/behave/tests/api/_test_async_step35.py +75 -0
- data/vendor/behave/tests/api/test_async_step.py +18 -0
- data/vendor/behave/tests/api/testing_support.py +94 -0
- data/vendor/behave/tests/api/testing_support_async.py +21 -0
- data/vendor/behave/tests/issues/test_issue0336.py +66 -0
- data/vendor/behave/tests/issues/test_issue0449.py +55 -0
- data/vendor/behave/tests/issues/test_issue0453.py +62 -0
- data/vendor/behave/tests/issues/test_issue0458.py +54 -0
- data/vendor/behave/tests/issues/test_issue0495.py +65 -0
- data/vendor/behave/tests/unit/__init__.py +0 -0
- data/vendor/behave/tests/unit/test_behave4cmd_command_shell_proc.py +135 -0
- data/vendor/behave/tests/unit/test_capture.py +280 -0
- data/vendor/behave/tests/unit/test_model_core.py +56 -0
- data/vendor/behave/tests/unit/test_textutil.py +267 -0
- data/vendor/behave/tools/test-features/background.feature +9 -0
- data/vendor/behave/tools/test-features/environment.py +8 -0
- data/vendor/behave/tools/test-features/french.feature +11 -0
- data/vendor/behave/tools/test-features/outline.feature +39 -0
- data/vendor/behave/tools/test-features/parse.feature +10 -0
- data/vendor/behave/tools/test-features/step-data.feature +60 -0
- data/vendor/behave/tools/test-features/steps/steps.py +120 -0
- data/vendor/behave/tools/test-features/tags.feature +18 -0
- data/vendor/behave/tox.ini +159 -0
- metadata +562 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import six
|
|
4
|
+
|
|
5
|
+
class TagExpression(object):
|
|
6
|
+
"""
|
|
7
|
+
Tag expression, as logical boolean expression, to select
|
|
8
|
+
(include or exclude) model elements.
|
|
9
|
+
|
|
10
|
+
BOOLEAN LOGIC := (or_expr1) and (or_expr2) and ...
|
|
11
|
+
with or_exprN := [not] tag1 or [not] tag2 or ...
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, tag_expressions):
|
|
15
|
+
self.ands = []
|
|
16
|
+
self.limits = {}
|
|
17
|
+
|
|
18
|
+
for expr in tag_expressions:
|
|
19
|
+
self.store_and_extract_limits(self.normalized_tags_from_or(expr))
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def normalize_tag(tag):
|
|
23
|
+
"""
|
|
24
|
+
Normalize a tag for a tag expression:
|
|
25
|
+
|
|
26
|
+
* strip whitespace
|
|
27
|
+
* strip '@' char
|
|
28
|
+
* convert '~' (tilde) into '-' (minus sign)
|
|
29
|
+
|
|
30
|
+
:param tag: Tag (as string).
|
|
31
|
+
:return: Normalized tag (as string).
|
|
32
|
+
"""
|
|
33
|
+
tag = tag.strip()
|
|
34
|
+
if tag.startswith('@'):
|
|
35
|
+
tag = tag[1:]
|
|
36
|
+
elif tag.startswith('-@') or tag.startswith('~@'):
|
|
37
|
+
tag = '-' + tag[2:]
|
|
38
|
+
elif tag.startswith('~'):
|
|
39
|
+
tag = '-' + tag[1:]
|
|
40
|
+
return tag
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def normalized_tags_from_or(cls, expr):
|
|
44
|
+
"""
|
|
45
|
+
Normalizes all tags in an OR expression (and return it as list).
|
|
46
|
+
|
|
47
|
+
:param expr: OR expression to normalize and split (as string).
|
|
48
|
+
:return: Generator of normalized tags (as string)
|
|
49
|
+
"""
|
|
50
|
+
for tag in expr.strip().split(','):
|
|
51
|
+
yield cls.normalize_tag(tag)
|
|
52
|
+
|
|
53
|
+
def store_and_extract_limits(self, tags):
|
|
54
|
+
tags_with_negation = []
|
|
55
|
+
|
|
56
|
+
for tag in tags:
|
|
57
|
+
negated = tag.startswith('-')
|
|
58
|
+
tag = tag.split(':')
|
|
59
|
+
tag_with_negation = tag.pop(0)
|
|
60
|
+
tags_with_negation.append(tag_with_negation)
|
|
61
|
+
|
|
62
|
+
if tag:
|
|
63
|
+
limit = int(tag[0])
|
|
64
|
+
if negated:
|
|
65
|
+
tag_without_negation = tag_with_negation[1:]
|
|
66
|
+
else:
|
|
67
|
+
tag_without_negation = tag_with_negation
|
|
68
|
+
limited = tag_without_negation in self.limits
|
|
69
|
+
if limited and self.limits[tag_without_negation] != limit:
|
|
70
|
+
msg = "Inconsistent tag limits for {0}: {1:d} and {2:d}"
|
|
71
|
+
msg = msg.format(tag_without_negation,
|
|
72
|
+
self.limits[tag_without_negation], limit)
|
|
73
|
+
raise Exception(msg)
|
|
74
|
+
self.limits[tag_without_negation] = limit
|
|
75
|
+
|
|
76
|
+
if tags_with_negation:
|
|
77
|
+
self.ands.append(tags_with_negation)
|
|
78
|
+
|
|
79
|
+
def check(self, tags):
|
|
80
|
+
"""
|
|
81
|
+
Checks if this tag expression matches the tags of a model element.
|
|
82
|
+
|
|
83
|
+
:param tags: List of tags of a model element.
|
|
84
|
+
:return: True, if tag expression matches. False, otherwise.
|
|
85
|
+
"""
|
|
86
|
+
if not self.ands:
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
element_tags = set(tags)
|
|
90
|
+
|
|
91
|
+
def test_tag(xtag):
|
|
92
|
+
if xtag.startswith('-'): # -- or xtag.startswith('~'):
|
|
93
|
+
return xtag[1:] not in element_tags
|
|
94
|
+
return xtag in element_tags
|
|
95
|
+
|
|
96
|
+
# -- EVALUATE: (or_expr1) and (or_expr2) and ...
|
|
97
|
+
return all(any(test_tag(xtag) for xtag in ors) for ors in self.ands)
|
|
98
|
+
|
|
99
|
+
def __len__(self):
|
|
100
|
+
return len(self.ands)
|
|
101
|
+
|
|
102
|
+
def __str__(self):
|
|
103
|
+
"""Conversion back into string that represents this tag expression."""
|
|
104
|
+
and_parts = []
|
|
105
|
+
for or_terms in self.ands:
|
|
106
|
+
and_parts.append(u",".join(or_terms))
|
|
107
|
+
return u" ".join(and_parts)
|
|
108
|
+
|
|
109
|
+
if six.PY2:
|
|
110
|
+
__unicode__ = __str__
|
|
111
|
+
__str__ = lambda self: self.__unicode__().encode("utf-8")
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from __future__ import absolute_import
|
|
4
|
+
import re
|
|
5
|
+
import operator
|
|
6
|
+
import warnings
|
|
7
|
+
import six
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TagMatcher(object):
|
|
11
|
+
"""Abstract base class that defines the TagMatcher protocol."""
|
|
12
|
+
|
|
13
|
+
def should_run_with(self, tags):
|
|
14
|
+
"""Determines if a feature/scenario with these tags should run or not.
|
|
15
|
+
|
|
16
|
+
:param tags: List of scenario/feature tags to check.
|
|
17
|
+
:return: True, if scenario/feature should run.
|
|
18
|
+
:return: False, if scenario/feature should be excluded from the run-set.
|
|
19
|
+
"""
|
|
20
|
+
return not self.should_exclude_with(tags)
|
|
21
|
+
|
|
22
|
+
def should_exclude_with(self, tags):
|
|
23
|
+
"""Determines if a feature/scenario with these tags should be excluded
|
|
24
|
+
from the run-set.
|
|
25
|
+
|
|
26
|
+
:param tags: List of scenario/feature tags to check.
|
|
27
|
+
:return: True, if scenario/feature should be excluded from the run-set.
|
|
28
|
+
:return: False, if scenario/feature should run.
|
|
29
|
+
"""
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ActiveTagMatcher(TagMatcher):
|
|
34
|
+
"""Provides an active tag matcher for many categories.
|
|
35
|
+
|
|
36
|
+
TAG SCHEMA:
|
|
37
|
+
* active.with_{category}={value}
|
|
38
|
+
* not_active.with_{category}={value}
|
|
39
|
+
* use.with_{category}={value}
|
|
40
|
+
* not.with_{category}={value}
|
|
41
|
+
* only.with_{category}={value} (NOTE: For backward compatibility)
|
|
42
|
+
|
|
43
|
+
TAG LOGIC
|
|
44
|
+
----------
|
|
45
|
+
|
|
46
|
+
Determine active-tag groups by grouping active-tags
|
|
47
|
+
with same category together::
|
|
48
|
+
|
|
49
|
+
active_group.enabled := enabled(group.tag1) or enabled(group.tag2) or ...
|
|
50
|
+
active_tags.enabled := enabled(group1) and enabled(group2) and ...
|
|
51
|
+
|
|
52
|
+
All active-tag groups must be turned "on".
|
|
53
|
+
Otherwise, the model element should be excluded.
|
|
54
|
+
|
|
55
|
+
CONCEPT: ValueProvider
|
|
56
|
+
------------------------------
|
|
57
|
+
|
|
58
|
+
A ValueProvider provides the value of a category, used in active tags.
|
|
59
|
+
A ValueProvider must provide a mapping-like protocol:
|
|
60
|
+
|
|
61
|
+
.. code-block:: python
|
|
62
|
+
|
|
63
|
+
class MyValueProvider(object):
|
|
64
|
+
def get(self, category_name, default=None):
|
|
65
|
+
...
|
|
66
|
+
return category_value # OR: default, if category is unknown.
|
|
67
|
+
|
|
68
|
+
EXAMPLE:
|
|
69
|
+
--------
|
|
70
|
+
|
|
71
|
+
Run some scenarios only when runtime conditions are met:
|
|
72
|
+
|
|
73
|
+
* Run scenario Alice only on Windows OS
|
|
74
|
+
* Run scenario Bob with all browsers except Chrome
|
|
75
|
+
|
|
76
|
+
.. code-block:: gherkin
|
|
77
|
+
|
|
78
|
+
# -- FILE: features/alice.feature
|
|
79
|
+
Feature:
|
|
80
|
+
|
|
81
|
+
@active.with_os=win32
|
|
82
|
+
Scenario: Alice (Run only on Windows)
|
|
83
|
+
Given I do something
|
|
84
|
+
...
|
|
85
|
+
|
|
86
|
+
@not_active.with_browser=chrome
|
|
87
|
+
Scenario: Bob (Excluded with Web-Browser Chrome)
|
|
88
|
+
Given I do something else
|
|
89
|
+
...
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
.. code-block:: python
|
|
93
|
+
|
|
94
|
+
# -- FILE: features/environment.py
|
|
95
|
+
from behave.tag_matcher import ActiveTagMatcher
|
|
96
|
+
import sys
|
|
97
|
+
|
|
98
|
+
# -- MATCHES ANY ACTIVE TAGS: @{prefix}.with_{category}={value}
|
|
99
|
+
# NOTE: active_tag_value_provider provides current category values.
|
|
100
|
+
active_tag_value_provider = {
|
|
101
|
+
"browser": os.environ.get("BEHAVE_BROWSER", "chrome"),
|
|
102
|
+
"os": sys.platform,
|
|
103
|
+
}
|
|
104
|
+
active_tag_matcher = ActiveTagMatcher(active_tag_value_provider)
|
|
105
|
+
|
|
106
|
+
def before_feature(context, feature):
|
|
107
|
+
if active_tag_matcher.should_exclude_with(feature.tags):
|
|
108
|
+
feature.skip() #< LATE-EXCLUDE from run-set.
|
|
109
|
+
|
|
110
|
+
def before_scenario(context, scenario):
|
|
111
|
+
if active_tag_matcher.should_exclude_with(scenario.effective_tags):
|
|
112
|
+
exclude_reason = active_tag_matcher.exclude_reason
|
|
113
|
+
scenario.skip(exclude_reason) #< LATE-EXCLUDE from run-set.
|
|
114
|
+
"""
|
|
115
|
+
value_separator = "="
|
|
116
|
+
tag_prefixes = ["active", "not_active", "use", "not", "only"]
|
|
117
|
+
tag_schema = r"^(?P<prefix>%s)\.with_(?P<category>\w+(\.\w+)*)%s(?P<value>.*)$"
|
|
118
|
+
ignore_unknown_categories = True
|
|
119
|
+
use_exclude_reason = False
|
|
120
|
+
|
|
121
|
+
def __init__(self, value_provider, tag_prefixes=None,
|
|
122
|
+
value_separator=None, ignore_unknown_categories=None):
|
|
123
|
+
if value_provider is None:
|
|
124
|
+
value_provider = {}
|
|
125
|
+
if tag_prefixes is None:
|
|
126
|
+
tag_prefixes = self.tag_prefixes
|
|
127
|
+
if ignore_unknown_categories is None:
|
|
128
|
+
ignore_unknown_categories = self.ignore_unknown_categories
|
|
129
|
+
|
|
130
|
+
super(ActiveTagMatcher, self).__init__()
|
|
131
|
+
self.value_provider = value_provider
|
|
132
|
+
self.tag_pattern = self.make_tag_pattern(tag_prefixes, value_separator)
|
|
133
|
+
self.tag_prefixes = tag_prefixes
|
|
134
|
+
self.ignore_unknown_categories = ignore_unknown_categories
|
|
135
|
+
self.exclude_reason = None
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def make_tag_pattern(cls, tag_prefixes, value_separator=None):
|
|
139
|
+
if value_separator is None:
|
|
140
|
+
value_separator = cls.value_separator
|
|
141
|
+
any_tag_prefix = r"|".join(tag_prefixes)
|
|
142
|
+
expression = cls.tag_schema % (any_tag_prefix, value_separator)
|
|
143
|
+
return re.compile(expression)
|
|
144
|
+
|
|
145
|
+
@classmethod
|
|
146
|
+
def make_category_tag(cls, category, value=None,
|
|
147
|
+
tag_prefix=None, value_sep=None):
|
|
148
|
+
"""Build category tag (mostly for testing purposes).
|
|
149
|
+
:return: Category tag as string (without leading AT char).
|
|
150
|
+
"""
|
|
151
|
+
if tag_prefix is None:
|
|
152
|
+
tag_prefix = cls.tag_prefixes[0] # -- USE: First as default.
|
|
153
|
+
if value_sep is None:
|
|
154
|
+
value_sep = cls.value_separator
|
|
155
|
+
value = value or ""
|
|
156
|
+
return "%s.with_%s%s%s" % (tag_prefix, category, value_sep, value)
|
|
157
|
+
|
|
158
|
+
def is_tag_negated(self, tag): # pylint: disable=no-self-use
|
|
159
|
+
return tag.startswith("not")
|
|
160
|
+
|
|
161
|
+
def is_tag_group_enabled(self, group_category, group_tag_pairs):
|
|
162
|
+
"""Provides boolean logic to determine if all active-tags
|
|
163
|
+
which use the same category result in a enabled value.
|
|
164
|
+
|
|
165
|
+
Use LOGICAL-OR expression for active-tags with same category::
|
|
166
|
+
|
|
167
|
+
category_tag_group.enabled := enabled(tag1) or enabled(tag2) or ...
|
|
168
|
+
|
|
169
|
+
.. code-block:: gherkin
|
|
170
|
+
|
|
171
|
+
@use.with_xxx=alice
|
|
172
|
+
@use.with_xxx=bob
|
|
173
|
+
@not.with_xxx=charly
|
|
174
|
+
Scenario:
|
|
175
|
+
Given a step passes
|
|
176
|
+
...
|
|
177
|
+
|
|
178
|
+
:param group_category: Category for this tag-group (as string).
|
|
179
|
+
:param category_tag_group: List of active-tag match-pairs.
|
|
180
|
+
:return: True, if tag-group is enabled.
|
|
181
|
+
"""
|
|
182
|
+
if not group_tag_pairs:
|
|
183
|
+
# -- CASE: Empty group is always enabled (CORNER-CASE).
|
|
184
|
+
return True
|
|
185
|
+
|
|
186
|
+
current_value = self.value_provider.get(group_category, None)
|
|
187
|
+
if current_value is None and self.ignore_unknown_categories:
|
|
188
|
+
# -- CASE: Unknown category, ignore it.
|
|
189
|
+
return True
|
|
190
|
+
|
|
191
|
+
tags_enabled = []
|
|
192
|
+
for category_tag, tag_match in group_tag_pairs:
|
|
193
|
+
tag_prefix = tag_match.group("prefix")
|
|
194
|
+
category = tag_match.group("category")
|
|
195
|
+
tag_value = tag_match.group("value")
|
|
196
|
+
assert category == group_category
|
|
197
|
+
|
|
198
|
+
is_category_tag_switched_on = operator.eq # equal_to
|
|
199
|
+
if self.is_tag_negated(tag_prefix):
|
|
200
|
+
is_category_tag_switched_on = operator.ne # not_equal_to
|
|
201
|
+
|
|
202
|
+
tag_enabled = is_category_tag_switched_on(tag_value, current_value)
|
|
203
|
+
tags_enabled.append(tag_enabled)
|
|
204
|
+
return any(tags_enabled) # -- PROVIDES: LOGICAL-OR expression
|
|
205
|
+
|
|
206
|
+
def should_exclude_with(self, tags):
|
|
207
|
+
group_categories = self.group_active_tags_by_category(tags)
|
|
208
|
+
for group_category, category_tag_pairs in group_categories:
|
|
209
|
+
if not self.is_tag_group_enabled(group_category, category_tag_pairs):
|
|
210
|
+
# -- LOGICAL-AND SHORTCUT: Any false => Makes everything false
|
|
211
|
+
if self.use_exclude_reason:
|
|
212
|
+
current_value = self.value_provider.get(group_category, None)
|
|
213
|
+
reason = "%s (but: %s)" % (group_category, current_value)
|
|
214
|
+
self.exclude_reason = reason
|
|
215
|
+
return True # SHOULD-EXCLUDE: not enabled = not False
|
|
216
|
+
# -- LOGICAL-AND: All parts are True
|
|
217
|
+
return False # SHOULD-EXCLUDE: not enabled = not True
|
|
218
|
+
|
|
219
|
+
def select_active_tags(self, tags):
|
|
220
|
+
"""Select all active tags that match the tag schema pattern.
|
|
221
|
+
|
|
222
|
+
:param tags: List of tags (as string).
|
|
223
|
+
:return: List of (tag, match_object) pairs (as generator).
|
|
224
|
+
"""
|
|
225
|
+
for tag in tags:
|
|
226
|
+
match_object = self.tag_pattern.match(tag)
|
|
227
|
+
if match_object:
|
|
228
|
+
yield (tag, match_object)
|
|
229
|
+
|
|
230
|
+
def group_active_tags_by_category(self, tags):
|
|
231
|
+
"""Select all active tags that match the tag schema pattern
|
|
232
|
+
and returns groups of active-tags, each group with tags
|
|
233
|
+
of the same category.
|
|
234
|
+
|
|
235
|
+
:param tags: List of tags (as string).
|
|
236
|
+
:return: List of tag-groups (as generator), each tag-group is a
|
|
237
|
+
list of (tag1, match1) pairs for the same category.
|
|
238
|
+
"""
|
|
239
|
+
category_tag_groups = {}
|
|
240
|
+
for tag in tags:
|
|
241
|
+
match_object = self.tag_pattern.match(tag)
|
|
242
|
+
if match_object:
|
|
243
|
+
category = match_object.group("category")
|
|
244
|
+
category_tag_pairs = category_tag_groups.get(category, None)
|
|
245
|
+
if category_tag_pairs is None:
|
|
246
|
+
category_tag_pairs = category_tag_groups[category] = []
|
|
247
|
+
category_tag_pairs.append((tag, match_object))
|
|
248
|
+
|
|
249
|
+
for category, category_tag_pairs in six.iteritems(category_tag_groups):
|
|
250
|
+
yield (category, category_tag_pairs)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class PredicateTagMatcher(TagMatcher):
|
|
254
|
+
def __init__(self, exclude_function):
|
|
255
|
+
assert callable(exclude_function)
|
|
256
|
+
super(PredicateTagMatcher, self).__init__()
|
|
257
|
+
self.predicate = exclude_function
|
|
258
|
+
|
|
259
|
+
def should_exclude_with(self, tags):
|
|
260
|
+
return self.predicate(tags)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
class CompositeTagMatcher(TagMatcher):
|
|
264
|
+
"""Provides a composite tag matcher."""
|
|
265
|
+
|
|
266
|
+
def __init__(self, tag_matchers=None):
|
|
267
|
+
super(CompositeTagMatcher, self).__init__()
|
|
268
|
+
self.tag_matchers = tag_matchers or []
|
|
269
|
+
|
|
270
|
+
def should_exclude_with(self, tags):
|
|
271
|
+
for tag_matcher in self.tag_matchers:
|
|
272
|
+
if tag_matcher.should_exclude_with(tags):
|
|
273
|
+
return True
|
|
274
|
+
# -- OTHERWISE:
|
|
275
|
+
return False
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def setup_active_tag_values(active_tag_values, data):
|
|
279
|
+
"""Setup/update active_tag values with dict-like data.
|
|
280
|
+
Only values for keys that are already present are updated.
|
|
281
|
+
|
|
282
|
+
:param active_tag_values: Data storage for active_tag value (dict-like).
|
|
283
|
+
:param data: Data that should be used for active_tag values (dict-like).
|
|
284
|
+
"""
|
|
285
|
+
for category in list(active_tag_values.keys()):
|
|
286
|
+
if category in data:
|
|
287
|
+
active_tag_values[category] = data[category]
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# -----------------------------------------------------------------------------
|
|
291
|
+
# PROTOTYPING CLASSES:
|
|
292
|
+
# -----------------------------------------------------------------------------
|
|
293
|
+
class OnlyWithCategoryTagMatcher(TagMatcher):
|
|
294
|
+
"""
|
|
295
|
+
Provides a tag matcher that allows to determine if feature/scenario
|
|
296
|
+
should run or should be excluded from the run-set (at runtime).
|
|
297
|
+
|
|
298
|
+
.. deprecated:: Use :class:`ActiveTagMatcher` instead.
|
|
299
|
+
|
|
300
|
+
EXAMPLE:
|
|
301
|
+
--------
|
|
302
|
+
|
|
303
|
+
Run some scenarios only when runtime conditions are met:
|
|
304
|
+
|
|
305
|
+
* Run scenario Alice only on Windows OS
|
|
306
|
+
* Run scenario Bob only on MACOSX
|
|
307
|
+
|
|
308
|
+
.. code-block:: gherkin
|
|
309
|
+
|
|
310
|
+
# -- FILE: features/alice.feature
|
|
311
|
+
# TAG SCHEMA: @only.with_{category}={current_value}
|
|
312
|
+
Feature:
|
|
313
|
+
|
|
314
|
+
@only.with_os=win32
|
|
315
|
+
Scenario: Alice (Run only on Windows)
|
|
316
|
+
Given I do something
|
|
317
|
+
...
|
|
318
|
+
|
|
319
|
+
@only.with_os=darwin
|
|
320
|
+
Scenario: Bob (Run only on MACOSX)
|
|
321
|
+
Given I do something else
|
|
322
|
+
...
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
.. code-block:: python
|
|
326
|
+
|
|
327
|
+
# -- FILE: features/environment.py
|
|
328
|
+
from behave.tag_matcher import OnlyWithCategoryTagMatcher
|
|
329
|
+
import sys
|
|
330
|
+
|
|
331
|
+
# -- MATCHES TAGS: @only.with_{category}=* = @only.with_os=*
|
|
332
|
+
active_tag_matcher = OnlyWithCategoryTagMatcher("os", sys.platform)
|
|
333
|
+
|
|
334
|
+
def before_scenario(context, scenario):
|
|
335
|
+
if active_tag_matcher.should_exclude_with(scenario.effective_tags):
|
|
336
|
+
scenario.skip() #< LATE-EXCLUDE from run-set.
|
|
337
|
+
"""
|
|
338
|
+
tag_prefix = "only.with_"
|
|
339
|
+
value_separator = "="
|
|
340
|
+
|
|
341
|
+
def __init__(self, category, value, tag_prefix=None, value_sep=None):
|
|
342
|
+
warnings.warn("Use ActiveTagMatcher instead.", DeprecationWarning)
|
|
343
|
+
super(OnlyWithCategoryTagMatcher, self).__init__()
|
|
344
|
+
self.active_tag = self.make_category_tag(category, value,
|
|
345
|
+
tag_prefix, value_sep)
|
|
346
|
+
self.category_tag_prefix = self.make_category_tag(category, None,
|
|
347
|
+
tag_prefix, value_sep)
|
|
348
|
+
|
|
349
|
+
def should_exclude_with(self, tags):
|
|
350
|
+
category_tags = self.select_category_tags(tags)
|
|
351
|
+
if category_tags and self.active_tag not in category_tags:
|
|
352
|
+
return True
|
|
353
|
+
# -- OTHERWISE: feature/scenario with theses tags should run.
|
|
354
|
+
return False
|
|
355
|
+
|
|
356
|
+
def select_category_tags(self, tags):
|
|
357
|
+
return [tag for tag in tags
|
|
358
|
+
if tag.startswith(self.category_tag_prefix)]
|
|
359
|
+
|
|
360
|
+
@classmethod
|
|
361
|
+
def make_category_tag(cls, category, value=None, tag_prefix=None,
|
|
362
|
+
value_sep=None):
|
|
363
|
+
if tag_prefix is None:
|
|
364
|
+
tag_prefix = cls.tag_prefix
|
|
365
|
+
if value_sep is None:
|
|
366
|
+
value_sep = cls.value_separator
|
|
367
|
+
value = value or ""
|
|
368
|
+
return "%s%s%s%s" % (tag_prefix, category, value_sep, value)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class OnlyWithAnyCategoryTagMatcher(TagMatcher):
|
|
372
|
+
"""
|
|
373
|
+
Provides a tag matcher that matches any category that follows the
|
|
374
|
+
"@only.with_" tag schema and determines if it should run or
|
|
375
|
+
should be excluded from the run-set (at runtime).
|
|
376
|
+
|
|
377
|
+
TAG SCHEMA: @only.with_{category}={value}
|
|
378
|
+
|
|
379
|
+
.. seealso:: OnlyWithCategoryTagMatcher
|
|
380
|
+
.. deprecated:: Use :class:`ActiveTagMatcher` instead.
|
|
381
|
+
|
|
382
|
+
EXAMPLE:
|
|
383
|
+
--------
|
|
384
|
+
|
|
385
|
+
Run some scenarios only when runtime conditions are met:
|
|
386
|
+
|
|
387
|
+
* Run scenario Alice only on Windows OS
|
|
388
|
+
* Run scenario Bob only with browser Chrome
|
|
389
|
+
|
|
390
|
+
.. code-block:: gherkin
|
|
391
|
+
|
|
392
|
+
# -- FILE: features/alice.feature
|
|
393
|
+
# TAG SCHEMA: @only.with_{category}={current_value}
|
|
394
|
+
Feature:
|
|
395
|
+
|
|
396
|
+
@only.with_os=win32
|
|
397
|
+
Scenario: Alice (Run only on Windows)
|
|
398
|
+
Given I do something
|
|
399
|
+
...
|
|
400
|
+
|
|
401
|
+
@only.with_browser=chrome
|
|
402
|
+
Scenario: Bob (Run only with Web-Browser Chrome)
|
|
403
|
+
Given I do something else
|
|
404
|
+
...
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
.. code-block:: python
|
|
408
|
+
|
|
409
|
+
# -- FILE: features/environment.py
|
|
410
|
+
from behave.tag_matcher import OnlyWithAnyCategoryTagMatcher
|
|
411
|
+
import sys
|
|
412
|
+
|
|
413
|
+
# -- MATCHES ANY TAGS: @only.with_{category}={value}
|
|
414
|
+
# NOTE: active_tag_value_provider provides current category values.
|
|
415
|
+
active_tag_value_provider = {
|
|
416
|
+
"browser": os.environ.get("BEHAVE_BROWSER", "chrome"),
|
|
417
|
+
"os": sys.platform,
|
|
418
|
+
}
|
|
419
|
+
active_tag_matcher = OnlyWithAnyCategoryTagMatcher(active_tag_value_provider)
|
|
420
|
+
|
|
421
|
+
def before_scenario(context, scenario):
|
|
422
|
+
if active_tag_matcher.should_exclude_with(scenario.effective_tags):
|
|
423
|
+
scenario.skip() #< LATE-EXCLUDE from run-set.
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
def __init__(self, value_provider, tag_prefix=None, value_sep=None):
|
|
427
|
+
warnings.warn("Use ActiveTagMatcher instead.", DeprecationWarning)
|
|
428
|
+
super(OnlyWithAnyCategoryTagMatcher, self).__init__()
|
|
429
|
+
if value_sep is None:
|
|
430
|
+
value_sep = OnlyWithCategoryTagMatcher.value_separator
|
|
431
|
+
self.value_provider = value_provider
|
|
432
|
+
self.tag_prefix = tag_prefix or OnlyWithCategoryTagMatcher.tag_prefix
|
|
433
|
+
self.value_separator = value_sep
|
|
434
|
+
|
|
435
|
+
def should_exclude_with(self, tags):
|
|
436
|
+
exclude_decision_map = {}
|
|
437
|
+
for category_tag in self.select_category_tags(tags):
|
|
438
|
+
category, value = self.parse_category_tag(category_tag)
|
|
439
|
+
active_value = self.value_provider.get(category, None)
|
|
440
|
+
if active_value is None:
|
|
441
|
+
# -- CASE: Unknown category, ignore it.
|
|
442
|
+
continue
|
|
443
|
+
elif active_value == value:
|
|
444
|
+
# -- CASE: Active category value selected, decision should run.
|
|
445
|
+
exclude_decision_map[category] = False
|
|
446
|
+
else:
|
|
447
|
+
# -- CASE: Inactive category value selected, may exclude it.
|
|
448
|
+
if category not in exclude_decision_map:
|
|
449
|
+
exclude_decision_map[category] = True
|
|
450
|
+
return any(exclude_decision_map.values())
|
|
451
|
+
|
|
452
|
+
def select_category_tags(self, tags):
|
|
453
|
+
return [tag for tag in tags
|
|
454
|
+
if tag.startswith(self.tag_prefix)]
|
|
455
|
+
|
|
456
|
+
def parse_category_tag(self, tag):
|
|
457
|
+
assert tag and tag.startswith(self.tag_prefix)
|
|
458
|
+
category_value = tag[len(self.tag_prefix):]
|
|
459
|
+
if self.value_separator in category_value:
|
|
460
|
+
category, value = category_value.split(self.value_separator, 1)
|
|
461
|
+
else:
|
|
462
|
+
# -- OOPS: TAG SCHEMA FORMAT MISMATCH
|
|
463
|
+
category = category_value
|
|
464
|
+
value = None
|
|
465
|
+
return category, value
|