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,256 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ This module provides pre-/post-processors for the mod:`behave4cmd0.command_shell`.
5
+ """
6
+
7
+ from __future__ import absolute_import, print_function
8
+ import re
9
+ import sys
10
+ from six import string_types
11
+
12
+
13
+ # -----------------------------------------------------------------------------
14
+ # UTILITY:
15
+ # -----------------------------------------------------------------------------
16
+ def posixpath_normpath(filename):
17
+ if not filename:
18
+ return filename
19
+ return filename.replace("\\", "/").replace("//", "/")
20
+
21
+
22
+ # -----------------------------------------------------------------------------
23
+ # LINE PROCESSORS:
24
+ # -----------------------------------------------------------------------------
25
+ class LineProcessor(object):
26
+ """Function-like object that may perform text-line transformations."""
27
+ def __init__(self, marker=None):
28
+ self.marker = marker
29
+
30
+ def reset(self):
31
+ pass
32
+
33
+ def __call__(self, text):
34
+ return text
35
+
36
+
37
+ class TracebackLineNormalizer(LineProcessor):
38
+ """Line processor that tries to normalize path lines in a traceback dump."""
39
+ marker = "Traceback (most recent call last):"
40
+ file_pattern = re.compile(r'\s\s+File "(?P<path>.*)", line .*')
41
+
42
+ def __init__(self):
43
+ super(TracebackLineNormalizer, self).__init__(self.marker)
44
+ self.traceback_section = False
45
+
46
+ def reset(self):
47
+ self.traceback_section = False
48
+
49
+ def __call__(self, line):
50
+ """Process a line and optionally transform it.
51
+
52
+ :param line: line to process (as text)
53
+ :return: Same line or transformed/normalized line (as text).
54
+ """
55
+ marker = self.marker
56
+ stripped_line = line.strip()
57
+ if marker == stripped_line:
58
+ assert not self.traceback_section
59
+ self.traceback_section = True
60
+ # print("XXX: TRACEBACK-START")
61
+ elif self.traceback_section:
62
+ matched = self.file_pattern.match(line)
63
+ if matched:
64
+ # matched_range = matched.regs[1]
65
+ filename = matched.groups()[0]
66
+ new_filename = posixpath_normpath(filename)
67
+ if new_filename != filename:
68
+ # print("XXX: %r => %r" % (filename, new_filename))
69
+ line = line.replace(filename, new_filename)
70
+ elif not stripped_line or line[0].isalpha():
71
+ # -- DETECTED TRCAEBACK-END: exception-description
72
+ # print("XXX: TRACEBACK-END")
73
+ self.traceback_section = False
74
+ return line
75
+
76
+
77
+ class ExceptionWithPathNormalizer(LineProcessor):
78
+ """Normalize filename path in Exception line (for Windows)."""
79
+ # http://myregexp.com/examples.html
80
+ # Windows File Name Regexp
81
+ # (?i) ^ (?! ^ (PRN | AUX | CLOCK\$ | NUL | CON | COM\d | LPT\d |\..* )(\..+)?$)
82
+ # [ ^\\\./:\ * \?\"<>\|][^\\/:\*\?\"<>\|]{0,254}$
83
+ problematic_path_patterns = [
84
+ 'ConfigError: No steps directory in "(?P<path>.*)"',
85
+ 'ParserError: Failed to parse "(?P<path>.*)"',
86
+ "Error: [Errno 2] No such file or directory: '(?P<path>.*)'",
87
+ ]
88
+
89
+ def __init__(self, pattern, marker_text=None):
90
+ super(ExceptionWithPathNormalizer, self).__init__(marker_text)
91
+ self.pattern = re.compile(pattern, re.UNICODE)
92
+ self.marker = marker_text
93
+
94
+ def __call__(self, line):
95
+ matched = self.pattern.search(line)
96
+ if matched:
97
+ # -- ONLY: One pattern per line should match.
98
+ filename = matched.groupdict()["path"]
99
+ new_filename = posixpath_normpath(filename)
100
+ if new_filename != filename:
101
+ line = line.replace(filename, new_filename)
102
+ return line
103
+
104
+
105
+ # -----------------------------------------------------------------------------
106
+ # COMMAND OUTPUT PROCESSORS:
107
+ # -----------------------------------------------------------------------------
108
+ class CommandPostProcessor(object):
109
+ """Syntactic sugar to mark a command post-processor."""
110
+
111
+
112
+ class CommandOutputProcessor(CommandPostProcessor):
113
+ """Abstract base class functionality for a CommandPostProcessor that
114
+ post-processes the output of a command.
115
+ """
116
+ enabled = True
117
+ output_parts = ("stderr", "stdout")
118
+
119
+ def __init__(self, enabled=None, output_parts=None):
120
+ if enabled is None:
121
+ # -- AUTO-DETECT: Enabled on Windows platform
122
+ enabled = self.__class__.enabled
123
+ if output_parts is None:
124
+ output_parts = self.__class__.output_parts
125
+ self.enabled = enabled
126
+ self.output_parts = output_parts
127
+
128
+ def matches_output(self, text):
129
+ """Abstract method that should be overwritten."""
130
+ # pylint: disable=no-self-use, unused-argument
131
+ return False
132
+
133
+ def process_output(self, text): # pylint: disable=no-self-use
134
+ """Abstract method that should be overwritten."""
135
+ changed = False
136
+ return changed, text
137
+
138
+ def __call__(self, command_result):
139
+ """Core functionality of command output processor.
140
+
141
+ :param command_result: As value object w/ command execution details.
142
+ :return: Command result
143
+ """
144
+ if not self.enabled:
145
+ return command_result
146
+
147
+ changes = 0
148
+ for output_name in self.output_parts:
149
+ output = getattr(command_result, output_name)
150
+ if output and self.matches_output(output):
151
+ changed, new_output = self.process_output(output)
152
+ if changed:
153
+ changes += 1
154
+ setattr(command_result, output_name, new_output)
155
+
156
+ if changes:
157
+ # -- RESET: Composite output
158
+ # pylint: disable=protected-access
159
+ command_result._output = None
160
+ return command_result
161
+
162
+
163
+ class LineCommandOutputProcessor(CommandOutputProcessor):
164
+ """Provides functionality to process text in line-oriented way by using
165
+ a number of line processors. The line processors perform the actual work
166
+ for transforming/normalizing the text.
167
+ """
168
+ enabled = True
169
+ line_processors = [TracebackLineNormalizer()]
170
+
171
+ def __init__(self, line_processors=None):
172
+ if line_processors is None:
173
+ line_processors = self.__class__.line_processors
174
+ super(LineCommandOutputProcessor, self).__init__(self.enabled)
175
+ self.line_processors = line_processors
176
+ self.markers = [p.marker for p in self.line_processors if p.marker]
177
+
178
+ def matches_output(self, text):
179
+ """Indicates it text contains sections of interest.
180
+ :param text: Text to inspect (as string).
181
+ :return: True, if text contains Traceback sections. False, otherwise.
182
+ """
183
+ if self.markers:
184
+ for marker in self.markers:
185
+ if marker in text:
186
+ return True
187
+ # -- OTHERWISE:
188
+ return False
189
+
190
+ def process_output(self, text):
191
+ """Normalizes multi-line text by applying the line processors.
192
+
193
+ :param text: Text to process (as string).
194
+ :return: Tuple (changed : bool, new_text : string)
195
+ """
196
+ new_lines = []
197
+ changed = False
198
+ for line_processor in self.line_processors:
199
+ line_processor.reset()
200
+
201
+ for line in text.splitlines():
202
+ # -- LINE PROCESSING PIPELINE:
203
+ original_line = line
204
+ for line_processor in self.line_processors:
205
+ line = line_processor(line)
206
+
207
+ if line != original_line:
208
+ changed = True
209
+ new_lines.append(line)
210
+
211
+ if changed:
212
+ text = "\n".join(new_lines) + "\n"
213
+ return changed, text
214
+
215
+ class TextProcessor(CommandOutputProcessor):
216
+ """Provides an adapter that uses an :class:`CommandOutputProcessor`
217
+ as text processor (normalizer).
218
+ """
219
+
220
+ def __init__(self, command_output_processor):
221
+ self.command_output_processor = command_output_processor
222
+ self.enabled = self.command_output_processor.enabled
223
+ self.output_parts = self.command_output_processor.output_parts
224
+
225
+ def process_output(self, text):
226
+ return self.command_output_processor.process_output(text)
227
+
228
+ def __call__(self, command_result):
229
+ if isinstance(command_result, string_types):
230
+ text = command_result
231
+ return self.command_output_processor.process_output(text)[1]
232
+ else:
233
+ return self.command_output_processor(command_result)
234
+
235
+
236
+ class BehaveWinCommandOutputProcessor(LineCommandOutputProcessor):
237
+ """Command output post-processor for :mod:`behave` on Windows platform.
238
+ Mostly, normalizes windows paths in output and exceptions to conform to
239
+ POSIX path conventions.
240
+ """
241
+ enabled = sys.platform.startswith("win") or True
242
+ line_processors = [
243
+ TracebackLineNormalizer(),
244
+ ExceptionWithPathNormalizer(
245
+ "ConfigError: No steps directory in '(?P<path>.*)'",
246
+ "ConfigError: No steps directory in"),
247
+ ExceptionWithPathNormalizer(
248
+ 'ParserError: Failed to parse "(?P<path>.*)"',
249
+ "ParserError: Failed to parse"),
250
+ ExceptionWithPathNormalizer(
251
+ "No such file or directory: '(?P<path>.*)'",
252
+ "[Errno 2] No such file or directory:"), # IOError
253
+ ExceptionWithPathNormalizer(
254
+ '^\s*File "(?P<path>.*)", line \d+, in ',
255
+ 'File "'),
256
+ ]
@@ -0,0 +1,532 @@
1
+ # -*- coding -*-
2
+ """
3
+ Provides step definitions to:
4
+
5
+ * run commands, like behave
6
+ * create textual files within a working directory
7
+
8
+ TODO:
9
+ matcher that ignores empty lines and whitespace and has contains comparison
10
+ """
11
+
12
+ from __future__ import absolute_import, print_function
13
+ from behave import given, when, then, step, matchers
14
+ from behave4cmd0 import command_shell, command_util, pathutil, textutil
15
+ from behave4cmd0.pathutil import posixpath_normpath
16
+ from behave4cmd0.command_shell_proc import \
17
+ TextProcessor, BehaveWinCommandOutputProcessor
18
+ import contextlib
19
+ import difflib
20
+ import os
21
+ import shutil
22
+ from hamcrest import assert_that, equal_to, is_not, contains_string
23
+
24
+ # -----------------------------------------------------------------------------
25
+ # INIT:
26
+ # -----------------------------------------------------------------------------
27
+ matchers.register_type(int=int)
28
+ DEBUG = False
29
+ file_contents_normalizer = None
30
+ if BehaveWinCommandOutputProcessor.enabled:
31
+ file_contents_normalizer = TextProcessor(BehaveWinCommandOutputProcessor())
32
+
33
+
34
+ # -----------------------------------------------------------------------------
35
+ # UTILITIES:
36
+ # -----------------------------------------------------------------------------
37
+ @contextlib.contextmanager
38
+ def on_assert_failed_print_details(actual, expected):
39
+ """
40
+ Print text details in case of assertation failed errors.
41
+
42
+ .. sourcecode:: python
43
+
44
+ with on_assert_failed_print_details(actual_text, expected_text):
45
+ assert actual == expected
46
+ """
47
+ try:
48
+ yield
49
+ except AssertionError:
50
+ # diff = difflib.unified_diff(expected.splitlines(), actual.splitlines(),
51
+ # "expected", "actual")
52
+ diff = difflib.ndiff(expected.splitlines(), actual.splitlines())
53
+ diff_text = u"\n".join(diff)
54
+ print(u"DIFF (+ ACTUAL, - EXPECTED):\n{0}\n".format(diff_text))
55
+ if DEBUG:
56
+ print(u"expected:\n{0}\n".format(expected))
57
+ print(u"actual:\n{0}\n".format(actual))
58
+ raise
59
+
60
+ @contextlib.contextmanager
61
+ def on_error_print_details(actual, expected):
62
+ """
63
+ Print text details in case of assertation failed errors.
64
+
65
+ .. sourcecode:: python
66
+
67
+ with on_error_print_details(actual_text, expected_text):
68
+ ... # Do something
69
+ """
70
+ try:
71
+ yield
72
+ except Exception:
73
+ diff = difflib.ndiff(expected.splitlines(), actual.splitlines())
74
+ diff_text = u"\n".join(diff)
75
+ print(u"DIFF (+ ACTUAL, - EXPECTED):\n{0}\n".format(diff_text))
76
+ if DEBUG:
77
+ print(u"expected:\n{0}\n".format(expected))
78
+ print(u"actual:\n{0}".format(actual))
79
+ raise
80
+
81
+ # -----------------------------------------------------------------------------
82
+ # STEPS: WORKING DIR
83
+ # -----------------------------------------------------------------------------
84
+ @given(u'a new working directory')
85
+ def step_a_new_working_directory(context):
86
+ """Creates a new, empty working directory."""
87
+ command_util.ensure_context_attribute_exists(context, "workdir", None)
88
+ # MAYBE: command_util.ensure_workdir_not_exists(context)
89
+ command_util.ensure_workdir_exists(context)
90
+ # OOPS:
91
+ shutil.rmtree(context.workdir, ignore_errors=True)
92
+ command_util.ensure_workdir_exists(context)
93
+
94
+ @given(u'I use the current directory as working directory')
95
+ def step_use_curdir_as_working_directory(context):
96
+ """
97
+ Uses the current directory as working directory
98
+ """
99
+ context.workdir = os.path.abspath(".")
100
+ command_util.ensure_workdir_exists(context)
101
+
102
+ # -----------------------------------------------------------------------------
103
+ # STEPS: Create files with contents
104
+ # -----------------------------------------------------------------------------
105
+ @given(u'a file named "{filename}" and encoding="{encoding}" with')
106
+ def step_a_file_named_filename_and_encoding_with(context, filename, encoding):
107
+ """Creates a textual file with the content provided as docstring."""
108
+ __encoding_is_valid = True
109
+ assert context.text is not None, "ENSURE: multiline text is provided."
110
+ assert not os.path.isabs(filename)
111
+ assert __encoding_is_valid
112
+ command_util.ensure_workdir_exists(context)
113
+ filename2 = os.path.join(context.workdir, filename)
114
+ pathutil.create_textfile_with_contents(filename2, context.text, encoding)
115
+
116
+
117
+ @given(u'a file named "{filename}" with')
118
+ def step_a_file_named_filename_with(context, filename):
119
+ """Creates a textual file with the content provided as docstring."""
120
+ step_a_file_named_filename_and_encoding_with(context, filename, "UTF-8")
121
+
122
+ # -- SPECIAL CASE: For usage with behave steps.
123
+ if filename.endswith(".feature"):
124
+ command_util.ensure_context_attribute_exists(context, "features", [])
125
+ context.features.append(filename)
126
+
127
+
128
+ @given(u'an empty file named "{filename}"')
129
+ def step_an_empty_file_named_filename(context, filename):
130
+ """
131
+ Creates an empty file.
132
+ """
133
+ assert not os.path.isabs(filename)
134
+ command_util.ensure_workdir_exists(context)
135
+ filename2 = os.path.join(context.workdir, filename)
136
+ pathutil.create_textfile_with_contents(filename2, "")
137
+
138
+
139
+ # -----------------------------------------------------------------------------
140
+ # STEPS: Run commands
141
+ # -----------------------------------------------------------------------------
142
+ @when(u'I run "{command}"')
143
+ @when(u'I run `{command}`')
144
+ def step_i_run_command(context, command):
145
+ """
146
+ Run a command as subprocess, collect its output and returncode.
147
+ """
148
+ command_util.ensure_workdir_exists(context)
149
+ context.command_result = command_shell.run(command, cwd=context.workdir)
150
+ command_util.workdir_save_coverage_files(context.workdir)
151
+ if False and DEBUG:
152
+ print(u"run_command: {0}".format(command))
153
+ print(u"run_command.output {0}".format(context.command_result.output))
154
+
155
+ @when(u'I successfully run "{command}"')
156
+ @when(u'I successfully run `{command}`')
157
+ def step_i_successfully_run_command(context, command):
158
+ step_i_run_command(context, command)
159
+ step_it_should_pass(context)
160
+
161
+ @then(u'it should fail with result "{result:int}"')
162
+ def step_it_should_fail_with_result(context, result):
163
+ assert_that(context.command_result.returncode, equal_to(result))
164
+ assert_that(result, is_not(equal_to(0)))
165
+
166
+ @then(u'the command should fail with returncode="{result:int}"')
167
+ def step_it_should_fail_with_returncode(context, result):
168
+ assert_that(context.command_result.returncode, equal_to(result))
169
+ assert_that(result, is_not(equal_to(0)))
170
+
171
+ @then(u'the command returncode is "{result:int}"')
172
+ def step_the_command_returncode_is(context, result):
173
+ assert_that(context.command_result.returncode, equal_to(result))
174
+
175
+ @then(u'the command returncode is non-zero')
176
+ def step_the_command_returncode_is_nonzero(context):
177
+ assert_that(context.command_result.returncode, is_not(equal_to(0)))
178
+
179
+ @then(u'it should pass')
180
+ def step_it_should_pass(context):
181
+ assert_that(context.command_result.returncode, equal_to(0),
182
+ context.command_result.output)
183
+
184
+ @then(u'it should fail')
185
+ def step_it_should_fail(context):
186
+ assert_that(context.command_result.returncode, is_not(equal_to(0)),
187
+ context.command_result.output)
188
+
189
+ @then(u'it should pass with')
190
+ def step_it_should_pass_with(context):
191
+ '''
192
+ EXAMPLE:
193
+ ...
194
+ when I run "behave ..."
195
+ then it should pass with:
196
+ """
197
+ TEXT
198
+ """
199
+ '''
200
+ assert context.text is not None, "ENSURE: multiline text is provided."
201
+ step_command_output_should_contain(context)
202
+ assert_that(context.command_result.returncode, equal_to(0),
203
+ context.command_result.output)
204
+
205
+
206
+ @then(u'it should fail with')
207
+ def step_it_should_fail_with(context):
208
+ '''
209
+ EXAMPLE:
210
+ ...
211
+ when I run "behave ..."
212
+ then it should fail with:
213
+ """
214
+ TEXT
215
+ """
216
+ '''
217
+ assert context.text is not None, "ENSURE: multiline text is provided."
218
+ step_command_output_should_contain(context)
219
+ assert_that(context.command_result.returncode, is_not(equal_to(0)))
220
+
221
+
222
+ # -----------------------------------------------------------------------------
223
+ # STEPS FOR: Output Comparison
224
+ # -----------------------------------------------------------------------------
225
+ @then(u'the command output should contain "{text}"')
226
+ def step_command_output_should_contain_text(context, text):
227
+ '''
228
+ EXAMPLE:
229
+ ...
230
+ Then the command output should contain "TEXT"
231
+ '''
232
+ expected_text = text
233
+ if "{__WORKDIR__}" in expected_text or "{__CWD__}" in expected_text:
234
+ expected_text = textutil.template_substitute(text,
235
+ __WORKDIR__ = posixpath_normpath(context.workdir),
236
+ __CWD__ = posixpath_normpath(os.getcwd())
237
+ )
238
+ actual_output = context.command_result.output
239
+ with on_assert_failed_print_details(actual_output, expected_text):
240
+ textutil.assert_normtext_should_contain(actual_output, expected_text)
241
+
242
+
243
+ @then(u'the command output should not contain "{text}"')
244
+ def step_command_output_should_not_contain_text(context, text):
245
+ '''
246
+ EXAMPLE:
247
+ ...
248
+ then the command output should not contain "TEXT"
249
+ '''
250
+ expected_text = text
251
+ if "{__WORKDIR__}" in text or "{__CWD__}" in text:
252
+ expected_text = textutil.template_substitute(text,
253
+ __WORKDIR__ = posixpath_normpath(context.workdir),
254
+ __CWD__ = posixpath_normpath(os.getcwd())
255
+ )
256
+ actual_output = context.command_result.output
257
+ with on_assert_failed_print_details(actual_output, expected_text):
258
+ textutil.assert_normtext_should_not_contain(actual_output, expected_text)
259
+
260
+
261
+ @then(u'the command output should contain "{text}" {count:d} times')
262
+ def step_command_output_should_contain_text_multiple_times(context, text, count):
263
+ '''
264
+ EXAMPLE:
265
+ ...
266
+ Then the command output should contain "TEXT" 3 times
267
+ '''
268
+ assert count >= 0
269
+ expected_text = text
270
+ if "{__WORKDIR__}" in expected_text or "{__CWD__}" in expected_text:
271
+ expected_text = textutil.template_substitute(text,
272
+ __WORKDIR__ = posixpath_normpath(context.workdir),
273
+ __CWD__ = posixpath_normpath(os.getcwd())
274
+ )
275
+ actual_output = context.command_result.output
276
+ with on_assert_failed_print_details(actual_output, expected_text):
277
+ textutil.assert_normtext_should_contain_multiple_times(actual_output,
278
+ expected_text,
279
+ count)
280
+
281
+ @then(u'the command output should contain exactly "{text}"')
282
+ def step_command_output_should_contain_exactly_text(context, text):
283
+ """
284
+ Verifies that the command output of the last command contains the
285
+ expected text.
286
+
287
+ .. code-block:: gherkin
288
+
289
+ When I run "echo Hello"
290
+ Then the command output should contain "Hello"
291
+ """
292
+ expected_text = text
293
+ if "{__WORKDIR__}" in text or "{__CWD__}" in text:
294
+ expected_text = textutil.template_substitute(text,
295
+ __WORKDIR__ = posixpath_normpath(context.workdir),
296
+ __CWD__ = posixpath_normpath(os.getcwd())
297
+ )
298
+ actual_output = context.command_result.output
299
+ textutil.assert_text_should_contain_exactly(actual_output, expected_text)
300
+
301
+
302
+ @then(u'the command output should not contain exactly "{text}"')
303
+ def step_command_output_should_not_contain_exactly_text(context, text):
304
+ expected_text = text
305
+ if "{__WORKDIR__}" in text or "{__CWD__}" in text:
306
+ expected_text = textutil.template_substitute(text,
307
+ __WORKDIR__ = posixpath_normpath(context.workdir),
308
+ __CWD__ = posixpath_normpath(os.getcwd())
309
+ )
310
+ actual_output = context.command_result.output
311
+ textutil.assert_text_should_not_contain_exactly(actual_output, expected_text)
312
+
313
+
314
+ @then(u'the command output should contain')
315
+ def step_command_output_should_contain(context):
316
+ '''
317
+ EXAMPLE:
318
+ ...
319
+ when I run "behave ..."
320
+ then it should pass
321
+ and the command output should contain:
322
+ """
323
+ TEXT
324
+ """
325
+ '''
326
+ assert context.text is not None, "REQUIRE: multi-line text"
327
+ step_command_output_should_contain_text(context, context.text)
328
+
329
+
330
+ @then(u'the command output should not contain')
331
+ def step_command_output_should_not_contain(context):
332
+ '''
333
+ EXAMPLE:
334
+ ...
335
+ when I run "behave ..."
336
+ then it should pass
337
+ and the command output should not contain:
338
+ """
339
+ TEXT
340
+ """
341
+ '''
342
+ assert context.text is not None, "REQUIRE: multi-line text"
343
+ step_command_output_should_not_contain_text(context, context.text.strip())
344
+
345
+ @then(u'the command output should contain {count:d} times')
346
+ def step_command_output_should_contain_multiple_times(context, count):
347
+ '''
348
+ EXAMPLE:
349
+ ...
350
+ when I run "behave ..."
351
+ then it should pass
352
+ and the command output should contain 2 times:
353
+ """
354
+ TEXT
355
+ """
356
+ '''
357
+ assert context.text is not None, "REQUIRE: multi-line text"
358
+ step_command_output_should_contain_text_multiple_times(context,
359
+ context.text, count)
360
+
361
+ @then(u'the command output should contain exactly')
362
+ def step_command_output_should_contain_exactly_with_multiline_text(context):
363
+ assert context.text is not None, "REQUIRE: multi-line text"
364
+ step_command_output_should_contain_exactly_text(context, context.text)
365
+
366
+
367
+ @then(u'the command output should not contain exactly')
368
+ def step_command_output_should_contain_not_exactly_with_multiline_text(context):
369
+ assert context.text is not None, "REQUIRE: multi-line text"
370
+ step_command_output_should_not_contain_exactly_text(context, context.text)
371
+
372
+
373
+ # -----------------------------------------------------------------------------
374
+ # STEPS FOR: Directories
375
+ # -----------------------------------------------------------------------------
376
+ @step(u'I remove the directory "{directory}"')
377
+ def step_remove_directory(context, directory):
378
+ path_ = directory
379
+ if not os.path.isabs(directory):
380
+ path_ = os.path.join(context.workdir, os.path.normpath(directory))
381
+ if os.path.isdir(path_):
382
+ shutil.rmtree(path_, ignore_errors=True)
383
+ assert_that(not os.path.isdir(path_))
384
+
385
+ @given(u'I ensure that the directory "{directory}" does not exist')
386
+ def step_given_the_directory_should_not_exist(context, directory):
387
+ step_remove_directory(context, directory)
388
+
389
+ @given(u'a directory named "{path}"')
390
+ def step_directory_named_dirname(context, path):
391
+ assert context.workdir, "REQUIRE: context.workdir"
392
+ path_ = os.path.join(context.workdir, os.path.normpath(path))
393
+ if not os.path.exists(path_):
394
+ os.makedirs(path_)
395
+ assert os.path.isdir(path_)
396
+
397
+ @then(u'the directory "{directory}" should exist')
398
+ def step_the_directory_should_exist(context, directory):
399
+ path_ = directory
400
+ if not os.path.isabs(directory):
401
+ path_ = os.path.join(context.workdir, os.path.normpath(directory))
402
+ assert_that(os.path.isdir(path_))
403
+
404
+ @then(u'the directory "{directory}" should not exist')
405
+ def step_the_directory_should_not_exist(context, directory):
406
+ path_ = directory
407
+ if not os.path.isabs(directory):
408
+ path_ = os.path.join(context.workdir, os.path.normpath(directory))
409
+ assert_that(not os.path.isdir(path_))
410
+
411
+ @step(u'the directory "{directory}" exists')
412
+ def step_directory_exists(context, directory):
413
+ """
414
+ Verifies that a directory exists.
415
+
416
+ .. code-block:: gherkin
417
+
418
+ Given the directory "abc.txt" exists
419
+ When the directory "abc.txt" exists
420
+ """
421
+ step_the_directory_should_exist(context, directory)
422
+
423
+ @step(u'the directory "{directory}" does not exist')
424
+ def step_directory_named_does_not_exist(context, directory):
425
+ """
426
+ Verifies that a directory does not exist.
427
+
428
+ .. code-block:: gherkin
429
+
430
+ Given the directory "abc/" does not exist
431
+ When the directory "abc/" does not exist
432
+ """
433
+ step_the_directory_should_not_exist(context, directory)
434
+
435
+ # -----------------------------------------------------------------------------
436
+ # FILE STEPS:
437
+ # -----------------------------------------------------------------------------
438
+ @step(u'a file named "{filename}" exists')
439
+ def step_file_named_filename_exists(context, filename):
440
+ """
441
+ Verifies that a file with this filename exists.
442
+
443
+ .. code-block:: gherkin
444
+
445
+ Given a file named "abc.txt" exists
446
+ When a file named "abc.txt" exists
447
+ """
448
+ step_file_named_filename_should_exist(context, filename)
449
+
450
+ @step(u'a file named "{filename}" does not exist')
451
+ def step_file_named_filename_does_not_exist(context, filename):
452
+ """
453
+ Verifies that a file with this filename does not exist.
454
+
455
+ .. code-block:: gherkin
456
+
457
+ Given a file named "abc.txt" does not exist
458
+ When a file named "abc.txt" does not exist
459
+ """
460
+ step_file_named_filename_should_not_exist(context, filename)
461
+
462
+ @then(u'a file named "{filename}" should exist')
463
+ def step_file_named_filename_should_exist(context, filename):
464
+ command_util.ensure_workdir_exists(context)
465
+ filename_ = pathutil.realpath_with_context(filename, context)
466
+ assert_that(os.path.exists(filename_) and os.path.isfile(filename_))
467
+
468
+ @then(u'a file named "{filename}" should not exist')
469
+ def step_file_named_filename_should_not_exist(context, filename):
470
+ command_util.ensure_workdir_exists(context)
471
+ filename_ = pathutil.realpath_with_context(filename, context)
472
+ assert_that(not os.path.exists(filename_))
473
+
474
+ # -----------------------------------------------------------------------------
475
+ # STEPS FOR FILE CONTENTS:
476
+ # -----------------------------------------------------------------------------
477
+ @then(u'the file "{filename}" should contain "{text}"')
478
+ def step_file_should_contain_text(context, filename, text):
479
+ expected_text = text
480
+ if "{__WORKDIR__}" in text or "{__CWD__}" in text:
481
+ expected_text = textutil.template_substitute(text,
482
+ __WORKDIR__ = posixpath_normpath(context.workdir),
483
+ __CWD__ = posixpath_normpath(os.getcwd())
484
+ )
485
+ file_contents = pathutil.read_file_contents(filename, context=context)
486
+ file_contents = file_contents.rstrip()
487
+ if file_contents_normalizer:
488
+ # -- HACK: Inject TextProcessor as text normalizer
489
+ file_contents = file_contents_normalizer(file_contents)
490
+ with on_assert_failed_print_details(file_contents, expected_text):
491
+ textutil.assert_normtext_should_contain(file_contents, expected_text)
492
+
493
+
494
+ @then(u'the file "{filename}" should not contain "{text}"')
495
+ def step_file_should_not_contain_text(context, filename, text):
496
+ file_contents = pathutil.read_file_contents(filename, context=context)
497
+ file_contents = file_contents.rstrip()
498
+ textutil.assert_normtext_should_not_contain(file_contents, text)
499
+ # XXX assert_that(file_contents, is_not(contains_string(text)))
500
+
501
+
502
+ @then(u'the file "{filename}" should contain')
503
+ def step_file_should_contain_multiline_text(context, filename):
504
+ assert context.text is not None, "REQUIRE: multiline text"
505
+ step_file_should_contain_text(context, filename, context.text)
506
+
507
+
508
+ @then(u'the file "{filename}" should not contain')
509
+ def step_file_should_not_contain_multiline_text(context, filename):
510
+ assert context.text is not None, "REQUIRE: multiline text"
511
+ step_file_should_not_contain_text(context, filename, context.text)
512
+
513
+
514
+ # -----------------------------------------------------------------------------
515
+ # ENVIRONMENT VARIABLES
516
+ # -----------------------------------------------------------------------------
517
+ @step(u'I set the environment variable "{env_name}" to "{env_value}"')
518
+ def step_I_set_the_environment_variable_to(context, env_name, env_value):
519
+ if not hasattr(context, "environ"):
520
+ context.environ = {}
521
+ context.environ[env_name] = env_value
522
+ os.environ[env_name] = env_value
523
+
524
+ @step(u'I remove the environment variable "{env_name}"')
525
+ def step_I_remove_the_environment_variable(context, env_name):
526
+ if not hasattr(context, "environ"):
527
+ context.environ = {}
528
+ context.environ[env_name] = ""
529
+ os.environ[env_name] = ""
530
+ del context.environ[env_name]
531
+ del os.environ[env_name]
532
+