busser-behave 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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,151 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Tests for behave.importing.
4
+ The module provides a lazy-loading/importing mechanism.
5
+ """
6
+
7
+ from __future__ import absolute_import
8
+ from behave.importer import LazyObject, LazyDict, load_module, parse_scoped_name
9
+ from behave.formatter.base import Formatter
10
+ from nose.tools import eq_, assert_raises
11
+ import sys
12
+ import types
13
+ # import unittest
14
+
15
+
16
+ class TestTheory(object): pass
17
+ class ImportModuleTheory(TestTheory):
18
+ """
19
+ Provides a test theory for importing modules.
20
+ """
21
+
22
+ @classmethod
23
+ def ensure_module_is_not_imported(cls, module_name):
24
+ if module_name in sys.modules:
25
+ del sys.modules[module_name]
26
+ cls.assert_module_is_not_imported(module_name)
27
+
28
+ @staticmethod
29
+ def assert_module_is_imported(module_name):
30
+ module = sys.modules.get(module_name, None)
31
+ assert module_name in sys.modules
32
+ assert module is not None
33
+
34
+ @staticmethod
35
+ def assert_module_is_not_imported(module_name):
36
+ assert module_name not in sys.modules
37
+
38
+ @staticmethod
39
+ def assert_module_with_name(module, name):
40
+ assert isinstance(module, types.ModuleType)
41
+ eq_(module.__name__, name)
42
+
43
+
44
+ class TestLoadModule(object):
45
+ theory = ImportModuleTheory
46
+
47
+ def test_load_module__should_fail_for_unknown_module(self):
48
+ assert_raises(ImportError, load_module, "__unknown_module__")
49
+
50
+ def test_load_module__should_succeed_for_already_imported_module(self):
51
+ module_name = "behave.importer"
52
+ self.theory.assert_module_is_imported(module_name)
53
+
54
+ module = load_module(module_name)
55
+ self.theory.assert_module_with_name(module, module_name)
56
+ self.theory.assert_module_is_imported(module_name)
57
+
58
+ def test_load_module__should_succeed_for_existing_module(self):
59
+ module_name = "test._importer_candidate"
60
+ self.theory.ensure_module_is_not_imported(module_name)
61
+
62
+ module = load_module(module_name)
63
+ self.theory.assert_module_with_name(module, module_name)
64
+ self.theory.assert_module_is_imported(module_name)
65
+
66
+ class TestLazyObject(object):
67
+
68
+ def test_get__should_succeed_for_known_object(self):
69
+ lazy = LazyObject("behave.importer", "LazyObject")
70
+ value = lazy.get()
71
+ assert value is LazyObject
72
+
73
+ lazy2 = LazyObject("behave.importer:LazyObject")
74
+ value2 = lazy2.get()
75
+ assert value2 is LazyObject
76
+
77
+ lazy3 = LazyObject("behave.formatter.steps", "StepsFormatter")
78
+ value3 = lazy3.get()
79
+ assert issubclass(value3, Formatter)
80
+
81
+ def test_get__should_fail_for_unknown_module(self):
82
+ lazy = LazyObject("__unknown_module__", "xxx")
83
+ assert_raises(ImportError, lazy.get)
84
+
85
+ def test_get__should_fail_for_unknown_object_in_module(self):
86
+ lazy = LazyObject("test._importer_candidate", "xxx")
87
+ assert_raises(ImportError, lazy.get)
88
+
89
+
90
+ class LazyDictTheory(TestTheory):
91
+
92
+ @staticmethod
93
+ def safe_getitem(data, key):
94
+ return dict.__getitem__(data, key)
95
+
96
+ @classmethod
97
+ def assert_item_is_lazy(cls, data, key):
98
+ value = cls.safe_getitem(data, key)
99
+ cls.assert_is_lazy_object(value)
100
+
101
+ @classmethod
102
+ def assert_item_is_not_lazy(cls, data, key):
103
+ value = cls.safe_getitem(data, key)
104
+ cls.assert_is_not_lazy_object(value)
105
+
106
+ @staticmethod
107
+ def assert_is_lazy_object(obj):
108
+ assert isinstance(obj, LazyObject)
109
+
110
+ @staticmethod
111
+ def assert_is_not_lazy_object(obj):
112
+ assert not isinstance(obj, LazyObject)
113
+
114
+
115
+ class TestLazyDict(object):
116
+ theory = LazyDictTheory
117
+
118
+ def test_unknown_item_access__should_raise_keyerror(self):
119
+ lazy_dict = LazyDict({"alice": 42})
120
+ item_access = lambda key: lazy_dict[key]
121
+ assert_raises(KeyError, item_access, "unknown")
122
+
123
+ def test_plain_item_access__should_succeed(self):
124
+ theory = LazyDictTheory
125
+ lazy_dict = LazyDict({"alice": 42})
126
+ theory.assert_item_is_not_lazy(lazy_dict, "alice")
127
+
128
+ value = lazy_dict["alice"]
129
+ eq_(value, 42)
130
+
131
+ def test_lazy_item_access__should_load_object(self):
132
+ ImportModuleTheory.ensure_module_is_not_imported("inspect")
133
+ lazy_dict = LazyDict({"alice": LazyObject("inspect:ismodule")})
134
+ self.theory.assert_item_is_lazy(lazy_dict, "alice")
135
+ self.theory.assert_item_is_lazy(lazy_dict, "alice")
136
+
137
+ value = lazy_dict["alice"]
138
+ self.theory.assert_is_not_lazy_object(value)
139
+ self.theory.assert_item_is_not_lazy(lazy_dict, "alice")
140
+
141
+ def test_lazy_item_access__should_fail_with_unknown_module(self):
142
+ lazy_dict = LazyDict({"bob": LazyObject("__unknown_module__", "xxx")})
143
+ item_access = lambda key: lazy_dict[key]
144
+ assert_raises(ImportError, item_access, "bob")
145
+
146
+ def test_lazy_item_access__should_fail_with_unknown_object(self):
147
+ lazy_dict = LazyDict({
148
+ "bob": LazyObject("behave.importer", "XUnknown")
149
+ })
150
+ item_access = lambda key: lazy_dict[key]
151
+ assert_raises(ImportError, item_access, "bob")
@@ -0,0 +1,29 @@
1
+ from __future__ import absolute_import, with_statement
2
+
3
+ from nose.tools import *
4
+ from mock import patch
5
+
6
+ from behave.log_capture import LoggingCapture
7
+ from six.moves import range
8
+
9
+ class TestLogCapture(object):
10
+ def test_get_value_returns_all_log_records(self):
11
+ class FakeConfig(object):
12
+ logging_filter = None
13
+ logging_format = None
14
+ logging_datefmt = None
15
+ logging_level = None
16
+
17
+ fake_records = [object() for x in range(0, 10)]
18
+
19
+ handler = LoggingCapture(FakeConfig())
20
+ handler.buffer = fake_records
21
+
22
+ with patch.object(handler.formatter, 'format') as format:
23
+ format.return_value = 'foo'
24
+ expected = '\n'.join(['foo'] * len(fake_records))
25
+
26
+ eq_(handler.getvalue(), expected)
27
+
28
+ calls = [args[0][0] for args in format.call_args_list]
29
+ eq_(calls, fake_records)
@@ -0,0 +1,236 @@
1
+ # -*- coding: UTF-8 -*-
2
+ from __future__ import absolute_import, with_statement
3
+ from mock import Mock, patch
4
+ from nose.tools import * # pylint: disable=wildcard-import, unused-wildcard-import
5
+ import parse
6
+ from behave.matchers import Match, Matcher, ParseMatcher, RegexMatcher, \
7
+ SimplifiedRegexMatcher, CucumberRegexMatcher
8
+ from behave import matchers, runner
9
+
10
+
11
+ class DummyMatcher(Matcher):
12
+ desired_result = None
13
+
14
+ def check_match(self, step):
15
+ return DummyMatcher.desired_result
16
+
17
+ class TestMatcher(object):
18
+ # pylint: disable=invalid-name, no-self-use
19
+
20
+ def setUp(self):
21
+ DummyMatcher.desired_result = None
22
+
23
+ def test_returns_none_if_check_match_returns_none(self):
24
+ matcher = DummyMatcher(None, None)
25
+ assert matcher.match('just a random step') is None
26
+
27
+ def test_returns_match_object_if_check_match_returns_arguments(self):
28
+ arguments = ['some', 'random', 'objects']
29
+ func = lambda x: -x
30
+
31
+ DummyMatcher.desired_result = arguments
32
+ matcher = DummyMatcher(func, None)
33
+
34
+ match = matcher.match('just a random step')
35
+ assert isinstance(match, Match)
36
+ assert match.func is func
37
+ assert match.arguments == arguments
38
+
39
+ class TestParseMatcher(object):
40
+ # pylint: disable=invalid-name, no-self-use
41
+
42
+ def setUp(self):
43
+ self.recorded_args = None
44
+
45
+ def record_args(self, *args, **kwargs):
46
+ self.recorded_args = (args, kwargs)
47
+
48
+ def test_returns_none_if_parser_does_not_match(self):
49
+ # pylint: disable=redefined-outer-name
50
+ # REASON: parse
51
+ matcher = ParseMatcher(None, 'a string')
52
+ with patch.object(matcher.parser, 'parse') as parse:
53
+ parse.return_value = None
54
+ assert matcher.match('just a random step') is None
55
+
56
+ def test_returns_arguments_based_on_matches(self):
57
+ func = lambda x: -x
58
+ matcher = ParseMatcher(func, 'foo')
59
+
60
+ results = parse.Result([1, 2, 3], {'foo': 'bar', 'baz': -45.3},
61
+ {
62
+ 0: (13, 14),
63
+ 1: (16, 17),
64
+ 2: (22, 23),
65
+ 'foo': (32, 35),
66
+ 'baz': (39, 44),
67
+ })
68
+
69
+ expected = [
70
+ (13, 14, '1', 1, None),
71
+ (16, 17, '2', 2, None),
72
+ (22, 23, '3', 3, None),
73
+ (32, 35, 'bar', 'bar', 'foo'),
74
+ (39, 44, '-45.3', -45.3, 'baz'),
75
+ ]
76
+
77
+ with patch.object(matcher.parser, 'parse') as p:
78
+ p.return_value = results
79
+ m = matcher.match('some numbers 1, 2 and 3 and the bar is -45.3')
80
+ assert m.func is func
81
+ args = m.arguments
82
+ have = [(a.start, a.end, a.original, a.value, a.name) for a in args]
83
+ eq_(have, expected)
84
+
85
+ def test_named_arguments(self):
86
+ text = "has a {string}, an {integer:d} and a {decimal:f}"
87
+ matcher = ParseMatcher(self.record_args, text)
88
+ context = runner.Context(Mock())
89
+
90
+ m = matcher.match("has a foo, an 11 and a 3.14159")
91
+ m.run(context)
92
+ eq_(self.recorded_args, ((context,), {
93
+ 'string': 'foo',
94
+ 'integer': 11,
95
+ 'decimal': 3.14159
96
+ }))
97
+
98
+ def test_positional_arguments(self):
99
+ text = "has a {}, an {:d} and a {:f}"
100
+ matcher = ParseMatcher(self.record_args, text)
101
+ context = runner.Context(Mock())
102
+
103
+ m = matcher.match("has a foo, an 11 and a 3.14159")
104
+ m.run(context)
105
+ eq_(self.recorded_args, ((context, 'foo', 11, 3.14159), {}))
106
+
107
+ class TestRegexMatcher(object):
108
+ # pylint: disable=invalid-name, no-self-use
109
+ MATCHER_CLASS = RegexMatcher
110
+
111
+ def test_returns_none_if_regex_does_not_match(self):
112
+ RegexMatcher = self.MATCHER_CLASS
113
+ matcher = RegexMatcher(None, 'a string')
114
+ regex = Mock()
115
+ regex.match.return_value = None
116
+ matcher.regex = regex
117
+ assert matcher.match('just a random step') is None
118
+
119
+ def test_returns_arguments_based_on_groups(self):
120
+ RegexMatcher = self.MATCHER_CLASS
121
+ func = lambda x: -x
122
+ matcher = RegexMatcher(func, 'foo')
123
+
124
+ regex = Mock()
125
+ regex.groupindex = {'foo': 4, 'baz': 5}
126
+
127
+ match = Mock()
128
+ match.groups.return_value = ('1', '2', '3', 'bar', '-45.3')
129
+ positions = {
130
+ 1: (13, 14),
131
+ 2: (16, 17),
132
+ 3: (22, 23),
133
+ 4: (32, 35),
134
+ 5: (39, 44),
135
+ }
136
+ match.start.side_effect = lambda idx: positions[idx][0]
137
+ match.end.side_effect = lambda idx: positions[idx][1]
138
+
139
+ regex.match.return_value = match
140
+ matcher.regex = regex
141
+
142
+ expected = [
143
+ (13, 14, '1', '1', None),
144
+ (16, 17, '2', '2', None),
145
+ (22, 23, '3', '3', None),
146
+ (32, 35, 'bar', 'bar', 'foo'),
147
+ (39, 44, '-45.3', '-45.3', 'baz'),
148
+ ]
149
+
150
+ m = matcher.match('some numbers 1, 2 and 3 and the bar is -45.3')
151
+ assert m.func is func
152
+ args = m.arguments
153
+ have = [(a.start, a.end, a.original, a.value, a.name) for a in args]
154
+ eq_(have, expected)
155
+
156
+
157
+
158
+ class TestSimplifiedRegexMatcher(TestRegexMatcher):
159
+ MATCHER_CLASS = SimplifiedRegexMatcher
160
+
161
+ def test_steps_with_same_prefix_are_not_ordering_sensitive(self):
162
+ # -- RELATED-TO: issue #280
163
+ # pylint: disable=unused-argument
164
+ def step_func1(context): pass # pylint: disable=multiple-statements
165
+ def step_func2(context): pass # pylint: disable=multiple-statements
166
+ # pylint: enable=unused-argument
167
+ matcher1 = SimplifiedRegexMatcher(step_func1, "I do something")
168
+ matcher2 = SimplifiedRegexMatcher(step_func2, "I do something more")
169
+
170
+ # -- CHECK: ORDERING SENSITIVITY
171
+ matched1 = matcher1.match(matcher2.string)
172
+ matched2 = matcher2.match(matcher1.string)
173
+ assert matched1 is None
174
+ assert matched2 is None
175
+
176
+ # -- CHECK: Can match itself (if step text is simple)
177
+ matched1 = matcher1.match(matcher1.string)
178
+ matched2 = matcher2.match(matcher2.string)
179
+ assert isinstance(matched1, Match)
180
+ assert isinstance(matched2, Match)
181
+
182
+ @raises(AssertionError)
183
+ def test_step_should_not_use_regex_begin_marker(self):
184
+ SimplifiedRegexMatcher(None, "^I do something")
185
+
186
+ @raises(AssertionError)
187
+ def test_step_should_not_use_regex_end_marker(self):
188
+ SimplifiedRegexMatcher(None, "I do something$")
189
+
190
+ @raises(AssertionError)
191
+ def test_step_should_not_use_regex_begin_and_end_marker(self):
192
+ SimplifiedRegexMatcher(None, "^I do something$")
193
+
194
+
195
+ class TestCucumberRegexMatcher(TestRegexMatcher):
196
+ MATCHER_CLASS = CucumberRegexMatcher
197
+
198
+ def test_steps_with_same_prefix_are_not_ordering_sensitive(self):
199
+ # -- RELATED-TO: issue #280
200
+ # pylint: disable=unused-argument
201
+ def step_func1(context): pass # pylint: disable=multiple-statements
202
+ def step_func2(context): pass # pylint: disable=multiple-statements
203
+ # pylint: enable=unused-argument
204
+ matcher1 = CucumberRegexMatcher(step_func1, "^I do something$")
205
+ matcher2 = CucumberRegexMatcher(step_func2, "^I do something more$")
206
+
207
+ # -- CHECK: ORDERING SENSITIVITY
208
+ matched1 = matcher1.match(matcher2.string[1:-1])
209
+ matched2 = matcher2.match(matcher1.string[1:-1])
210
+ assert matched1 is None
211
+ assert matched2 is None
212
+
213
+ # -- CHECK: Can match itself (if step text is simple)
214
+ matched1 = matcher1.match(matcher1.string[1:-1])
215
+ matched2 = matcher2.match(matcher2.string[1:-1])
216
+ assert isinstance(matched1, Match)
217
+ assert isinstance(matched2, Match)
218
+
219
+ def test_step_should_use_regex_begin_marker(self):
220
+ CucumberRegexMatcher(None, "^I do something")
221
+
222
+ def test_step_should_use_regex_end_marker(self):
223
+ CucumberRegexMatcher(None, "I do something$")
224
+
225
+ def test_step_should_use_regex_begin_and_end_marker(self):
226
+ CucumberRegexMatcher(None, "^I do something$")
227
+
228
+
229
+ def test_step_matcher_current_matcher():
230
+ current_matcher = matchers.current_matcher
231
+ for name, klass in list(matchers.matcher_mapping.items()):
232
+ matchers.use_step_matcher(name)
233
+ matcher = matchers.get_matcher(lambda x: -x, 'foo')
234
+ assert isinstance(matcher, klass)
235
+
236
+ matchers.current_matcher = current_matcher
@@ -0,0 +1,871 @@
1
+ # -*- coding: utf-8 -*-
2
+ # pylint: disable=no-self-use, line-too-long
3
+
4
+ from __future__ import absolute_import, print_function, with_statement
5
+ import unittest
6
+ from mock import Mock, patch
7
+ from nose.tools import * # pylint: disable=wildcard-import, unused-wildcard-import
8
+ import six
9
+ from six.moves import range # pylint: disable=redefined-builtin
10
+ from six.moves import zip # pylint: disable=redefined-builtin
11
+ if six.PY2:
12
+ import traceback2 as traceback
13
+ traceback_modname = "traceback2"
14
+ else:
15
+ import traceback
16
+ traceback_modname = "traceback"
17
+
18
+ from behave.model_core import FileLocation, Status
19
+ from behave.model import Feature, Scenario, ScenarioOutline, Step
20
+ from behave.model import Table, Row
21
+ from behave.matchers import NoMatch
22
+ from behave.runner import Context
23
+ from behave.capture import CaptureController
24
+ from behave.configuration import Configuration
25
+ from behave.compat.collections import OrderedDict
26
+ from behave import step_registry
27
+
28
+
29
+ # -- CONVENIENCE-ALIAS:
30
+ _text = six.text_type
31
+
32
+
33
+ class TestFeatureRun(unittest.TestCase):
34
+ # pylint: disable=invalid-name
35
+
36
+ def setUp(self):
37
+ self.runner = Mock()
38
+ self.runner.aborted = False
39
+ self.runner.feature.tags = []
40
+ self.config = self.runner.config = Mock()
41
+ self.context = self.runner.context = Mock()
42
+ self.formatters = self.runner.formatters = [Mock()]
43
+ self.run_hook = self.runner.run_hook = Mock()
44
+
45
+ def test_formatter_feature_called(self):
46
+ feature = Feature('foo.feature', 1, u'Feature', u'foo',
47
+ background=Mock())
48
+
49
+ feature.run(self.runner)
50
+
51
+ self.formatters[0].feature.assert_called_with(feature)
52
+
53
+ def test_formatter_background_called_when_feature_has_background(self):
54
+ feature = Feature('foo.feature', 1, u'Feature', u'foo',
55
+ background=Mock())
56
+
57
+ feature.run(self.runner)
58
+
59
+ self.formatters[0].background.assert_called_with(feature.background)
60
+
61
+ def test_formatter_background_not_called_when_feature_has_no_background(self):
62
+ feature = Feature('foo.feature', 1, u'Feature', u'foo')
63
+
64
+ feature.run(self.runner)
65
+
66
+ assert not self.formatters[0].background.called
67
+
68
+ def test_run_runs_scenarios(self):
69
+ scenarios = [Mock(), Mock()]
70
+ for scenario in scenarios:
71
+ scenario.tags = []
72
+ scenario.run.return_value = False
73
+
74
+ self.config.tags.check.return_value = True # pylint: disable=no-member
75
+ self.config.name = []
76
+
77
+ feature = Feature('foo.feature', 1, u'Feature', u'foo',
78
+ scenarios=scenarios)
79
+
80
+ feature.run(self.runner)
81
+
82
+ for scenario in scenarios:
83
+ scenario.run.assert_called_with(self.runner)
84
+
85
+ def test_run_runs_named_scenarios(self):
86
+ scenarios = [Mock(Scenario), Mock(Scenario)]
87
+ scenarios[0].name = 'first scenario'
88
+ scenarios[1].name = 'second scenario'
89
+ scenarios[0].tags = []
90
+ scenarios[1].tags = []
91
+ # -- FAKE-CHECK:
92
+ scenarios[0].should_run_with_name_select.return_value = True
93
+ scenarios[1].should_run_with_name_select.return_value = False
94
+
95
+ for scenario in scenarios:
96
+ scenario.run.return_value = False
97
+
98
+ self.config.tags.check.return_value = True # pylint: disable=no-member
99
+ self.config.name = ['first', 'third']
100
+ self.config.name_re = Configuration.build_name_re(self.config.name)
101
+
102
+ feature = Feature('foo.feature', 1, u'Feature', u'foo',
103
+ scenarios=scenarios)
104
+
105
+ feature.run(self.runner)
106
+
107
+ scenarios[0].run.assert_called_with(self.runner)
108
+ assert not scenarios[1].run.called
109
+ scenarios[0].should_run_with_name_select.assert_called_with(self.config)
110
+ scenarios[1].should_run_with_name_select.assert_called_with(self.config)
111
+
112
+ def test_run_runs_named_scenarios_with_regexp(self):
113
+ scenarios = [Mock(), Mock()]
114
+ scenarios[0].name = 'first scenario'
115
+ scenarios[1].name = 'second scenario'
116
+ scenarios[0].tags = []
117
+ scenarios[1].tags = []
118
+ # -- FAKE-CHECK:
119
+ scenarios[0].should_run_with_name_select.return_value = False
120
+ scenarios[1].should_run_with_name_select.return_value = True
121
+
122
+ for scenario in scenarios:
123
+ scenario.run.return_value = False
124
+
125
+ self.config.tags.check.return_value = True # pylint: disable=no-member
126
+ self.config.name = ['third .*', 'second .*']
127
+ self.config.name_re = Configuration.build_name_re(self.config.name)
128
+
129
+ feature = Feature('foo.feature', 1, u'Feature', u'foo',
130
+ scenarios=scenarios)
131
+
132
+ feature.run(self.runner)
133
+
134
+ assert not scenarios[0].run.called
135
+ scenarios[1].run.assert_called_with(self.runner)
136
+ scenarios[0].should_run_with_name_select.assert_called_with(self.config)
137
+ scenarios[1].should_run_with_name_select.assert_called_with(self.config)
138
+
139
+ # @prepared
140
+ def test_run_exclude_named_scenarios_with_regexp(self):
141
+ # -- NOTE: Works here only because it is run against Mocks.
142
+ scenarios = [Mock(), Mock(), Mock()]
143
+ scenarios[0].name = "Alice in Florida"
144
+ scenarios[1].name = "Alice and Bob"
145
+ scenarios[2].name = "Bob in Paris"
146
+ scenarios[0].tags = []
147
+ scenarios[1].tags = []
148
+ scenarios[2].tags = []
149
+ # -- FAKE-CHECK:
150
+ scenarios[0].should_run_with_name_select.return_value = False
151
+ scenarios[1].should_run_with_name_select.return_value = False
152
+ scenarios[2].should_run_with_name_select.return_value = True
153
+
154
+ for scenario in scenarios:
155
+ scenario.run.return_value = False
156
+
157
+ self.config.tags.check.return_value = True # pylint: disable=no-member
158
+ self.config.name = ["(?!Alice)"] # Exclude all scenarios with "Alice"
159
+ self.config.name_re = Configuration.build_name_re(self.config.name)
160
+
161
+ feature = Feature('foo.feature', 1, u'Feature', u'foo',
162
+ scenarios=scenarios)
163
+
164
+ feature.run(self.runner)
165
+
166
+ assert not scenarios[0].run.called
167
+ scenarios[0].should_run_with_name_select.assert_called_with(self.config)
168
+ scenarios[1].should_run_with_name_select.assert_called_with(self.config)
169
+ scenarios[2].should_run_with_name_select.assert_called_with(self.config)
170
+ scenarios[0].run.assert_not_called()
171
+ scenarios[1].run.assert_not_called()
172
+ scenarios[2].run.assert_called_with(self.runner)
173
+
174
+ def test_feature_hooks_not_run_if_feature_not_being_run(self):
175
+ self.config.tags.check.return_value = False # pylint: disable=no-member
176
+
177
+ feature = Feature('foo.feature', 1, u'Feature', u'foo')
178
+ feature.run(self.runner)
179
+ assert not self.run_hook.called
180
+
181
+
182
+ class TestScenarioRun(unittest.TestCase):
183
+ # pylint: disable=invalid-name
184
+
185
+ def setUp(self):
186
+ self.runner = Mock()
187
+ self.runner.aborted = False
188
+ self.runner.feature.tags = []
189
+ self.config = self.runner.config = Mock()
190
+ self.config.dry_run = False
191
+ self.context = self.runner.context = Mock()
192
+ self.formatters = self.runner.formatters = [Mock()]
193
+ self.run_hook = self.runner.run_hook = Mock()
194
+
195
+ def test_run_invokes_formatter_scenario_and_steps_correctly(self):
196
+ self.config.stdout_capture = False
197
+ self.config.log_capture = False
198
+ self.config.tags.check.return_value = True # pylint: disable=no-member
199
+ steps = [Mock(), Mock()]
200
+ scenario = Scenario('foo.feature', 17, u'Scenario', u'foo',
201
+ steps=steps)
202
+
203
+ scenario.run(self.runner)
204
+
205
+ self.formatters[0].scenario.assert_called_with(scenario)
206
+ for step in steps:
207
+ step.run.assert_called_with(self.runner)
208
+
209
+ if six.PY3:
210
+ stringio_target = 'io.StringIO'
211
+ else:
212
+ stringio_target = 'StringIO.StringIO'
213
+
214
+ def test_handles_stdout_and_log_capture(self):
215
+ self.config.stdout_capture = True
216
+ self.config.log_capture = True
217
+ self.config.tags.check.return_value = True # pylint: disable=no-member
218
+
219
+ steps = [Mock(), Mock()]
220
+ scenario = Scenario('foo.feature', 17, u'Scenario', u'foo',
221
+ steps=steps)
222
+
223
+ scenario.run(self.runner)
224
+
225
+ self.runner.setup_capture.assert_called_with()
226
+ self.runner.teardown_capture.assert_called_with()
227
+
228
+ def test_failed_step_causes_remaining_steps_to_be_skipped(self):
229
+ self.config.stdout_capture = False
230
+ self.config.log_capture = False
231
+ self.config.tags.check.return_value = True # pylint: disable=no-member
232
+
233
+ steps = [Mock(), Mock()]
234
+ scenario = Scenario('foo.feature', 17, u'Scenario', u'foo',
235
+ steps=steps)
236
+ steps[0].run.return_value = False
237
+ steps[1].step_type = "when"
238
+ steps[1].name = "step1"
239
+
240
+ def step1_function(context): # pylint: disable=unused-argument
241
+ pass
242
+ my_step_registry = step_registry.StepRegistry()
243
+ my_step_registry.add_step_definition("when", "step1", step1_function)
244
+
245
+ with patch("behave.step_registry.registry", my_step_registry):
246
+ assert scenario.run(self.runner)
247
+ eq_(steps[1].status, Status.skipped)
248
+
249
+ def test_failed_step_causes_context_failure_to_be_set(self):
250
+ self.config.stdout_capture = False
251
+ self.config.log_capture = False
252
+ self.config.tags.check.return_value = True # pylint: disable=no-member
253
+
254
+ steps = [
255
+ Mock(step_type="given", name="step0"),
256
+ Mock(step_type="then", name="step1"),
257
+ ]
258
+ scenario = Scenario('foo.feature', 17, u'Scenario', u'foo',
259
+ steps=steps)
260
+ steps[0].run.return_value = False
261
+
262
+ assert scenario.run(self.runner)
263
+ # pylint: disable=protected-access
264
+ self.context._set_root_attribute.assert_called_with("failed", True)
265
+
266
+ def test_undefined_step_causes_failed_scenario_status(self):
267
+ self.config.stdout_capture = False
268
+ self.config.log_capture = False
269
+ self.config.tags.check.return_value = True # pylint: disable=no-member
270
+
271
+ passed_step = Mock()
272
+ undefined_step = Mock()
273
+
274
+ steps = [passed_step, undefined_step]
275
+ scenario = Scenario('foo.feature', 17, u'Scenario', u'foo',
276
+ steps=steps)
277
+ passed_step.run.return_value = True
278
+ passed_step.status = Status.passed
279
+ undefined_step.run.return_value = False
280
+ undefined_step.status = Status.undefined
281
+
282
+ assert scenario.run(self.runner)
283
+ eq_(undefined_step.status, Status.undefined)
284
+ eq_(scenario.status, Status.failed)
285
+ # pylint: disable=protected-access
286
+ self.context._set_root_attribute.assert_called_with("failed", True)
287
+
288
+ def test_skipped_steps_set_step_status_and_scenario_status_if_not_set(self):
289
+ self.config.stdout_capture = False
290
+ self.config.log_capture = False
291
+ self.config.tags.check.return_value = False # pylint: disable=no-member
292
+
293
+ steps = [Mock(), Mock()]
294
+ scenario = Scenario('foo.feature', 17, u'Scenario', u'foo',
295
+ steps=steps)
296
+
297
+ scenario.run(self.runner)
298
+
299
+ assert False not in [s.status == Status.skipped for s in steps]
300
+ eq_(scenario.status, Status.skipped)
301
+
302
+ def test_scenario_hooks_not_run_if_scenario_not_being_run(self):
303
+ self.config.tags.check.return_value = False # pylint: disable=no-member
304
+
305
+ scenario = Scenario('foo.feature', 17, u'Scenario', u'foo')
306
+
307
+ scenario.run(self.runner)
308
+
309
+ assert not self.run_hook.called
310
+
311
+ def test_should_run_with_name_select(self):
312
+ scenario_name = u"first scenario"
313
+ scenario = Scenario("foo.feature", 17, u"Scenario", scenario_name)
314
+ self.config.name = ['first .*', 'second .*']
315
+ self.config.name_re = Configuration.build_name_re(self.config.name)
316
+
317
+ assert scenario.should_run_with_name_select(self.config)
318
+
319
+ class TestScenarioOutline(unittest.TestCase):
320
+ # pylint: disable=invalid-name
321
+
322
+ def test_run_calls_run_on_each_generated_scenario(self):
323
+ # pylint: disable=protected-access
324
+ outline = ScenarioOutline('foo.feature', 17, u'Scenario Outline',
325
+ u'foo')
326
+ outline._scenarios = [Mock(), Mock()]
327
+ for scenario in outline._scenarios:
328
+ scenario.run.return_value = False
329
+
330
+ runner = Mock()
331
+ runner.context = Mock()
332
+
333
+ outline.run(runner)
334
+
335
+ for s in outline._scenarios:
336
+ s.run.assert_called_with(runner)
337
+
338
+ def test_run_stops_on_first_failure_if_requested(self):
339
+ # pylint: disable=protected-access
340
+ outline = ScenarioOutline('foo.feature', 17, u'Scenario Outline',
341
+ u'foo')
342
+ outline._scenarios = [Mock(), Mock()]
343
+ outline._scenarios[0].run.return_value = True
344
+
345
+ runner = Mock()
346
+ runner.context = Mock()
347
+ config = runner.config = Mock()
348
+ config.stop = True
349
+
350
+ outline.run(runner)
351
+
352
+ outline._scenarios[0].run.assert_called_with(runner)
353
+ assert not outline._scenarios[1].run.called
354
+
355
+ def test_run_sets_context_variable_for_outline(self):
356
+ # pylint: disable=protected-access
357
+ outline = ScenarioOutline('foo.feature', 17, u'Scenario Outline',
358
+ u'foo')
359
+ outline._scenarios = [Mock(), Mock(), Mock()]
360
+ for scenario in outline._scenarios:
361
+ scenario.run.return_value = False
362
+
363
+ runner = Mock()
364
+ context = runner.context = Mock()
365
+ config = runner.config = Mock()
366
+ config.stop = True
367
+
368
+ outline.run(runner)
369
+
370
+ eq_(context._set_root_attribute.call_args_list, [
371
+ (('active_outline', outline._scenarios[0]._row), {}),
372
+ (('active_outline', outline._scenarios[1]._row), {}),
373
+ (('active_outline', outline._scenarios[2]._row), {}),
374
+ (('active_outline', None), {}),
375
+ ])
376
+
377
+ def test_run_should_pass_when_all_examples_pass(self):
378
+ # pylint: disable=protected-access
379
+ outline = ScenarioOutline('foo.feature', 17, u'Scenario Outline',
380
+ u'foo')
381
+ outline._scenarios = [Mock(), Mock(), Mock()]
382
+ for scenario in outline._scenarios:
383
+ scenario.run.return_value = False
384
+
385
+ runner = Mock()
386
+ context = runner.context = Mock()
387
+ config = runner.config = Mock()
388
+ config.stop = True
389
+
390
+ resultFailed = outline.run(runner)
391
+ eq_(resultFailed, False)
392
+
393
+ def test_run_should_fail_when_first_examples_fails(self):
394
+ outline = ScenarioOutline('foo.feature', 17, u'Scenario Outline',
395
+ u'foo')
396
+ failed = True
397
+ # pylint: disable=protected-access
398
+ outline._scenarios = [Mock(), Mock()]
399
+ outline._scenarios[0].run.return_value = failed
400
+ outline._scenarios[1].run.return_value = not failed
401
+
402
+ runner = Mock()
403
+ context = runner.context = Mock()
404
+ config = runner.config = Mock()
405
+ config.stop = True
406
+
407
+ resultFailed = outline.run(runner)
408
+ eq_(resultFailed, True)
409
+
410
+ def test_run_should_fail_when_last_examples_fails(self):
411
+ outline = ScenarioOutline('foo.feature', 17, u'Scenario Outline',
412
+ u'foo')
413
+ failed = True
414
+ # pylint: disable=protected-access
415
+ outline._scenarios = [Mock(), Mock()]
416
+ outline._scenarios[0].run.return_value = not failed
417
+ outline._scenarios[1].run.return_value = failed
418
+
419
+ runner = Mock()
420
+ context = runner.context = Mock()
421
+ config = runner.config = Mock()
422
+ config.stop = True
423
+
424
+ resultFailed = outline.run(runner)
425
+ eq_(resultFailed, True)
426
+
427
+ def test_run_should_fail_when_middle_examples_fails(self):
428
+ outline = ScenarioOutline('foo.feature', 17, u'Scenario Outline',
429
+ u'foo')
430
+ failed = True
431
+ # pylint: disable=protected-access
432
+ outline._scenarios = [Mock(), Mock(), Mock()]
433
+ outline._scenarios[0].run.return_value = not failed
434
+ outline._scenarios[1].run.return_value = failed
435
+ outline._scenarios[2].run.return_value = not failed
436
+
437
+ runner = Mock()
438
+ context = runner.context = Mock()
439
+ config = runner.config = Mock()
440
+ config.stop = True
441
+
442
+ resultFailed = outline.run(runner)
443
+ eq_(resultFailed, True)
444
+
445
+
446
+ def raiser(exception):
447
+ def func(*args, **kwargs): # pylint: disable=unused-argument
448
+ raise exception
449
+ return func
450
+
451
+
452
+ class TestStepRun(unittest.TestCase):
453
+ # pylint: disable=invalid-name
454
+
455
+ def setUp(self):
456
+ self.step_registry = Mock()
457
+ self.runner = Mock()
458
+ # self.capture_controller = self.runner.capture_controller = Mock()
459
+ self.capture_controller = CaptureController(self.runner.config)
460
+ self.runner.capture_controller = self.capture_controller
461
+ self.runner.step_registry = self.step_registry
462
+ self.config = self.runner.config = Mock()
463
+ self.config.outputs = [None]
464
+ self.context = self.runner.context = Mock()
465
+ print('context is %s' % self.context)
466
+ self.formatters = self.runner.formatters = [Mock()]
467
+ self.stdout_capture = self.capture_controller.stdout_capture = Mock()
468
+ self.stdout_capture.getvalue.return_value = ''
469
+ self.stderr_capture = self.capture_controller.stderr_capture = Mock()
470
+ self.stderr_capture.getvalue.return_value = ''
471
+ self.log_capture = self.capture_controller.log_capture = Mock()
472
+ self.log_capture.getvalue.return_value = ''
473
+ self.run_hook = self.runner.run_hook = Mock()
474
+
475
+ def test_run_appends_step_to_undefined_when_no_match_found(self):
476
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
477
+ self.runner.step_registry.find_match.return_value = None
478
+ self.runner.undefined_steps = []
479
+ assert not step.run(self.runner)
480
+
481
+ assert step in self.runner.undefined_steps
482
+ eq_(step.status, Status.undefined)
483
+
484
+ def test_run_reports_undefined_step_via_formatter_when_not_quiet(self):
485
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
486
+ self.runner.step_registry.find_match.return_value = None
487
+ assert not step.run(self.runner)
488
+
489
+ self.formatters[0].match.assert_called_with(NoMatch())
490
+ self.formatters[0].result.assert_called_with(step)
491
+
492
+ def test_run_with_no_match_does_not_touch_formatter_when_quiet(self):
493
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
494
+ self.runner.step_registry.find_match.return_value = None
495
+ assert not step.run(self.runner, quiet=True)
496
+
497
+ assert not self.formatters[0].match.called
498
+ assert not self.formatters[0].result.called
499
+
500
+ def test_run_when_not_quiet_reports_match_and_result(self):
501
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
502
+ match = Mock()
503
+ self.runner.step_registry.find_match.return_value = match
504
+
505
+ side_effects = (None, raiser(AssertionError('whee')),
506
+ raiser(Exception('whee')))
507
+ for side_effect in side_effects:
508
+ match.run.side_effect = side_effect
509
+ step.run(self.runner)
510
+ self.formatters[0].match.assert_called_with(match)
511
+ self.formatters[0].result.assert_called_with(step)
512
+
513
+ def test_run_when_quiet_reports_nothing(self):
514
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
515
+ match = Mock()
516
+ self.runner.step_registry.find_match.return_value = match
517
+
518
+ side_effects = (None, raiser(AssertionError('whee')),
519
+ raiser(Exception('whee')))
520
+ for side_effect in side_effects:
521
+ match.run.side_effect = side_effect
522
+ step.run(self.runner, quiet=True)
523
+ assert not self.formatters[0].match.called
524
+ assert not self.formatters[0].result.called
525
+
526
+ def test_run_runs_before_hook_then_match_then_after_hook(self):
527
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
528
+ match = Mock()
529
+ self.runner.step_registry.find_match.return_value = match
530
+
531
+ side_effects = (None, AssertionError('whee'), Exception('whee'))
532
+ for side_effect in side_effects:
533
+ # Make match.run() and runner.run_hook() the same mock so
534
+ # we can make sure things happen in the right order.
535
+ self.runner.run_hook = match.run = Mock()
536
+
537
+ def effect(thing):
538
+ # pylint: disable=unused-argument
539
+ def raiser_(*args, **kwargs):
540
+ match.run.side_effect = None
541
+ if thing:
542
+ raise thing
543
+
544
+ def nonraiser(*args, **kwargs):
545
+ match.run.side_effect = raiser_
546
+
547
+ return nonraiser
548
+
549
+ match.run.side_effect = effect(side_effect)
550
+ step.run(self.runner)
551
+
552
+ eq_(match.run.call_args_list, [
553
+ (('before_step', self.context, step), {}),
554
+ ((self.context,), {}),
555
+ (('after_step', self.context, step), {}),
556
+ ])
557
+
558
+
559
+ def test_run_sets_table_if_present(self):
560
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo',
561
+ table=Mock())
562
+ self.runner.step_registry.find_match.return_value = Mock()
563
+ step.run(self.runner)
564
+ eq_(self.context.table, step.table)
565
+
566
+ def test_run_sets_text_if_present(self):
567
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo',
568
+ text=Mock(name='text'))
569
+ self.runner.step_registry.find_match.return_value = Mock()
570
+ step.run(self.runner)
571
+
572
+ eq_(self.context.text, step.text)
573
+
574
+ def test_run_sets_status_to_passed_if_nothing_goes_wrong(self):
575
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
576
+ step.error_message = None
577
+ self.runner.step_registry.find_match.return_value = Mock()
578
+ step.run(self.runner)
579
+
580
+ eq_(step.status, Status.passed)
581
+ eq_(step.error_message, None)
582
+
583
+ def test_run_sets_status_to_failed_on_assertion_error(self):
584
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
585
+ self.runner.context = Context(self.runner)
586
+ self.runner.config.stdout_capture = True
587
+ self.runner.config.log_capture = False
588
+ self.runner.capture_controller = CaptureController(self.runner.config)
589
+ self.runner.capture_controller.setup_capture(self.runner.context)
590
+ step.error_message = None
591
+ match = Mock()
592
+ match.run.side_effect = raiser(AssertionError('whee'))
593
+ self.runner.step_registry.find_match.return_value = match
594
+ step.run(self.runner)
595
+
596
+ eq_(step.status, Status.failed)
597
+ assert step.error_message.startswith('Assertion Failed')
598
+
599
+ @patch('%s.format_exc' % traceback_modname)
600
+ def test_run_sets_status_to_failed_on_exception(self, format_exc):
601
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
602
+ step.error_message = None
603
+ match = Mock()
604
+ match.run.side_effect = raiser(Exception('whee'))
605
+ self.runner.step_registry.find_match.return_value = match
606
+ format_exc.return_value = 'something to do with an exception'
607
+
608
+ step.run(self.runner)
609
+ eq_(step.status, Status.failed)
610
+ eq_(step.error_message, format_exc.return_value)
611
+
612
+ @patch('time.time')
613
+ def test_run_calculates_duration(self, time_time):
614
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
615
+ match = Mock()
616
+ self.runner.step_registry.find_match.return_value = match
617
+
618
+ def time_time_1():
619
+ def time_time_2():
620
+ return 23
621
+ time_time.side_effect = time_time_2
622
+ return 17
623
+
624
+ side_effects = (None, raiser(AssertionError('whee')),
625
+ raiser(Exception('whee')))
626
+ for side_effect in side_effects:
627
+ match.run.side_effect = side_effect
628
+ time_time.side_effect = time_time_1
629
+
630
+ step.run(self.runner)
631
+ eq_(step.duration, 23 - 17)
632
+
633
+ def test_run_captures_stdout_and_logging(self):
634
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
635
+ match = Mock()
636
+ self.runner.step_registry.find_match.return_value = match
637
+
638
+ assert step.run(self.runner)
639
+
640
+ self.runner.start_capture.assert_called_with()
641
+ self.runner.stop_capture.assert_called_with()
642
+
643
+ def test_run_appends_any_captured_stdout_on_failure(self):
644
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
645
+ match = Mock()
646
+ self.runner.step_registry.find_match.return_value = match
647
+ self.stdout_capture.getvalue.return_value = 'frogs'
648
+ match.run.side_effect = raiser(Exception('halibut'))
649
+
650
+ assert not step.run(self.runner)
651
+ assert 'Captured stdout:' in step.error_message
652
+ assert 'frogs' in step.error_message
653
+
654
+ def test_run_appends_any_captured_logging_on_failure(self):
655
+ step = Step('foo.feature', 17, u'Given', 'given', u'foo')
656
+ match = Mock()
657
+ self.runner.step_registry.find_match.return_value = match
658
+ self.log_capture.getvalue.return_value = 'toads'
659
+ match.run.side_effect = raiser(AssertionError('kipper'))
660
+
661
+ assert not step.run(self.runner)
662
+ assert 'Captured logging:' in step.error_message
663
+ assert 'toads' in step.error_message
664
+
665
+
666
+ class TestTableModel(unittest.TestCase):
667
+ # pylint: disable=invalid-name
668
+ HEAD = [u'type of stuff', u'awesomeness', u'ridiculousness']
669
+ DATA = [
670
+ [u'fluffy', u'large', u'frequent'],
671
+ [u'lint', u'low', u'high'],
672
+ [u'green', u'variable', u'awkward'],
673
+ ]
674
+
675
+ def setUp(self):
676
+ self.table = Table(self.HEAD, 0, self.DATA)
677
+
678
+ def test_equivalence(self):
679
+ t1 = self.table
680
+ self.setUp()
681
+ eq_(t1, self.table)
682
+
683
+ def test_table_iteration(self):
684
+ for i, row in enumerate(self.table):
685
+ for j, cell in enumerate(row):
686
+ eq_(cell, self.DATA[i][j])
687
+
688
+ def test_table_row_by_index(self):
689
+ for i in range(3):
690
+ eq_(self.table[i], Row(self.HEAD, self.DATA[i], 0))
691
+
692
+ def test_table_row_name(self):
693
+ eq_(self.table[0]['type of stuff'], 'fluffy')
694
+ eq_(self.table[1]['awesomeness'], 'low')
695
+ eq_(self.table[2]['ridiculousness'], 'awkward')
696
+
697
+ def test_table_row_index(self):
698
+ eq_(self.table[0][0], 'fluffy')
699
+ eq_(self.table[1][1], 'low')
700
+ eq_(self.table[2][2], 'awkward')
701
+
702
+ @raises(KeyError)
703
+ def test_table_row_keyerror(self):
704
+ self.table[0]['spam'] # pylint: disable=pointless-statement
705
+
706
+ def test_table_row_items(self):
707
+ eq_(list(self.table[0].items()), list(zip(self.HEAD, self.DATA[0])))
708
+
709
+
710
+ class TestModelRow(unittest.TestCase):
711
+ # pylint: disable=invalid-name, bad-whitespace
712
+ HEAD = [u'name', u'sex', u'age']
713
+ DATA = [u'Alice', u'female', u'12']
714
+
715
+ def setUp(self):
716
+ self.row = Row(self.HEAD, self.DATA, 0)
717
+
718
+ def test_len(self):
719
+ eq_(len(self.row), 3)
720
+
721
+ def test_getitem_with_valid_colname(self):
722
+ # pylint: disable=bad-whitespace
723
+ eq_(self.row['name'], u'Alice')
724
+ eq_(self.row['sex'], u'female')
725
+ eq_(self.row['age'], u'12')
726
+
727
+ @raises(KeyError)
728
+ def test_getitem_with_unknown_colname(self):
729
+ self.row['__UNKNOWN_COLUMN__'] # pylint: disable=pointless-statement
730
+
731
+ def test_getitem_with_valid_index(self):
732
+ eq_(self.row[0], u'Alice')
733
+ eq_(self.row[1], u'female')
734
+ eq_(self.row[2], u'12')
735
+
736
+ @raises(IndexError)
737
+ def test_getitem_with_invalid_index(self):
738
+ colsize = len(self.row)
739
+ eq_(colsize, 3)
740
+ self.row[colsize] # pylint: disable=pointless-statement
741
+
742
+ def test_get_with_valid_colname(self):
743
+ # pylint: disable=bad-whitespace
744
+ eq_(self.row.get('name'), u'Alice')
745
+ eq_(self.row.get('sex'), u'female')
746
+ eq_(self.row.get('age'), u'12')
747
+
748
+ def test_getitem_with_unknown_colname_should_return_default(self):
749
+ eq_(self.row.get('__UNKNOWN_COLUMN__', 'XXX'), u'XXX')
750
+
751
+ def test_as_dict(self):
752
+ data1 = self.row.as_dict()
753
+ data2 = dict(self.row.as_dict())
754
+ assert isinstance(data1, dict)
755
+ assert isinstance(data2, dict)
756
+ assert isinstance(data1, OrderedDict)
757
+ # -- REQUIRES: Python2.7 or ordereddict installed.
758
+ # assert not isinstance(data2, OrderedDict)
759
+ eq_(data1, data2)
760
+ # pylint: disable=bad-whitespace
761
+ eq_(data1['name'], u'Alice')
762
+ eq_(data1['sex'], u'female')
763
+ eq_(data1['age'], u'12')
764
+
765
+
766
+ class TestFileLocation(unittest.TestCase):
767
+ # pylint: disable=invalid-name
768
+ ordered_locations1 = [
769
+ FileLocation("features/alice.feature", 1),
770
+ FileLocation("features/alice.feature", 5),
771
+ FileLocation("features/alice.feature", 10),
772
+ FileLocation("features/alice.feature", 11),
773
+ FileLocation("features/alice.feature", 100),
774
+ ]
775
+ ordered_locations2 = [
776
+ FileLocation("features/alice.feature", 1),
777
+ FileLocation("features/alice.feature", 10),
778
+ FileLocation("features/bob.feature", 5),
779
+ FileLocation("features/charly.feature", None),
780
+ FileLocation("features/charly.feature", 0),
781
+ FileLocation("features/charly.feature", 100),
782
+ ]
783
+ same_locations = [
784
+ (FileLocation("alice.feature"),
785
+ FileLocation("alice.feature", None),
786
+ ),
787
+ (FileLocation("alice.feature", 10),
788
+ FileLocation("alice.feature", 10),
789
+ ),
790
+ (FileLocation("features/bob.feature", 11),
791
+ FileLocation("features/bob.feature", 11),
792
+ ),
793
+ ]
794
+
795
+ def test_compare_equal(self):
796
+ for value1, value2 in self.same_locations:
797
+ eq_(value1, value2)
798
+
799
+ def test_compare_equal_with_string(self):
800
+ for location in self.ordered_locations2:
801
+ eq_(location, location.filename)
802
+ eq_(location.filename, location)
803
+
804
+ def test_compare_not_equal(self):
805
+ for value1, value2 in self.same_locations:
806
+ assert not(value1 != value2) # pylint: disable=unneeded-not, superfluous-parens
807
+
808
+ for locations in [self.ordered_locations1, self.ordered_locations2]:
809
+ for value1, value2 in zip(locations, locations[1:]):
810
+ assert value1 != value2
811
+
812
+ def test_compare_less_than(self):
813
+ for locations in [self.ordered_locations1, self.ordered_locations2]:
814
+ for value1, value2 in zip(locations, locations[1:]):
815
+ assert value1 < value2, "FAILED: %s < %s" % (_text(value1), _text(value2))
816
+ assert value1 != value2
817
+
818
+ def test_compare_less_than_with_string(self):
819
+ locations = self.ordered_locations2
820
+ for value1, value2 in zip(locations, locations[1:]):
821
+ if value1.filename == value2.filename:
822
+ continue
823
+ assert value1 < value2.filename, \
824
+ "FAILED: %s < %s" % (_text(value1), _text(value2.filename))
825
+ assert value1.filename < value2, \
826
+ "FAILED: %s < %s" % (_text(value1.filename), _text(value2))
827
+
828
+ def test_compare_greater_than(self):
829
+ for locations in [self.ordered_locations1, self.ordered_locations2]:
830
+ for value1, value2 in zip(locations, locations[1:]):
831
+ assert value2 > value1, "FAILED: %s > %s" % (_text(value2), _text(value1))
832
+ assert value2 != value1
833
+
834
+ def test_compare_less_or_equal(self):
835
+ for value1, value2 in self.same_locations:
836
+ assert value1 <= value2, "FAILED: %s <= %s" % (_text(value1), _text(value2))
837
+ assert value1 == value2
838
+
839
+ for locations in [self.ordered_locations1, self.ordered_locations2]:
840
+ for value1, value2 in zip(locations, locations[1:]):
841
+ assert value1 <= value2, "FAILED: %s <= %s" % (_text(value1), _text(value2))
842
+ assert value1 != value2
843
+
844
+ def test_compare_greater_or_equal(self):
845
+ for value1, value2 in self.same_locations:
846
+ assert value2 >= value1, "FAILED: %s >= %s" % (_text(value2), _text(value1))
847
+ assert value2 == value1
848
+
849
+ for locations in [self.ordered_locations1, self.ordered_locations2]:
850
+ for value1, value2 in zip(locations, locations[1:]):
851
+ assert value2 >= value1, "FAILED: %s >= %s" % (_text(value2), _text(value1))
852
+ assert value2 != value1
853
+
854
+ def test_filename_should_be_same_as_self(self):
855
+ for location in self.ordered_locations2:
856
+ assert location == location.filename
857
+ assert location.filename == location
858
+
859
+ def test_string_conversion(self):
860
+ for location in self.ordered_locations2:
861
+ expected = u"%s:%s" % (location.filename, location.line)
862
+ if location.line is None:
863
+ expected = location.filename
864
+ assert six.text_type(location) == expected
865
+
866
+ def test_repr_conversion(self):
867
+ for location in self.ordered_locations2:
868
+ expected = u'<FileLocation: filename="%s", line=%s>' % \
869
+ (location.filename, location.line)
870
+ actual = repr(location)
871
+ assert actual == expected, "FAILED: %s == %s" % (actual, expected)