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,615 @@
|
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
|
2
|
+
|
|
3
|
+
from __future__ import absolute_import, with_statement
|
|
4
|
+
import re
|
|
5
|
+
import sys
|
|
6
|
+
import six
|
|
7
|
+
from behave import model, i18n
|
|
8
|
+
from behave.textutil import text as _text
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
DEFAULT_LANGUAGE = "en"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def parse_file(filename, language=None):
|
|
15
|
+
with open(filename, "rb") as f:
|
|
16
|
+
# file encoding is assumed to be utf8. Oh, yes.
|
|
17
|
+
data = f.read().decode("utf8")
|
|
18
|
+
return parse_feature(data, language, filename)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def parse_feature(data, language=None, filename=None):
|
|
22
|
+
# ALL data operated on by the parser MUST be unicode
|
|
23
|
+
assert isinstance(data, six.text_type)
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
result = Parser(language).parse(data, filename)
|
|
27
|
+
except ParserError as e:
|
|
28
|
+
e.filename = filename
|
|
29
|
+
raise
|
|
30
|
+
|
|
31
|
+
return result
|
|
32
|
+
|
|
33
|
+
def parse_steps(text, language=None, filename=None):
|
|
34
|
+
"""
|
|
35
|
+
Parse a number of steps a multi-line text from a scenario.
|
|
36
|
+
Scenario line with title and keyword is not provided.
|
|
37
|
+
|
|
38
|
+
:param text: Multi-line text with steps to parse (as unicode).
|
|
39
|
+
:param language: i18n language identifier (optional).
|
|
40
|
+
:param filename: Filename (optional).
|
|
41
|
+
:return: Parsed steps (if successful).
|
|
42
|
+
"""
|
|
43
|
+
assert isinstance(text, six.text_type)
|
|
44
|
+
try:
|
|
45
|
+
result = Parser(language, variant="steps").parse_steps(text, filename)
|
|
46
|
+
except ParserError as e:
|
|
47
|
+
e.filename = filename
|
|
48
|
+
raise
|
|
49
|
+
return result
|
|
50
|
+
|
|
51
|
+
def parse_tags(text):
|
|
52
|
+
"""
|
|
53
|
+
Parse tags from text (one or more lines, as string).
|
|
54
|
+
|
|
55
|
+
:param text: Multi-line text with tags to parse (as unicode).
|
|
56
|
+
:return: List of tags (if successful).
|
|
57
|
+
"""
|
|
58
|
+
# assert isinstance(text, unicode)
|
|
59
|
+
if not text:
|
|
60
|
+
return []
|
|
61
|
+
return Parser(variant="tags").parse_tags(text)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class ParserError(Exception):
|
|
65
|
+
def __init__(self, message, line, filename=None, line_text=None):
|
|
66
|
+
if line:
|
|
67
|
+
message += u" at line %d" % line
|
|
68
|
+
if line_text:
|
|
69
|
+
message += u': "%s"' % line_text.strip()
|
|
70
|
+
super(ParserError, self).__init__(message)
|
|
71
|
+
self.line = line
|
|
72
|
+
self.line_text = line_text
|
|
73
|
+
self.filename = filename
|
|
74
|
+
|
|
75
|
+
def __str__(self):
|
|
76
|
+
arg0 = _text(self.args[0])
|
|
77
|
+
if self.filename:
|
|
78
|
+
filename = _text(self.filename, sys.getfilesystemencoding())
|
|
79
|
+
return u'Failed to parse "%s": %s' % (filename, arg0)
|
|
80
|
+
else:
|
|
81
|
+
return u"Failed to parse <string>: %s" % arg0
|
|
82
|
+
|
|
83
|
+
if six.PY2:
|
|
84
|
+
__unicode__ = __str__
|
|
85
|
+
__str__ = lambda self: self.__unicode__().encode("utf-8")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Parser(object):
|
|
89
|
+
"""Feature file parser for behave."""
|
|
90
|
+
# pylint: disable=too-many-instance-attributes
|
|
91
|
+
|
|
92
|
+
def __init__(self, language=None, variant=None):
|
|
93
|
+
if not variant:
|
|
94
|
+
variant = "feature"
|
|
95
|
+
self.language = language
|
|
96
|
+
self.variant = variant
|
|
97
|
+
self.state = "init"
|
|
98
|
+
self.line = 0
|
|
99
|
+
self.last_step = None
|
|
100
|
+
self.multiline_start = None
|
|
101
|
+
self.multiline_leading = None
|
|
102
|
+
self.multiline_terminator = None
|
|
103
|
+
|
|
104
|
+
self.filename = None
|
|
105
|
+
self.feature = None
|
|
106
|
+
self.statement = None
|
|
107
|
+
self.tags = []
|
|
108
|
+
self.lines = []
|
|
109
|
+
self.table = None
|
|
110
|
+
self.examples = None
|
|
111
|
+
self.keywords = None
|
|
112
|
+
if self.language:
|
|
113
|
+
self.keywords = i18n.languages[self.language]
|
|
114
|
+
# NOT-NEEDED: self.reset()
|
|
115
|
+
|
|
116
|
+
def reset(self):
|
|
117
|
+
# This can probably go away.
|
|
118
|
+
if self.language:
|
|
119
|
+
self.keywords = i18n.languages[self.language]
|
|
120
|
+
else:
|
|
121
|
+
self.keywords = None
|
|
122
|
+
|
|
123
|
+
self.state = "init"
|
|
124
|
+
self.line = 0
|
|
125
|
+
self.last_step = None
|
|
126
|
+
self.multiline_start = None
|
|
127
|
+
self.multiline_leading = None
|
|
128
|
+
self.multiline_terminator = None
|
|
129
|
+
|
|
130
|
+
self.filename = None
|
|
131
|
+
self.feature = None
|
|
132
|
+
self.statement = None
|
|
133
|
+
self.tags = []
|
|
134
|
+
self.lines = []
|
|
135
|
+
self.table = None
|
|
136
|
+
self.examples = None
|
|
137
|
+
|
|
138
|
+
def parse(self, data, filename=None):
|
|
139
|
+
self.reset()
|
|
140
|
+
|
|
141
|
+
self.filename = filename
|
|
142
|
+
|
|
143
|
+
for line in data.split("\n"):
|
|
144
|
+
self.line += 1
|
|
145
|
+
if not line.strip() and self.state != "multiline":
|
|
146
|
+
# -- SKIP EMPTY LINES, except in multiline string args.
|
|
147
|
+
continue
|
|
148
|
+
self.action(line)
|
|
149
|
+
|
|
150
|
+
if self.table:
|
|
151
|
+
self.action_table("")
|
|
152
|
+
|
|
153
|
+
feature = self.feature
|
|
154
|
+
if feature:
|
|
155
|
+
feature.parser = self
|
|
156
|
+
self.reset()
|
|
157
|
+
return feature
|
|
158
|
+
|
|
159
|
+
def _build_feature(self, keyword, line):
|
|
160
|
+
name = line[len(keyword) + 1:].strip()
|
|
161
|
+
language = self.language or DEFAULT_LANGUAGE
|
|
162
|
+
self.feature = model.Feature(self.filename, self.line, keyword,
|
|
163
|
+
name, tags=self.tags, language=language)
|
|
164
|
+
# -- RESET STATE:
|
|
165
|
+
self.tags = []
|
|
166
|
+
|
|
167
|
+
def _build_background_statement(self, keyword, line):
|
|
168
|
+
if self.tags:
|
|
169
|
+
msg = u"Background supports no tags: @%s" % (u" @".join(self.tags))
|
|
170
|
+
raise ParserError(msg, self.line, self.filename, line)
|
|
171
|
+
name = line[len(keyword) + 1:].strip()
|
|
172
|
+
statement = model.Background(self.filename, self.line, keyword, name)
|
|
173
|
+
self.statement = statement
|
|
174
|
+
self.feature.background = self.statement
|
|
175
|
+
|
|
176
|
+
def _build_scenario_statement(self, keyword, line):
|
|
177
|
+
name = line[len(keyword) + 1:].strip()
|
|
178
|
+
self.statement = model.Scenario(self.filename, self.line,
|
|
179
|
+
keyword, name, tags=self.tags)
|
|
180
|
+
self.feature.add_scenario(self.statement)
|
|
181
|
+
# -- RESET STATE:
|
|
182
|
+
self.tags = []
|
|
183
|
+
|
|
184
|
+
def _build_scenario_outline_statement(self, keyword, line):
|
|
185
|
+
# pylint: disable=C0103
|
|
186
|
+
# C0103 Invalid name "build_scenario_outline_statement", too long.
|
|
187
|
+
name = line[len(keyword) + 1:].strip()
|
|
188
|
+
self.statement = model.ScenarioOutline(self.filename, self.line,
|
|
189
|
+
keyword, name, tags=self.tags)
|
|
190
|
+
self.feature.add_scenario(self.statement)
|
|
191
|
+
# -- RESET STATE:
|
|
192
|
+
self.tags = []
|
|
193
|
+
|
|
194
|
+
def _build_examples(self, keyword, line):
|
|
195
|
+
if not isinstance(self.statement, model.ScenarioOutline):
|
|
196
|
+
message = u"Examples must only appear inside scenario outline"
|
|
197
|
+
raise ParserError(message, self.line, self.filename, line)
|
|
198
|
+
name = line[len(keyword) + 1:].strip()
|
|
199
|
+
self.examples = model.Examples(self.filename, self.line,
|
|
200
|
+
keyword, name, tags=self.tags)
|
|
201
|
+
# pylint: disable=E1103
|
|
202
|
+
# E1103 Instance of "Background" has no "examples" member
|
|
203
|
+
# (but some types could not be inferred).
|
|
204
|
+
self.statement.examples.append(self.examples)
|
|
205
|
+
|
|
206
|
+
# -- RESET STATE:
|
|
207
|
+
self.tags = []
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def diagnose_feature_usage_error(self):
|
|
211
|
+
if self.feature:
|
|
212
|
+
return "Multiple features in one file are not supported."
|
|
213
|
+
else:
|
|
214
|
+
return "Feature should not be used here."
|
|
215
|
+
|
|
216
|
+
def diagnose_background_usage_error(self):
|
|
217
|
+
if self.feature and self.feature.scenarios:
|
|
218
|
+
return "Background may not occur after Scenario/ScenarioOutline."
|
|
219
|
+
elif self.tags:
|
|
220
|
+
return "Background does not support tags."
|
|
221
|
+
else:
|
|
222
|
+
return "Background should not be used here."
|
|
223
|
+
|
|
224
|
+
def diagnose_scenario_usage_error(self):
|
|
225
|
+
if not self.feature:
|
|
226
|
+
return "Scenario may not occur before Feature."
|
|
227
|
+
else:
|
|
228
|
+
return "Scenario should not be used here."
|
|
229
|
+
|
|
230
|
+
def diagnose_scenario_outline_usage_error(self): # pylint: disable=invalid-name
|
|
231
|
+
if not self.feature:
|
|
232
|
+
return "ScenarioOutline may not occur before Feature."
|
|
233
|
+
else:
|
|
234
|
+
return "ScenarioOutline should not be used here."
|
|
235
|
+
|
|
236
|
+
def ask_parse_failure_oracle(self, line):
|
|
237
|
+
"""
|
|
238
|
+
Try to find the failure reason when a parse failure occurs:
|
|
239
|
+
|
|
240
|
+
Oracle, oracle, ... what went wrong?
|
|
241
|
+
Zzzz
|
|
242
|
+
|
|
243
|
+
:param line: Text line where parse failure occured (as string).
|
|
244
|
+
:return: Reason (as string) if an explanation is found.
|
|
245
|
+
Otherwise, empty string or None.
|
|
246
|
+
"""
|
|
247
|
+
feature_kwd = self.match_keyword("feature", line)
|
|
248
|
+
if feature_kwd:
|
|
249
|
+
return self.diagnose_feature_usage_error()
|
|
250
|
+
background_kwd = self.match_keyword("background", line)
|
|
251
|
+
if background_kwd:
|
|
252
|
+
return self.diagnose_background_usage_error()
|
|
253
|
+
scenario_kwd = self.match_keyword("scenario", line)
|
|
254
|
+
if scenario_kwd:
|
|
255
|
+
return self.diagnose_scenario_usage_error()
|
|
256
|
+
scenario_outline_kwd = self.match_keyword("scenario_outline", line)
|
|
257
|
+
if scenario_outline_kwd:
|
|
258
|
+
return self.diagnose_scenario_outline_usage_error()
|
|
259
|
+
# -- OTHERWISE:
|
|
260
|
+
if self.variant == "feature" and not self.feature:
|
|
261
|
+
return "No feature found."
|
|
262
|
+
# -- FINALLY: No glue what went wrong.
|
|
263
|
+
return None
|
|
264
|
+
|
|
265
|
+
def action(self, line):
|
|
266
|
+
if line.strip().startswith("#") and self.state != "multiline":
|
|
267
|
+
if self.state != "init" or self.tags or self.variant != "feature":
|
|
268
|
+
return
|
|
269
|
+
|
|
270
|
+
# -- DETECT: language comment (at begin of feature file; state=init)
|
|
271
|
+
line = line.strip()[1:].strip()
|
|
272
|
+
if line.lstrip().lower().startswith("language:"):
|
|
273
|
+
language = line[9:].strip()
|
|
274
|
+
self.language = language
|
|
275
|
+
self.keywords = i18n.languages[language]
|
|
276
|
+
return
|
|
277
|
+
|
|
278
|
+
func = getattr(self, "action_" + self.state, None)
|
|
279
|
+
if func is None:
|
|
280
|
+
line = line.strip()
|
|
281
|
+
msg = u"Parser in unknown state %s;" % self.state
|
|
282
|
+
raise ParserError(msg, self.line, self.filename, line)
|
|
283
|
+
if not func(line):
|
|
284
|
+
line = line.strip()
|
|
285
|
+
msg = u'\nParser failure in state %s, at line %d: "%s"\n' % \
|
|
286
|
+
(self.state, self.line, line)
|
|
287
|
+
reason = self.ask_parse_failure_oracle(line)
|
|
288
|
+
if reason:
|
|
289
|
+
msg += u"REASON: %s" % reason
|
|
290
|
+
raise ParserError(msg, None, self.filename)
|
|
291
|
+
|
|
292
|
+
def action_init(self, line):
|
|
293
|
+
line = line.strip()
|
|
294
|
+
if line.startswith("@"):
|
|
295
|
+
self.tags.extend(self.parse_tags(line))
|
|
296
|
+
return True
|
|
297
|
+
|
|
298
|
+
feature_kwd = self.match_keyword("feature", line)
|
|
299
|
+
if feature_kwd:
|
|
300
|
+
self._build_feature(feature_kwd, line)
|
|
301
|
+
self.state = "feature"
|
|
302
|
+
return True
|
|
303
|
+
return False
|
|
304
|
+
|
|
305
|
+
# def subaction_detect_next_scenario(self, line):
|
|
306
|
+
# if line.startswith("@"):
|
|
307
|
+
# self.tags.extend(self.parse_tags(line))
|
|
308
|
+
# self.state = "next_scenario"
|
|
309
|
+
# return True
|
|
310
|
+
#
|
|
311
|
+
# scenario_kwd = self.match_keyword("scenario", line)
|
|
312
|
+
# if scenario_kwd:
|
|
313
|
+
# self._build_scenario_statement(scenario_kwd, line)
|
|
314
|
+
# self.state = "scenario"
|
|
315
|
+
# return True
|
|
316
|
+
#
|
|
317
|
+
# scenario_outline_kwd = self.match_keyword("scenario_outline", line)
|
|
318
|
+
# if scenario_outline_kwd:
|
|
319
|
+
# self._build_scenario_outline_statement(scenario_outline_kwd, line)
|
|
320
|
+
# self.state = "scenario"
|
|
321
|
+
# return True
|
|
322
|
+
#
|
|
323
|
+
# # -- OTHERWISE:
|
|
324
|
+
# return False
|
|
325
|
+
|
|
326
|
+
# pylint: disable=invalid-name
|
|
327
|
+
def subaction_detect_taggable_statement(self, line):
|
|
328
|
+
"""Subaction is used after first tag line is detected.
|
|
329
|
+
Additional lines with tags or taggable_statement follow.
|
|
330
|
+
|
|
331
|
+
Taggable statements (excluding Feature) are:
|
|
332
|
+
* Scenario
|
|
333
|
+
* ScenarioOutline
|
|
334
|
+
* Examples (within ScenarioOutline)
|
|
335
|
+
"""
|
|
336
|
+
if line.startswith("@"):
|
|
337
|
+
self.tags.extend(self.parse_tags(line))
|
|
338
|
+
self.state = "taggable_statement"
|
|
339
|
+
return True
|
|
340
|
+
|
|
341
|
+
scenario_kwd = self.match_keyword("scenario", line)
|
|
342
|
+
if scenario_kwd:
|
|
343
|
+
self._build_scenario_statement(scenario_kwd, line)
|
|
344
|
+
self.state = "scenario"
|
|
345
|
+
return True
|
|
346
|
+
|
|
347
|
+
scenario_outline_kwd = self.match_keyword("scenario_outline", line)
|
|
348
|
+
if scenario_outline_kwd:
|
|
349
|
+
self._build_scenario_outline_statement(scenario_outline_kwd, line)
|
|
350
|
+
self.state = "scenario"
|
|
351
|
+
return True
|
|
352
|
+
|
|
353
|
+
examples_kwd = self.match_keyword("examples", line)
|
|
354
|
+
if examples_kwd:
|
|
355
|
+
self._build_examples(examples_kwd, line)
|
|
356
|
+
self.state = "table"
|
|
357
|
+
return True
|
|
358
|
+
|
|
359
|
+
# -- OTHERWISE:
|
|
360
|
+
return False
|
|
361
|
+
# pylint: enable=invalid-name
|
|
362
|
+
|
|
363
|
+
def action_feature(self, line):
|
|
364
|
+
line = line.strip()
|
|
365
|
+
# OLD: if self.subaction_detect_next_scenario(line):
|
|
366
|
+
if self.subaction_detect_taggable_statement(line):
|
|
367
|
+
# -- DETECTED: Next Scenario, ScenarioOutline (or tags)
|
|
368
|
+
return True
|
|
369
|
+
|
|
370
|
+
background_kwd = self.match_keyword("background", line)
|
|
371
|
+
if background_kwd:
|
|
372
|
+
self._build_background_statement(background_kwd, line)
|
|
373
|
+
self.state = "steps"
|
|
374
|
+
return True
|
|
375
|
+
|
|
376
|
+
self.feature.description.append(line)
|
|
377
|
+
return True
|
|
378
|
+
|
|
379
|
+
# def action_next_scenario(self, line):
|
|
380
|
+
# """
|
|
381
|
+
# Entered after first tag for Scenario/ScenarioOutline is detected.
|
|
382
|
+
# """
|
|
383
|
+
# line = line.strip()
|
|
384
|
+
# if self.subaction_detect_next_scenario(line):
|
|
385
|
+
# return True
|
|
386
|
+
#
|
|
387
|
+
# return False
|
|
388
|
+
|
|
389
|
+
def action_taggable_statement(self, line):
|
|
390
|
+
"""Entered after first tag for Scenario/ScenarioOutline or
|
|
391
|
+
Examples is detected (= taggable_statement except Feature).
|
|
392
|
+
|
|
393
|
+
Taggable statements (excluding Feature) are:
|
|
394
|
+
* Scenario
|
|
395
|
+
* ScenarioOutline
|
|
396
|
+
* Examples (within ScenarioOutline)
|
|
397
|
+
"""
|
|
398
|
+
line = line.strip()
|
|
399
|
+
if self.subaction_detect_taggable_statement(line):
|
|
400
|
+
# -- DETECTED: Next Scenario, ScenarioOutline or Examples (or tags)
|
|
401
|
+
return True
|
|
402
|
+
|
|
403
|
+
return False
|
|
404
|
+
|
|
405
|
+
def action_scenario(self, line):
|
|
406
|
+
"""
|
|
407
|
+
Entered when Scenario/ScenarioOutline keyword/line is detected.
|
|
408
|
+
Hunts/collects scenario description lines.
|
|
409
|
+
|
|
410
|
+
DETECT:
|
|
411
|
+
* first step of Scenario/ScenarioOutline
|
|
412
|
+
* next Scenario/ScenarioOutline.
|
|
413
|
+
"""
|
|
414
|
+
line = line.strip()
|
|
415
|
+
step = self.parse_step(line)
|
|
416
|
+
if step:
|
|
417
|
+
# -- FIRST STEP DETECTED: End collection of scenario descriptions.
|
|
418
|
+
self.state = "steps"
|
|
419
|
+
self.statement.steps.append(step)
|
|
420
|
+
return True
|
|
421
|
+
|
|
422
|
+
# -- CASE: Detect next Scenario/ScenarioOutline
|
|
423
|
+
# * Scenario with scenario description, but without steps.
|
|
424
|
+
# * Title-only scenario without scenario description and steps.
|
|
425
|
+
# OLD: if self.subaction_detect_next_scenario(line):
|
|
426
|
+
if self.subaction_detect_taggable_statement(line):
|
|
427
|
+
# -- DETECTED: Next Scenario, ScenarioOutline (or tags)
|
|
428
|
+
return True
|
|
429
|
+
|
|
430
|
+
# -- OTHERWISE: Add scenario description line.
|
|
431
|
+
# pylint: disable=E1103
|
|
432
|
+
# E1103 Instance of "Background" has no "description" member...
|
|
433
|
+
self.statement.description.append(line)
|
|
434
|
+
return True
|
|
435
|
+
|
|
436
|
+
def action_steps(self, line):
|
|
437
|
+
"""
|
|
438
|
+
Entered when first step is detected (or nested step parsing).
|
|
439
|
+
|
|
440
|
+
Subcases:
|
|
441
|
+
* step
|
|
442
|
+
* multi-line text (doc-string), following a step
|
|
443
|
+
* table, following a step
|
|
444
|
+
* examples for a ScenarioOutline, after ScenarioOutline steps
|
|
445
|
+
|
|
446
|
+
DETECT:
|
|
447
|
+
* next Scenario/ScenarioOutline or Examples (in a ScenarioOutline)
|
|
448
|
+
"""
|
|
449
|
+
# pylint: disable=R0911
|
|
450
|
+
# R0911 Too many return statements (8/6)
|
|
451
|
+
stripped = line.lstrip()
|
|
452
|
+
if stripped.startswith('"""') or stripped.startswith("'''"):
|
|
453
|
+
self.state = "multiline"
|
|
454
|
+
self.multiline_start = self.line
|
|
455
|
+
self.multiline_terminator = stripped[:3]
|
|
456
|
+
self.multiline_leading = line.index(stripped[0])
|
|
457
|
+
return True
|
|
458
|
+
|
|
459
|
+
line = line.strip()
|
|
460
|
+
step = self.parse_step(line)
|
|
461
|
+
if step:
|
|
462
|
+
self.statement.steps.append(step)
|
|
463
|
+
return True
|
|
464
|
+
|
|
465
|
+
if self.subaction_detect_taggable_statement(line):
|
|
466
|
+
# -- DETECTED: Next Scenario, ScenarioOutline or Examples (or tags)
|
|
467
|
+
return True
|
|
468
|
+
|
|
469
|
+
if line.startswith("|"):
|
|
470
|
+
assert self.statement.steps, "TABLE-START without step detected."
|
|
471
|
+
self.state = "table"
|
|
472
|
+
return self.action_table(line)
|
|
473
|
+
|
|
474
|
+
return False
|
|
475
|
+
|
|
476
|
+
def action_multiline(self, line):
|
|
477
|
+
if line.strip().startswith(self.multiline_terminator):
|
|
478
|
+
step = self.statement.steps[-1]
|
|
479
|
+
step.text = model.Text(u"\n".join(self.lines), u"text/plain",
|
|
480
|
+
self.multiline_start)
|
|
481
|
+
if step.name.endswith(":"):
|
|
482
|
+
step.name = step.name[:-1]
|
|
483
|
+
self.lines = []
|
|
484
|
+
self.multiline_terminator = None
|
|
485
|
+
self.state = "steps"
|
|
486
|
+
return True
|
|
487
|
+
|
|
488
|
+
self.lines.append(line[self.multiline_leading:])
|
|
489
|
+
# -- BETTER DIAGNOSTICS: May remove non-whitespace in execute_steps()
|
|
490
|
+
removed_line_prefix = line[:self.multiline_leading]
|
|
491
|
+
if removed_line_prefix.strip():
|
|
492
|
+
message = u"BAD-INDENT in multiline text: "
|
|
493
|
+
message += u"Line '%s' would strip leading '%s'" % \
|
|
494
|
+
(line, removed_line_prefix)
|
|
495
|
+
raise ParserError(message, self.line, self.filename)
|
|
496
|
+
return True
|
|
497
|
+
|
|
498
|
+
def action_table(self, line):
|
|
499
|
+
line = line.strip()
|
|
500
|
+
|
|
501
|
+
if not line.startswith("|"):
|
|
502
|
+
if self.examples:
|
|
503
|
+
self.examples.table = self.table
|
|
504
|
+
self.examples = None
|
|
505
|
+
else:
|
|
506
|
+
step = self.statement.steps[-1]
|
|
507
|
+
step.table = self.table
|
|
508
|
+
if step.name.endswith(":"):
|
|
509
|
+
step.name = step.name[:-1]
|
|
510
|
+
self.table = None
|
|
511
|
+
self.state = "steps"
|
|
512
|
+
return self.action_steps(line)
|
|
513
|
+
|
|
514
|
+
# -- SUPPORT: Escaped-pipe(s) in Gherkin cell values.
|
|
515
|
+
# Search for pipe(s) that are not preceeded with an escape char.
|
|
516
|
+
cells = [cell.replace("\\|", "|").strip()
|
|
517
|
+
for cell in re.split(r"(?<!\\)\|", line[1:-1])]
|
|
518
|
+
if self.table is None:
|
|
519
|
+
self.table = model.Table(cells, self.line)
|
|
520
|
+
else:
|
|
521
|
+
if len(cells) != len(self.table.headings):
|
|
522
|
+
raise ParserError(u"Malformed table", self.line)
|
|
523
|
+
self.table.add_row(cells, self.line)
|
|
524
|
+
return True
|
|
525
|
+
|
|
526
|
+
def match_keyword(self, keyword, line):
|
|
527
|
+
if not self.keywords:
|
|
528
|
+
self.language = DEFAULT_LANGUAGE
|
|
529
|
+
self.keywords = i18n.languages[DEFAULT_LANGUAGE]
|
|
530
|
+
for alias in self.keywords[keyword]:
|
|
531
|
+
if line.startswith(alias + ":"):
|
|
532
|
+
return alias
|
|
533
|
+
return False
|
|
534
|
+
|
|
535
|
+
def parse_tags(self, line):
|
|
536
|
+
"""
|
|
537
|
+
Parse a line with one or more tags:
|
|
538
|
+
|
|
539
|
+
* A tag starts with the AT sign.
|
|
540
|
+
* A tag consists of one word without whitespace chars.
|
|
541
|
+
* Multiple tags are separated with whitespace chars
|
|
542
|
+
* End-of-line comment is stripped.
|
|
543
|
+
|
|
544
|
+
:param line: Line with one/more tags to process.
|
|
545
|
+
:raise ParserError: If syntax error is detected.
|
|
546
|
+
"""
|
|
547
|
+
assert line.startswith("@")
|
|
548
|
+
tags = []
|
|
549
|
+
for word in line.split():
|
|
550
|
+
if word.startswith("@"):
|
|
551
|
+
tags.append(model.Tag(word[1:], self.line))
|
|
552
|
+
elif word.startswith("#"):
|
|
553
|
+
break # -- COMMENT: Skip rest of line.
|
|
554
|
+
else:
|
|
555
|
+
# -- BAD-TAG: Abort here.
|
|
556
|
+
raise ParserError(u"tag: %s (line: %s)" % (word, line),
|
|
557
|
+
self.line, self.filename)
|
|
558
|
+
return tags
|
|
559
|
+
|
|
560
|
+
def parse_step(self, line):
|
|
561
|
+
for step_type in ("given", "when", "then", "and", "but"):
|
|
562
|
+
for kw in self.keywords[step_type]:
|
|
563
|
+
if kw.endswith("<"):
|
|
564
|
+
whitespace = ""
|
|
565
|
+
kw = kw[:-1]
|
|
566
|
+
else:
|
|
567
|
+
whitespace = " "
|
|
568
|
+
|
|
569
|
+
# try to match the keyword; also attempt a purely lowercase
|
|
570
|
+
# match if that'll work
|
|
571
|
+
if not (line.startswith(kw + whitespace)
|
|
572
|
+
or line.lower().startswith(kw.lower() + whitespace)):
|
|
573
|
+
continue
|
|
574
|
+
|
|
575
|
+
name = line[len(kw):].strip()
|
|
576
|
+
if step_type in ("and", "but"):
|
|
577
|
+
if not self.last_step:
|
|
578
|
+
raise ParserError(u"No previous step", self.line)
|
|
579
|
+
step_type = self.last_step
|
|
580
|
+
else:
|
|
581
|
+
self.last_step = step_type
|
|
582
|
+
step = model.Step(self.filename, self.line, kw, step_type,
|
|
583
|
+
name)
|
|
584
|
+
return step
|
|
585
|
+
return None
|
|
586
|
+
|
|
587
|
+
def parse_steps(self, text, filename=None):
|
|
588
|
+
"""
|
|
589
|
+
Parse support for execute_steps() functionality that supports step with:
|
|
590
|
+
* multiline text
|
|
591
|
+
* table
|
|
592
|
+
|
|
593
|
+
:param text: Text that contains 0..* steps
|
|
594
|
+
:return: List of parsed steps (as model.Step objects).
|
|
595
|
+
"""
|
|
596
|
+
assert isinstance(text, six.text_type)
|
|
597
|
+
if not self.language:
|
|
598
|
+
self.language = DEFAULT_LANGUAGE
|
|
599
|
+
self.reset()
|
|
600
|
+
self.filename = filename
|
|
601
|
+
self.statement = model.Scenario(filename, 0, u"scenario", u"")
|
|
602
|
+
self.state = "steps"
|
|
603
|
+
|
|
604
|
+
for line in text.split("\n"):
|
|
605
|
+
self.line += 1
|
|
606
|
+
if not line.strip() and self.state != "multiline":
|
|
607
|
+
# -- SKIP EMPTY LINES, except in multiline string args.
|
|
608
|
+
continue
|
|
609
|
+
self.action(line)
|
|
610
|
+
|
|
611
|
+
# -- FINALLY:
|
|
612
|
+
if self.table:
|
|
613
|
+
self.action_table("")
|
|
614
|
+
steps = self.statement.steps
|
|
615
|
+
return steps
|