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.
Files changed (418) hide show
  1. checksums.yaml +7 -0
  2. data/.cane +0 -0
  3. data/.gitignore +17 -0
  4. data/.tailor +4 -0
  5. data/.travis.yml +11 -0
  6. data/CHANGELOG.md +3 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +15 -0
  9. data/README.md +41 -0
  10. data/Rakefile +68 -0
  11. data/busser-behave.gemspec +30 -0
  12. data/features/plugin_install_command.feature +11 -0
  13. data/features/plugin_list_command.feature +8 -0
  14. data/features/support/env.rb +13 -0
  15. data/features/test_command.feature +31 -0
  16. data/lib/busser/behave/version.rb +26 -0
  17. data/lib/busser/runner_plugin/behave.rb +37 -0
  18. data/vendor/behave/CHANGES.rst +483 -0
  19. data/vendor/behave/LICENSE +23 -0
  20. data/vendor/behave/MANIFEST.in +37 -0
  21. data/vendor/behave/PROJECT_INFO.rst +21 -0
  22. data/vendor/behave/README.rst +112 -0
  23. data/vendor/behave/VERSION.txt +1 -0
  24. data/vendor/behave/behave.ini +22 -0
  25. data/vendor/behave/behave/__init__.py +30 -0
  26. data/vendor/behave/behave/__main__.py +187 -0
  27. data/vendor/behave/behave/_stepimport.py +185 -0
  28. data/vendor/behave/behave/_types.py +134 -0
  29. data/vendor/behave/behave/api/__init__.py +7 -0
  30. data/vendor/behave/behave/api/async_step.py +283 -0
  31. data/vendor/behave/behave/capture.py +227 -0
  32. data/vendor/behave/behave/compat/__init__.py +5 -0
  33. data/vendor/behave/behave/compat/collections.py +20 -0
  34. data/vendor/behave/behave/configuration.py +788 -0
  35. data/vendor/behave/behave/contrib/__init__.py +0 -0
  36. data/vendor/behave/behave/contrib/scenario_autoretry.py +73 -0
  37. data/vendor/behave/behave/formatter/__init__.py +12 -0
  38. data/vendor/behave/behave/formatter/_builtins.py +39 -0
  39. data/vendor/behave/behave/formatter/_registry.py +135 -0
  40. data/vendor/behave/behave/formatter/ansi_escapes.py +91 -0
  41. data/vendor/behave/behave/formatter/base.py +200 -0
  42. data/vendor/behave/behave/formatter/formatters.py +57 -0
  43. data/vendor/behave/behave/formatter/json.py +253 -0
  44. data/vendor/behave/behave/formatter/null.py +12 -0
  45. data/vendor/behave/behave/formatter/plain.py +158 -0
  46. data/vendor/behave/behave/formatter/pretty.py +351 -0
  47. data/vendor/behave/behave/formatter/progress.py +287 -0
  48. data/vendor/behave/behave/formatter/rerun.py +114 -0
  49. data/vendor/behave/behave/formatter/sphinx_steps.py +372 -0
  50. data/vendor/behave/behave/formatter/sphinx_util.py +118 -0
  51. data/vendor/behave/behave/formatter/steps.py +497 -0
  52. data/vendor/behave/behave/formatter/tags.py +178 -0
  53. data/vendor/behave/behave/i18n.py +614 -0
  54. data/vendor/behave/behave/importer.py +102 -0
  55. data/vendor/behave/behave/json_parser.py +264 -0
  56. data/vendor/behave/behave/log_capture.py +233 -0
  57. data/vendor/behave/behave/matchers.py +402 -0
  58. data/vendor/behave/behave/model.py +1737 -0
  59. data/vendor/behave/behave/model_core.py +416 -0
  60. data/vendor/behave/behave/model_describe.py +105 -0
  61. data/vendor/behave/behave/parser.py +615 -0
  62. data/vendor/behave/behave/reporter/__init__.py +0 -0
  63. data/vendor/behave/behave/reporter/base.py +45 -0
  64. data/vendor/behave/behave/reporter/junit.py +473 -0
  65. data/vendor/behave/behave/reporter/summary.py +94 -0
  66. data/vendor/behave/behave/runner.py +753 -0
  67. data/vendor/behave/behave/runner_util.py +417 -0
  68. data/vendor/behave/behave/step_registry.py +112 -0
  69. data/vendor/behave/behave/tag_expression.py +111 -0
  70. data/vendor/behave/behave/tag_matcher.py +465 -0
  71. data/vendor/behave/behave/textutil.py +137 -0
  72. data/vendor/behave/behave/userdata.py +130 -0
  73. data/vendor/behave/behave4cmd0/__all_steps__.py +12 -0
  74. data/vendor/behave/behave4cmd0/__init__.py +5 -0
  75. data/vendor/behave/behave4cmd0/__setup.py +11 -0
  76. data/vendor/behave/behave4cmd0/command_shell.py +216 -0
  77. data/vendor/behave/behave4cmd0/command_shell_proc.py +256 -0
  78. data/vendor/behave/behave4cmd0/command_steps.py +532 -0
  79. data/vendor/behave/behave4cmd0/command_util.py +147 -0
  80. data/vendor/behave/behave4cmd0/failing_steps.py +49 -0
  81. data/vendor/behave/behave4cmd0/log/__init__.py +1 -0
  82. data/vendor/behave/behave4cmd0/log/steps.py +395 -0
  83. data/vendor/behave/behave4cmd0/note_steps.py +29 -0
  84. data/vendor/behave/behave4cmd0/passing_steps.py +36 -0
  85. data/vendor/behave/behave4cmd0/pathutil.py +146 -0
  86. data/vendor/behave/behave4cmd0/setup_command_shell.py +24 -0
  87. data/vendor/behave/behave4cmd0/textutil.py +304 -0
  88. data/vendor/behave/bin/behave +44 -0
  89. data/vendor/behave/bin/behave.cmd +10 -0
  90. data/vendor/behave/bin/behave.junit_filter.py +85 -0
  91. data/vendor/behave/bin/behave.step_durations.py +163 -0
  92. data/vendor/behave/bin/behave2cucumber_json.py +63 -0
  93. data/vendor/behave/bin/behave_cmd.py +44 -0
  94. data/vendor/behave/bin/convert_i18n_yaml.py +77 -0
  95. data/vendor/behave/bin/explore_platform_encoding.py +24 -0
  96. data/vendor/behave/bin/i18n.yml +621 -0
  97. data/vendor/behave/bin/invoke +8 -0
  98. data/vendor/behave/bin/invoke.cmd +9 -0
  99. data/vendor/behave/bin/json.format.py +167 -0
  100. data/vendor/behave/bin/jsonschema_validate.py +122 -0
  101. data/vendor/behave/bin/make_localpi.py +279 -0
  102. data/vendor/behave/bin/project_bootstrap.sh +30 -0
  103. data/vendor/behave/bin/toxcmd.py +270 -0
  104. data/vendor/behave/bin/toxcmd3.py +270 -0
  105. data/vendor/behave/conftest.py +27 -0
  106. data/vendor/behave/docs/Makefile +154 -0
  107. data/vendor/behave/docs/_static/agogo.css +501 -0
  108. data/vendor/behave/docs/_static/behave_logo.png +0 -0
  109. data/vendor/behave/docs/_static/behave_logo1.png +0 -0
  110. data/vendor/behave/docs/_static/behave_logo2.png +0 -0
  111. data/vendor/behave/docs/_static/behave_logo3.png +0 -0
  112. data/vendor/behave/docs/_themes/LICENSE +45 -0
  113. data/vendor/behave/docs/_themes/kr/layout.html +17 -0
  114. data/vendor/behave/docs/_themes/kr/relations.html +19 -0
  115. data/vendor/behave/docs/_themes/kr/static/flasky.css_t +480 -0
  116. data/vendor/behave/docs/_themes/kr/static/small_flask.css +90 -0
  117. data/vendor/behave/docs/_themes/kr/theme.conf +7 -0
  118. data/vendor/behave/docs/_themes/kr_small/layout.html +22 -0
  119. data/vendor/behave/docs/_themes/kr_small/static/flasky.css_t +287 -0
  120. data/vendor/behave/docs/_themes/kr_small/theme.conf +10 -0
  121. data/vendor/behave/docs/api.rst +408 -0
  122. data/vendor/behave/docs/appendix.rst +19 -0
  123. data/vendor/behave/docs/behave.rst +640 -0
  124. data/vendor/behave/docs/behave.rst-template +86 -0
  125. data/vendor/behave/docs/behave_ecosystem.rst +81 -0
  126. data/vendor/behave/docs/comparison.rst +85 -0
  127. data/vendor/behave/docs/conf.py +293 -0
  128. data/vendor/behave/docs/context_attributes.rst +66 -0
  129. data/vendor/behave/docs/django.rst +192 -0
  130. data/vendor/behave/docs/formatters.rst +61 -0
  131. data/vendor/behave/docs/gherkin.rst +673 -0
  132. data/vendor/behave/docs/index.rst +57 -0
  133. data/vendor/behave/docs/install.rst +60 -0
  134. data/vendor/behave/docs/more_info.rst +184 -0
  135. data/vendor/behave/docs/new_and_noteworthy.rst +18 -0
  136. data/vendor/behave/docs/new_and_noteworthy_v1.2.4.rst +11 -0
  137. data/vendor/behave/docs/new_and_noteworthy_v1.2.5.rst +814 -0
  138. data/vendor/behave/docs/new_and_noteworthy_v1.2.6.rst +255 -0
  139. data/vendor/behave/docs/parse_builtin_types.rst +59 -0
  140. data/vendor/behave/docs/philosophy.rst +235 -0
  141. data/vendor/behave/docs/regular_expressions.rst +71 -0
  142. data/vendor/behave/docs/related.rst +14 -0
  143. data/vendor/behave/docs/test_domains.rst +62 -0
  144. data/vendor/behave/docs/tutorial.rst +636 -0
  145. data/vendor/behave/docs/update_behave_rst.py +100 -0
  146. data/vendor/behave/etc/json/behave.json-schema +172 -0
  147. data/vendor/behave/etc/junit.xml/behave_junit.xsd +103 -0
  148. data/vendor/behave/etc/junit.xml/junit-4.xsd +92 -0
  149. data/vendor/behave/examples/async_step/README.txt +8 -0
  150. data/vendor/behave/examples/async_step/behave.ini +14 -0
  151. data/vendor/behave/examples/async_step/features/async_dispatch.feature +8 -0
  152. data/vendor/behave/examples/async_step/features/async_run.feature +6 -0
  153. data/vendor/behave/examples/async_step/features/environment.py +28 -0
  154. data/vendor/behave/examples/async_step/features/steps/async_dispatch_steps.py +26 -0
  155. data/vendor/behave/examples/async_step/features/steps/async_steps34.py +10 -0
  156. data/vendor/behave/examples/async_step/features/steps/async_steps35.py +10 -0
  157. data/vendor/behave/examples/async_step/testrun_example.async_dispatch.txt +11 -0
  158. data/vendor/behave/examples/async_step/testrun_example.async_run.txt +9 -0
  159. data/vendor/behave/examples/env_vars/README.rst +26 -0
  160. data/vendor/behave/examples/env_vars/behave.ini +15 -0
  161. data/vendor/behave/examples/env_vars/behave_run.output_example.txt +12 -0
  162. data/vendor/behave/examples/env_vars/features/env_var.feature +6 -0
  163. data/vendor/behave/examples/env_vars/features/steps/env_var_steps.py +38 -0
  164. data/vendor/behave/features/README.txt +12 -0
  165. data/vendor/behave/features/background.feature +392 -0
  166. data/vendor/behave/features/capture_stderr.feature +172 -0
  167. data/vendor/behave/features/capture_stdout.feature +125 -0
  168. data/vendor/behave/features/cmdline.lang_list.feature +33 -0
  169. data/vendor/behave/features/configuration.default_paths.feature +116 -0
  170. data/vendor/behave/features/context.global_params.feature +35 -0
  171. data/vendor/behave/features/context.local_params.feature +17 -0
  172. data/vendor/behave/features/directory_layout.advanced.feature +147 -0
  173. data/vendor/behave/features/directory_layout.basic.feature +75 -0
  174. data/vendor/behave/features/directory_layout.basic2.feature +87 -0
  175. data/vendor/behave/features/environment.py +53 -0
  176. data/vendor/behave/features/exploratory_testing.with_table.feature +141 -0
  177. data/vendor/behave/features/feature.description.feature +0 -0
  178. data/vendor/behave/features/feature.exclude_from_run.feature +96 -0
  179. data/vendor/behave/features/formatter.help.feature +30 -0
  180. data/vendor/behave/features/formatter.json.feature +420 -0
  181. data/vendor/behave/features/formatter.progress3.feature +235 -0
  182. data/vendor/behave/features/formatter.rerun.feature +296 -0
  183. data/vendor/behave/features/formatter.steps.feature +181 -0
  184. data/vendor/behave/features/formatter.steps_catalog.feature +100 -0
  185. data/vendor/behave/features/formatter.steps_doc.feature +140 -0
  186. data/vendor/behave/features/formatter.steps_usage.feature +404 -0
  187. data/vendor/behave/features/formatter.tags.feature +134 -0
  188. data/vendor/behave/features/formatter.tags_location.feature +183 -0
  189. data/vendor/behave/features/formatter.user_defined.feature +196 -0
  190. data/vendor/behave/features/i18n.unicode_problems.feature +445 -0
  191. data/vendor/behave/features/logcapture.clear_handlers.feature +114 -0
  192. data/vendor/behave/features/logcapture.feature +188 -0
  193. data/vendor/behave/features/logcapture.filter.feature +130 -0
  194. data/vendor/behave/features/logging.no_capture.feature +99 -0
  195. data/vendor/behave/features/logging.setup_format.feature +157 -0
  196. data/vendor/behave/features/logging.setup_level.feature +168 -0
  197. data/vendor/behave/features/logging.setup_with_configfile.feature +137 -0
  198. data/vendor/behave/features/parser.background.sad_cases.feature +129 -0
  199. data/vendor/behave/features/parser.feature.sad_cases.feature +144 -0
  200. data/vendor/behave/features/runner.abort_by_user.feature +305 -0
  201. data/vendor/behave/features/runner.continue_after_failed_step.feature +136 -0
  202. data/vendor/behave/features/runner.default_format.feature +175 -0
  203. data/vendor/behave/features/runner.dry_run.feature +184 -0
  204. data/vendor/behave/features/runner.feature_listfile.feature +223 -0
  205. data/vendor/behave/features/runner.hook_errors.feature +382 -0
  206. data/vendor/behave/features/runner.multiple_formatters.feature +285 -0
  207. data/vendor/behave/features/runner.scenario_autoretry.feature +131 -0
  208. data/vendor/behave/features/runner.select_files_by_regexp.example.feature +71 -0
  209. data/vendor/behave/features/runner.select_files_by_regexp.feature +84 -0
  210. data/vendor/behave/features/runner.select_scenarios_by_file_location.feature +403 -0
  211. data/vendor/behave/features/runner.select_scenarios_by_name.feature +289 -0
  212. data/vendor/behave/features/runner.select_scenarios_by_tag.feature +225 -0
  213. data/vendor/behave/features/runner.stop_after_failure.feature +122 -0
  214. data/vendor/behave/features/runner.tag_logic.feature +67 -0
  215. data/vendor/behave/features/runner.unknown_formatter.feature +23 -0
  216. data/vendor/behave/features/runner.use_stage_implementations.feature +126 -0
  217. data/vendor/behave/features/scenario.description.feature +171 -0
  218. data/vendor/behave/features/scenario.exclude_from_run.feature +217 -0
  219. data/vendor/behave/features/scenario_outline.basics.feature +100 -0
  220. data/vendor/behave/features/scenario_outline.improved.feature +177 -0
  221. data/vendor/behave/features/scenario_outline.name_annotation.feature +157 -0
  222. data/vendor/behave/features/scenario_outline.parametrized.feature +401 -0
  223. data/vendor/behave/features/scenario_outline.tagged_examples.feature +118 -0
  224. data/vendor/behave/features/step.async_steps.feature +225 -0
  225. data/vendor/behave/features/step.duplicated_step.feature +106 -0
  226. data/vendor/behave/features/step.execute_steps.feature +59 -0
  227. data/vendor/behave/features/step.execute_steps.with_table.feature +65 -0
  228. data/vendor/behave/features/step.import_other_step_module.feature +103 -0
  229. data/vendor/behave/features/step.pending_steps.feature +128 -0
  230. data/vendor/behave/features/step.undefined_steps.feature +307 -0
  231. data/vendor/behave/features/step.use_step_library.feature +44 -0
  232. data/vendor/behave/features/step_dialect.generic_steps.feature +189 -0
  233. data/vendor/behave/features/step_dialect.given_when_then.feature +89 -0
  234. data/vendor/behave/features/step_param.builtin_types.with_float.feature +239 -0
  235. data/vendor/behave/features/step_param.builtin_types.with_integer.feature +305 -0
  236. data/vendor/behave/features/step_param.custom_types.feature +134 -0
  237. data/vendor/behave/features/steps/behave_active_tags_steps.py +86 -0
  238. data/vendor/behave/features/steps/behave_context_steps.py +67 -0
  239. data/vendor/behave/features/steps/behave_model_tag_logic_steps.py +105 -0
  240. data/vendor/behave/features/steps/behave_model_util.py +105 -0
  241. data/vendor/behave/features/steps/behave_select_files_steps.py +83 -0
  242. data/vendor/behave/features/steps/behave_tag_expression_steps.py +166 -0
  243. data/vendor/behave/features/steps/behave_undefined_steps.py +101 -0
  244. data/vendor/behave/features/steps/use_steplib_behave4cmd.py +12 -0
  245. data/vendor/behave/features/summary.undefined_steps.feature +114 -0
  246. data/vendor/behave/features/tags.active_tags.feature +385 -0
  247. data/vendor/behave/features/tags.default_tags.feature +104 -0
  248. data/vendor/behave/features/tags.tag_expression.feature +105 -0
  249. data/vendor/behave/features/userdata.feature +331 -0
  250. data/vendor/behave/invoke.yaml +21 -0
  251. data/vendor/behave/issue.features/README.txt +17 -0
  252. data/vendor/behave/issue.features/environment.py +97 -0
  253. data/vendor/behave/issue.features/issue0030.feature +21 -0
  254. data/vendor/behave/issue.features/issue0031.feature +16 -0
  255. data/vendor/behave/issue.features/issue0032.feature +28 -0
  256. data/vendor/behave/issue.features/issue0035.feature +74 -0
  257. data/vendor/behave/issue.features/issue0040.feature +154 -0
  258. data/vendor/behave/issue.features/issue0041.feature +135 -0
  259. data/vendor/behave/issue.features/issue0042.feature +230 -0
  260. data/vendor/behave/issue.features/issue0044.feature +51 -0
  261. data/vendor/behave/issue.features/issue0046.feature +77 -0
  262. data/vendor/behave/issue.features/issue0052.feature +66 -0
  263. data/vendor/behave/issue.features/issue0059.feature +29 -0
  264. data/vendor/behave/issue.features/issue0063.feature +102 -0
  265. data/vendor/behave/issue.features/issue0064.feature +97 -0
  266. data/vendor/behave/issue.features/issue0065.feature +18 -0
  267. data/vendor/behave/issue.features/issue0066.feature +80 -0
  268. data/vendor/behave/issue.features/issue0067.feature +90 -0
  269. data/vendor/behave/issue.features/issue0069.feature +64 -0
  270. data/vendor/behave/issue.features/issue0072.feature +32 -0
  271. data/vendor/behave/issue.features/issue0073.feature +228 -0
  272. data/vendor/behave/issue.features/issue0075.feature +18 -0
  273. data/vendor/behave/issue.features/issue0077.feature +89 -0
  274. data/vendor/behave/issue.features/issue0080.feature +49 -0
  275. data/vendor/behave/issue.features/issue0081.feature +138 -0
  276. data/vendor/behave/issue.features/issue0083.feature +69 -0
  277. data/vendor/behave/issue.features/issue0084.feature +69 -0
  278. data/vendor/behave/issue.features/issue0085.feature +119 -0
  279. data/vendor/behave/issue.features/issue0092.feature +66 -0
  280. data/vendor/behave/issue.features/issue0096.feature +173 -0
  281. data/vendor/behave/issue.features/issue0099.feature +130 -0
  282. data/vendor/behave/issue.features/issue0109.feature +60 -0
  283. data/vendor/behave/issue.features/issue0111.feature +53 -0
  284. data/vendor/behave/issue.features/issue0112.feature +64 -0
  285. data/vendor/behave/issue.features/issue0114.feature +118 -0
  286. data/vendor/behave/issue.features/issue0116.feature +71 -0
  287. data/vendor/behave/issue.features/issue0125.feature +49 -0
  288. data/vendor/behave/issue.features/issue0127.feature +64 -0
  289. data/vendor/behave/issue.features/issue0139.feature +67 -0
  290. data/vendor/behave/issue.features/issue0142.feature +37 -0
  291. data/vendor/behave/issue.features/issue0143.feature +54 -0
  292. data/vendor/behave/issue.features/issue0145.feature +63 -0
  293. data/vendor/behave/issue.features/issue0148.feature +105 -0
  294. data/vendor/behave/issue.features/issue0152.feature +52 -0
  295. data/vendor/behave/issue.features/issue0159.feature +74 -0
  296. data/vendor/behave/issue.features/issue0162.feature +86 -0
  297. data/vendor/behave/issue.features/issue0171.feature +16 -0
  298. data/vendor/behave/issue.features/issue0172.feature +51 -0
  299. data/vendor/behave/issue.features/issue0175.feature +91 -0
  300. data/vendor/behave/issue.features/issue0177.feature +40 -0
  301. data/vendor/behave/issue.features/issue0181.feature +36 -0
  302. data/vendor/behave/issue.features/issue0184.feature +144 -0
  303. data/vendor/behave/issue.features/issue0186.feature +12 -0
  304. data/vendor/behave/issue.features/issue0188.feature +60 -0
  305. data/vendor/behave/issue.features/issue0191.feature +178 -0
  306. data/vendor/behave/issue.features/issue0194.feature +215 -0
  307. data/vendor/behave/issue.features/issue0197.feature +11 -0
  308. data/vendor/behave/issue.features/issue0216.feature +129 -0
  309. data/vendor/behave/issue.features/issue0226.feature +51 -0
  310. data/vendor/behave/issue.features/issue0228.feature +41 -0
  311. data/vendor/behave/issue.features/issue0230.feature +46 -0
  312. data/vendor/behave/issue.features/issue0231.feature +77 -0
  313. data/vendor/behave/issue.features/issue0238.feature +52 -0
  314. data/vendor/behave/issue.features/issue0251.feature +15 -0
  315. data/vendor/behave/issue.features/issue0280.feature +118 -0
  316. data/vendor/behave/issue.features/issue0288.feature +95 -0
  317. data/vendor/behave/issue.features/issue0300.feature +49 -0
  318. data/vendor/behave/issue.features/issue0302.feature +91 -0
  319. data/vendor/behave/issue.features/issue0309.feature +52 -0
  320. data/vendor/behave/issue.features/issue0330.feature +124 -0
  321. data/vendor/behave/issue.features/issue0349.feature +9 -0
  322. data/vendor/behave/issue.features/issue0361.feature +79 -0
  323. data/vendor/behave/issue.features/issue0383.feature +76 -0
  324. data/vendor/behave/issue.features/issue0384.feature +103 -0
  325. data/vendor/behave/issue.features/issue0385.feature +109 -0
  326. data/vendor/behave/issue.features/issue0424.feature +66 -0
  327. data/vendor/behave/issue.features/issue0446.feature +116 -0
  328. data/vendor/behave/issue.features/issue0449.feature +42 -0
  329. data/vendor/behave/issue.features/issue0453.feature +42 -0
  330. data/vendor/behave/issue.features/issue0457.feature +65 -0
  331. data/vendor/behave/issue.features/issue0462.feature +38 -0
  332. data/vendor/behave/issue.features/issue0476.feature +39 -0
  333. data/vendor/behave/issue.features/issue0487.feature +92 -0
  334. data/vendor/behave/issue.features/issue0506.feature +77 -0
  335. data/vendor/behave/issue.features/issue0510.feature +51 -0
  336. data/vendor/behave/issue.features/requirements.txt +12 -0
  337. data/vendor/behave/issue.features/steps/ansi_steps.py +20 -0
  338. data/vendor/behave/issue.features/steps/behave_hooks_steps.py +10 -0
  339. data/vendor/behave/issue.features/steps/use_steplib_behave4cmd.py +13 -0
  340. data/vendor/behave/more.features/formatter.json.validate_output.feature +37 -0
  341. data/vendor/behave/more.features/steps/tutorial_steps.py +16 -0
  342. data/vendor/behave/more.features/steps/use_steplib_behave4cmd.py +7 -0
  343. data/vendor/behave/more.features/tutorial.feature +6 -0
  344. data/vendor/behave/py.requirements/README.txt +5 -0
  345. data/vendor/behave/py.requirements/all.txt +16 -0
  346. data/vendor/behave/py.requirements/basic.txt +21 -0
  347. data/vendor/behave/py.requirements/develop.txt +28 -0
  348. data/vendor/behave/py.requirements/docs.txt +6 -0
  349. data/vendor/behave/py.requirements/json.txt +7 -0
  350. data/vendor/behave/py.requirements/more_py26.txt +8 -0
  351. data/vendor/behave/py.requirements/testing.txt +10 -0
  352. data/vendor/behave/pytest.ini +24 -0
  353. data/vendor/behave/setup.cfg +29 -0
  354. data/vendor/behave/setup.py +118 -0
  355. data/vendor/behave/setuptools_behave.py +130 -0
  356. data/vendor/behave/tasks/__behave.py +45 -0
  357. data/vendor/behave/tasks/__init__.py +55 -0
  358. data/vendor/behave/tasks/__main__.py +70 -0
  359. data/vendor/behave/tasks/_setup.py +135 -0
  360. data/vendor/behave/tasks/_vendor/README.rst +35 -0
  361. data/vendor/behave/tasks/_vendor/invoke.zip +0 -0
  362. data/vendor/behave/tasks/_vendor/path.py +1725 -0
  363. data/vendor/behave/tasks/_vendor/pathlib.py +1280 -0
  364. data/vendor/behave/tasks/_vendor/six.py +868 -0
  365. data/vendor/behave/tasks/clean.py +246 -0
  366. data/vendor/behave/tasks/docs.py +97 -0
  367. data/vendor/behave/tasks/requirements.txt +17 -0
  368. data/vendor/behave/tasks/test.py +192 -0
  369. data/vendor/behave/test/__init__.py +0 -0
  370. data/vendor/behave/test/_importer_candidate.py +3 -0
  371. data/vendor/behave/test/reporters/__init__.py +0 -0
  372. data/vendor/behave/test/reporters/test_summary.py +240 -0
  373. data/vendor/behave/test/test_ansi_escapes.py +73 -0
  374. data/vendor/behave/test/test_configuration.py +172 -0
  375. data/vendor/behave/test/test_formatter.py +265 -0
  376. data/vendor/behave/test/test_formatter_progress.py +39 -0
  377. data/vendor/behave/test/test_formatter_rerun.py +97 -0
  378. data/vendor/behave/test/test_formatter_tags.py +57 -0
  379. data/vendor/behave/test/test_importer.py +151 -0
  380. data/vendor/behave/test/test_log_capture.py +29 -0
  381. data/vendor/behave/test/test_matchers.py +236 -0
  382. data/vendor/behave/test/test_model.py +871 -0
  383. data/vendor/behave/test/test_parser.py +1590 -0
  384. data/vendor/behave/test/test_runner.py +1074 -0
  385. data/vendor/behave/test/test_step_registry.py +96 -0
  386. data/vendor/behave/test/test_tag_expression.py +506 -0
  387. data/vendor/behave/test/test_tag_expression2.py +462 -0
  388. data/vendor/behave/test/test_tag_matcher.py +729 -0
  389. data/vendor/behave/test/test_userdata.py +184 -0
  390. data/vendor/behave/tests/README.txt +12 -0
  391. data/vendor/behave/tests/__init__.py +0 -0
  392. data/vendor/behave/tests/api/__ONLY_PY34_or_newer.txt +0 -0
  393. data/vendor/behave/tests/api/__init__.py +0 -0
  394. data/vendor/behave/tests/api/_test_async_step34.py +130 -0
  395. data/vendor/behave/tests/api/_test_async_step35.py +75 -0
  396. data/vendor/behave/tests/api/test_async_step.py +18 -0
  397. data/vendor/behave/tests/api/testing_support.py +94 -0
  398. data/vendor/behave/tests/api/testing_support_async.py +21 -0
  399. data/vendor/behave/tests/issues/test_issue0336.py +66 -0
  400. data/vendor/behave/tests/issues/test_issue0449.py +55 -0
  401. data/vendor/behave/tests/issues/test_issue0453.py +62 -0
  402. data/vendor/behave/tests/issues/test_issue0458.py +54 -0
  403. data/vendor/behave/tests/issues/test_issue0495.py +65 -0
  404. data/vendor/behave/tests/unit/__init__.py +0 -0
  405. data/vendor/behave/tests/unit/test_behave4cmd_command_shell_proc.py +135 -0
  406. data/vendor/behave/tests/unit/test_capture.py +280 -0
  407. data/vendor/behave/tests/unit/test_model_core.py +56 -0
  408. data/vendor/behave/tests/unit/test_textutil.py +267 -0
  409. data/vendor/behave/tools/test-features/background.feature +9 -0
  410. data/vendor/behave/tools/test-features/environment.py +8 -0
  411. data/vendor/behave/tools/test-features/french.feature +11 -0
  412. data/vendor/behave/tools/test-features/outline.feature +39 -0
  413. data/vendor/behave/tools/test-features/parse.feature +10 -0
  414. data/vendor/behave/tools/test-features/step-data.feature +60 -0
  415. data/vendor/behave/tools/test-features/steps/steps.py +120 -0
  416. data/vendor/behave/tools/test-features/tags.feature +18 -0
  417. data/vendor/behave/tox.ini +159 -0
  418. 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