jwilger-cucumber 0.3.11.200906161550

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 (411) hide show
  1. data/History.txt +830 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +410 -0
  4. data/README.txt +4 -0
  5. data/Rakefile +9 -0
  6. data/bin/cucumber +17 -0
  7. data/config/hoe.rb +76 -0
  8. data/config/requirements.rb +15 -0
  9. data/cucumber.yml +2 -0
  10. data/examples/cs/README.textile +1 -0
  11. data/examples/cs/Rakefile +12 -0
  12. data/examples/cs/compile.bat +1 -0
  13. data/examples/cs/features/addition.feature +16 -0
  14. data/examples/cs/features/step_definitons/calculator_steps.rb +19 -0
  15. data/examples/cs/src/demo/Calculator.cs +20 -0
  16. data/examples/dos_line_endings/Rakefile +6 -0
  17. data/examples/dos_line_endings/features/dos_line_endings.feature +9 -0
  18. data/examples/i18n/README.textile +18 -0
  19. data/examples/i18n/Rakefile +30 -0
  20. data/examples/i18n/ar/Rakefile +6 -0
  21. data/examples/i18n/ar/features/addition.feature +17 -0
  22. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +24 -0
  23. data/examples/i18n/ar/lib/calculator.rb +11 -0
  24. data/examples/i18n/bg/Rakefile +6 -0
  25. data/examples/i18n/bg/features/addition.feature +12 -0
  26. data/examples/i18n/bg/features/consecutive_calculations.feature +19 -0
  27. data/examples/i18n/bg/features/division.feature +17 -0
  28. data/examples/i18n/bg/features/step_definitons/calculator_steps.rb +24 -0
  29. data/examples/i18n/bg/features/support/env.rb +6 -0
  30. data/examples/i18n/bg/features/support/world.rb +8 -0
  31. data/examples/i18n/bg/lib/calculator.rb +24 -0
  32. data/examples/i18n/cat/Rakefile +6 -0
  33. data/examples/i18n/cat/features/step_definitons/calculator_steps.rb +21 -0
  34. data/examples/i18n/cat/features/suma.feature +17 -0
  35. data/examples/i18n/cat/lib/calculadora.rb +16 -0
  36. data/examples/i18n/da/Rakefile +6 -0
  37. data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +24 -0
  38. data/examples/i18n/da/features/summering.feature +18 -0
  39. data/examples/i18n/da/lib/kalkulator.rb +11 -0
  40. data/examples/i18n/de/Rakefile +6 -0
  41. data/examples/i18n/de/features/addition.feature +17 -0
  42. data/examples/i18n/de/features/division.feature +10 -0
  43. data/examples/i18n/de/features/step_definitons/calculator_steps.rb +24 -0
  44. data/examples/i18n/de/lib/calculator.rb +14 -0
  45. data/examples/i18n/en/Rakefile +6 -0
  46. data/examples/i18n/en/features/addition.feature +17 -0
  47. data/examples/i18n/en/features/division.feature +10 -0
  48. data/examples/i18n/en/features/step_definitons/calculator_steps.rb +24 -0
  49. data/examples/i18n/en/lib/calculator.rb +14 -0
  50. data/examples/i18n/en-lol/Rakefile +6 -0
  51. data/examples/i18n/en-lol/features/step_definitions/cucumbrz_steps.rb +16 -0
  52. data/examples/i18n/en-lol/features/stuffing.feature +8 -0
  53. data/examples/i18n/en-lol/features/support/env.rb +8 -0
  54. data/examples/i18n/en-lol/lib/basket.rb +12 -0
  55. data/examples/i18n/en-lol/lib/belly.rb +11 -0
  56. data/examples/i18n/es/Rakefile +6 -0
  57. data/examples/i18n/es/features/adicion.feature +17 -0
  58. data/examples/i18n/es/features/step_definitons/calculador_steps.rb +21 -0
  59. data/examples/i18n/es/lib/calculador.rb +14 -0
  60. data/examples/i18n/et/Rakefile +6 -0
  61. data/examples/i18n/et/features/jagamine.feature +10 -0
  62. data/examples/i18n/et/features/liitmine.feature +17 -0
  63. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +24 -0
  64. data/examples/i18n/et/lib/kalkulaator.rb +14 -0
  65. data/examples/i18n/fi/Rakefile +6 -0
  66. data/examples/i18n/fi/features/jakolasku.feature +10 -0
  67. data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +24 -0
  68. data/examples/i18n/fi/features/yhteenlasku.feature +16 -0
  69. data/examples/i18n/fi/lib/laskin.rb +14 -0
  70. data/examples/i18n/fr/Rakefile +6 -0
  71. data/examples/i18n/fr/features/addition.feature +18 -0
  72. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +25 -0
  73. data/examples/i18n/fr/lib/calculatrice.rb +10 -0
  74. data/examples/i18n/he/Rakefile +6 -0
  75. data/examples/i18n/he/features/addition.feature +17 -0
  76. data/examples/i18n/he/features/division.feature +10 -0
  77. data/examples/i18n/he/features/step_definitons/calculator_steps.rb +24 -0
  78. data/examples/i18n/he/lib/calculator.rb +14 -0
  79. data/examples/i18n/hu/Rakefile +6 -0
  80. data/examples/i18n/hu/features/addition.feature +17 -0
  81. data/examples/i18n/hu/features/division.feature +10 -0
  82. data/examples/i18n/hu/features/step_definitons/calculator_steps.rb +25 -0
  83. data/examples/i18n/hu/lib/calculator.rb +14 -0
  84. data/examples/i18n/id/Rakefile +6 -0
  85. data/examples/i18n/id/features/addition.feature +17 -0
  86. data/examples/i18n/id/features/division.feature +10 -0
  87. data/examples/i18n/id/features/step_definitons/calculator_steps.rb +24 -0
  88. data/examples/i18n/id/lib/calculator.rb +14 -0
  89. data/examples/i18n/it/Rakefile +6 -0
  90. data/examples/i18n/it/features/somma.feature +11 -0
  91. data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +24 -0
  92. data/examples/i18n/it/lib/calcolatrice.rb +11 -0
  93. data/examples/i18n/ja/Rakefile +6 -0
  94. data/examples/i18n/ja/features/addition.feature +17 -0
  95. data/examples/i18n/ja/features/division.feature +10 -0
  96. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +24 -0
  97. data/examples/i18n/ja/lib/calculator.rb +14 -0
  98. data/examples/i18n/ko/Rakefile +6 -0
  99. data/examples/i18n/ko/features/addition.feature +17 -0
  100. data/examples/i18n/ko/features/division.feature +11 -0
  101. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +24 -0
  102. data/examples/i18n/ko/lib/calculator.rb +14 -0
  103. data/examples/i18n/lt/Rakefile +6 -0
  104. data/examples/i18n/lt/features/addition.feature +17 -0
  105. data/examples/i18n/lt/features/division.feature +10 -0
  106. data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +24 -0
  107. data/examples/i18n/lt/lib/calculator.rb +14 -0
  108. data/examples/i18n/lv/Rakefile +6 -0
  109. data/examples/i18n/lv/features/addition.feature +17 -0
  110. data/examples/i18n/lv/features/division.feature +10 -0
  111. data/examples/i18n/lv/features/step_definitons/calculator_steps.rb +24 -0
  112. data/examples/i18n/lv/lib/calculator.rb +14 -0
  113. data/examples/i18n/no/Rakefile +6 -0
  114. data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +17 -0
  115. data/examples/i18n/no/features/summering.feature +19 -0
  116. data/examples/i18n/no/features/support/env.rb +6 -0
  117. data/examples/i18n/no/lib/kalkulator.rb +11 -0
  118. data/examples/i18n/pl/Rakefile +6 -0
  119. data/examples/i18n/pl/features/addition.feature +17 -0
  120. data/examples/i18n/pl/features/division.feature +10 -0
  121. data/examples/i18n/pl/features/step_definitons/calculator_steps.rb +24 -0
  122. data/examples/i18n/pl/features/support/env.rb +6 -0
  123. data/examples/i18n/pl/lib/calculator.rb +14 -0
  124. data/examples/i18n/pt/Rakefile +6 -0
  125. data/examples/i18n/pt/features/adicao.feature +11 -0
  126. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +20 -0
  127. data/examples/i18n/pt/features/support/env.rb +6 -0
  128. data/examples/i18n/pt/lib/calculadora.rb +10 -0
  129. data/examples/i18n/ro/Rakefile +6 -0
  130. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +24 -0
  131. data/examples/i18n/ro/features/suma.feature +11 -0
  132. data/examples/i18n/ro/lib/calculator.rb +11 -0
  133. data/examples/i18n/ru/Rakefile +6 -0
  134. data/examples/i18n/ru/features/addition.feature +11 -0
  135. data/examples/i18n/ru/features/consecutive_calculations.feature +17 -0
  136. data/examples/i18n/ru/features/division.feature +16 -0
  137. data/examples/i18n/ru/features/step_definitons/calculator_steps.rb +19 -0
  138. data/examples/i18n/ru/features/support/env.rb +6 -0
  139. data/examples/i18n/ru/features/support/world.rb +8 -0
  140. data/examples/i18n/ru/lib/calculator.rb +24 -0
  141. data/examples/i18n/se/Rakefile +6 -0
  142. data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +24 -0
  143. data/examples/i18n/se/features/summering.feature +18 -0
  144. data/examples/i18n/se/lib/kalkulator.rb +11 -0
  145. data/examples/i18n/sk/Rakefile +6 -0
  146. data/examples/i18n/sk/features/addition.feature +17 -0
  147. data/examples/i18n/sk/features/division.feature +10 -0
  148. data/examples/i18n/sk/features/step_definitons/calculator_steps.rb +24 -0
  149. data/examples/i18n/sk/lib/calculator.rb +14 -0
  150. data/examples/i18n/zh-CN/Rakefile +6 -0
  151. data/examples/i18n/zh-CN/features/addition.feature +18 -0
  152. data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +26 -0
  153. data/examples/i18n/zh-CN/lib/calculator.rb +10 -0
  154. data/examples/i18n/zh-TW/Rakefile +6 -0
  155. data/examples/i18n/zh-TW/features/addition.feature +17 -0
  156. data/examples/i18n/zh-TW/features/division.feature +11 -0
  157. data/examples/i18n/zh-TW/features/step_definitons/calculator_steps.rb +24 -0
  158. data/examples/i18n/zh-TW/lib/calculator.rb +14 -0
  159. data/examples/java/README.textile +18 -0
  160. data/examples/java/build.xml +33 -0
  161. data/examples/java/features/hello.feature +11 -0
  162. data/examples/java/features/step_definitons/hello_steps.rb +23 -0
  163. data/examples/java/features/step_definitons/tree_steps.rb +14 -0
  164. data/examples/java/features/tree.feature +9 -0
  165. data/examples/java/src/cucumber/demo/Hello.java +16 -0
  166. data/examples/junit/features/one_passing_one_failing.feature +8 -0
  167. data/examples/junit/features/pending.feature +5 -0
  168. data/examples/junit/features/step_definitions/steps.rb +11 -0
  169. data/examples/pure_java/README.textile +5 -0
  170. data/examples/selenium/Rakefile +6 -0
  171. data/examples/selenium/features/search.feature +9 -0
  172. data/examples/selenium/features/step_definitons/search_steps.rb +13 -0
  173. data/examples/selenium/features/support/env.rb +19 -0
  174. data/examples/selenium_webrat/Rakefile +6 -0
  175. data/examples/selenium_webrat/config.ru +0 -0
  176. data/examples/selenium_webrat/features/search.feature +9 -0
  177. data/examples/selenium_webrat/features/step_definitons/search_steps.rb +13 -0
  178. data/examples/selenium_webrat/features/support/env.rb +45 -0
  179. data/examples/self_test/README.textile +6 -0
  180. data/examples/self_test/Rakefile +6 -0
  181. data/examples/self_test/features/background/background_tagged_before_on_outline.feature +12 -0
  182. data/examples/self_test/features/background/background_with_name.feature +7 -0
  183. data/examples/self_test/features/background/failing_background.feature +12 -0
  184. data/examples/self_test/features/background/failing_background_after_success.feature +11 -0
  185. data/examples/self_test/features/background/multiline_args_background.feature +32 -0
  186. data/examples/self_test/features/background/passing_background.feature +10 -0
  187. data/examples/self_test/features/background/pending_background.feature +10 -0
  188. data/examples/self_test/features/background/scenario_outline_failing_background.feature +16 -0
  189. data/examples/self_test/features/background/scenario_outline_passing_background.feature +16 -0
  190. data/examples/self_test/features/call_undefined_step_from_step_def.feature +7 -0
  191. data/examples/self_test/features/failing_expectation.feature +4 -0
  192. data/examples/self_test/features/lots_of_undefined.feature +8 -0
  193. data/examples/self_test/features/multiline_name.feature +27 -0
  194. data/examples/self_test/features/outline_sample.feature +15 -0
  195. data/examples/self_test/features/sample.feature +21 -0
  196. data/examples/self_test/features/search_sample.feature +32 -0
  197. data/examples/self_test/features/step_definitions/sample_steps.rb +81 -0
  198. data/examples/self_test/features/support/env.rb +17 -0
  199. data/examples/self_test/features/tons_of_cukes.feature +52 -0
  200. data/examples/self_test/features/undefined_multiline_args.feature +12 -0
  201. data/examples/sinatra/Rakefile +6 -0
  202. data/examples/sinatra/app.rb +14 -0
  203. data/examples/sinatra/features/add.feature +11 -0
  204. data/examples/sinatra/features/step_definitions/add_steps.rb +15 -0
  205. data/examples/sinatra/features/support/env.rb +28 -0
  206. data/examples/sinatra/views/add.erb +5 -0
  207. data/examples/sinatra/views/layout.erb +8 -0
  208. data/examples/steps_library/features/step_definitions/steps_lib1.rb +8 -0
  209. data/examples/steps_library/features/step_definitions/steps_lib2.rb +8 -0
  210. data/examples/test_unit/Rakefile +6 -0
  211. data/examples/test_unit/features/step_definitions/test_unit_steps.rb +23 -0
  212. data/examples/test_unit/features/test_unit.feature +9 -0
  213. data/examples/tickets/Rakefile +16 -0
  214. data/examples/tickets/features/172.feature +28 -0
  215. data/examples/tickets/features/177/1.feature +29 -0
  216. data/examples/tickets/features/177/2.feature +21 -0
  217. data/examples/tickets/features/177/3.feature +18 -0
  218. data/examples/tickets/features/180.feature +7 -0
  219. data/examples/tickets/features/229/tagged_hooks.feature +8 -0
  220. data/examples/tickets/features/229/tagged_hooks.rb +14 -0
  221. data/examples/tickets/features/236.feature +13 -0
  222. data/examples/tickets/features/241.feature +13 -0
  223. data/examples/tickets/features/246.feature +4 -0
  224. data/examples/tickets/features/248.feature +11 -0
  225. data/examples/tickets/features/270/back.feature +14 -0
  226. data/examples/tickets/features/270/back.steps.rb +14 -0
  227. data/examples/tickets/features/272/hooks.feature +26 -0
  228. data/examples/tickets/features/272/hooks_steps.rb +53 -0
  229. data/examples/tickets/features/279/py_string_indent.feature +25 -0
  230. data/examples/tickets/features/279/py_string_indent.steps.rb +12 -0
  231. data/examples/tickets/features/279/wrong.feature_ +11 -0
  232. data/examples/tickets/features/301/filter_background_tagged_hooks.feature +6 -0
  233. data/examples/tickets/features/301/filter_background_tagged_hooks_steps.rb +12 -0
  234. data/examples/tickets/features/306/only_background.feature +4 -0
  235. data/examples/tickets/features/lib/eatting_machine.rb +18 -0
  236. data/examples/tickets/features/lib/pantry.rb +20 -0
  237. data/examples/tickets/features/scenario_outline.feature +95 -0
  238. data/examples/tickets/features/step_definitons/246_steps.rb +3 -0
  239. data/examples/tickets/features/step_definitons/248_steps.rb +15 -0
  240. data/examples/tickets/features/step_definitons/scenario_outline_steps.rb +42 -0
  241. data/examples/tickets/features/step_definitons/tickets_steps.rb +66 -0
  242. data/examples/tickets/features/tickets.feature +28 -0
  243. data/examples/watir/README.textile +16 -0
  244. data/examples/watir/Rakefile +6 -0
  245. data/examples/watir/features/search.feature +12 -0
  246. data/examples/watir/features/step_definitons/search_steps.rb +22 -0
  247. data/examples/watir/features/support/env.rb +32 -0
  248. data/features/after_block_exceptions.feature +102 -0
  249. data/features/after_step_block_exceptions.feature +104 -0
  250. data/features/background.feature +311 -0
  251. data/features/bug_371.feature +32 -0
  252. data/features/cucumber_cli.feature +549 -0
  253. data/features/cucumber_cli_diff_disabled.feature +53 -0
  254. data/features/cucumber_cli_outlines.feature +109 -0
  255. data/features/custom_formatter.feature +11 -0
  256. data/features/drb_server_integration.feature +115 -0
  257. data/features/exclude_files.feature +20 -0
  258. data/features/expand.feature +49 -0
  259. data/features/html_formatter/a.html +185 -0
  260. data/features/html_formatter.feature +7 -0
  261. data/features/junit_formatter.feature +71 -0
  262. data/features/language_from_header.feature +30 -0
  263. data/features/multiline_names.feature +43 -0
  264. data/features/rake_task.feature +150 -0
  265. data/features/report_called_undefined_steps.feature +35 -0
  266. data/features/snippet.feature +22 -0
  267. data/features/step_definitions/cucumber_steps.rb +130 -0
  268. data/features/step_definitions/extra_steps.rb +2 -0
  269. data/features/steps_formatter.feature +25 -0
  270. data/features/support/env.rb +120 -0
  271. data/features/usage.feature +126 -0
  272. data/features/work_in_progress.feature +151 -0
  273. data/gem_tasks/deployment.rake +11 -0
  274. data/gem_tasks/environment.rake +7 -0
  275. data/gem_tasks/features.rake +10 -0
  276. data/gem_tasks/fix_cr_lf.rake +10 -0
  277. data/gem_tasks/flog.rake +4 -0
  278. data/gem_tasks/gemspec.rake +10 -0
  279. data/gem_tasks/rspec.rake +45 -0
  280. data/gem_tasks/sass.rake +4 -0
  281. data/gem_tasks/yard.rake +8 -0
  282. data/lib/autotest/cucumber.rb +6 -0
  283. data/lib/autotest/cucumber_mixin.rb +125 -0
  284. data/lib/autotest/cucumber_rails.rb +6 -0
  285. data/lib/autotest/cucumber_rails_rspec.rb +6 -0
  286. data/lib/autotest/cucumber_rspec.rb +6 -0
  287. data/lib/autotest/discover.rb +9 -0
  288. data/lib/cucumber/ast/background.rb +62 -0
  289. data/lib/cucumber/ast/comment.rb +30 -0
  290. data/lib/cucumber/ast/examples.rb +26 -0
  291. data/lib/cucumber/ast/feature.rb +58 -0
  292. data/lib/cucumber/ast/feature_element.rb +57 -0
  293. data/lib/cucumber/ast/features.rb +30 -0
  294. data/lib/cucumber/ast/outline_table.rb +143 -0
  295. data/lib/cucumber/ast/py_string.rb +57 -0
  296. data/lib/cucumber/ast/scenario.rb +83 -0
  297. data/lib/cucumber/ast/scenario_outline.rb +93 -0
  298. data/lib/cucumber/ast/step.rb +112 -0
  299. data/lib/cucumber/ast/step_collection.rb +75 -0
  300. data/lib/cucumber/ast/step_invocation.rb +136 -0
  301. data/lib/cucumber/ast/table.rb +334 -0
  302. data/lib/cucumber/ast/tags.rb +33 -0
  303. data/lib/cucumber/ast/visitor.rb +116 -0
  304. data/lib/cucumber/ast.rb +29 -0
  305. data/lib/cucumber/broadcaster.rb +13 -0
  306. data/lib/cucumber/cli/configuration.rb +427 -0
  307. data/lib/cucumber/cli/drb_client.rb +20 -0
  308. data/lib/cucumber/cli/language_help_formatter.rb +59 -0
  309. data/lib/cucumber/cli/main.rb +136 -0
  310. data/lib/cucumber/core_ext/exception.rb +53 -0
  311. data/lib/cucumber/core_ext/instance_exec.rb +67 -0
  312. data/lib/cucumber/core_ext/proc.rb +29 -0
  313. data/lib/cucumber/core_ext/string.rb +48 -0
  314. data/lib/cucumber/feature_file.rb +47 -0
  315. data/lib/cucumber/filter.rb +50 -0
  316. data/lib/cucumber/formatter/ansicolor.rb +110 -0
  317. data/lib/cucumber/formatter/color_io.rb +23 -0
  318. data/lib/cucumber/formatter/console.rb +149 -0
  319. data/lib/cucumber/formatter/cucumber.css +132 -0
  320. data/lib/cucumber/formatter/cucumber.sass +139 -0
  321. data/lib/cucumber/formatter/duration.rb +10 -0
  322. data/lib/cucumber/formatter/html.rb +258 -0
  323. data/lib/cucumber/formatter/junit.rb +75 -0
  324. data/lib/cucumber/formatter/pretty.rb +188 -0
  325. data/lib/cucumber/formatter/profile.rb +77 -0
  326. data/lib/cucumber/formatter/progress.rb +60 -0
  327. data/lib/cucumber/formatter/rerun.rb +44 -0
  328. data/lib/cucumber/formatter/steps.rb +49 -0
  329. data/lib/cucumber/formatter/tag_cloud.rb +28 -0
  330. data/lib/cucumber/formatter/unicode.rb +35 -0
  331. data/lib/cucumber/formatter/usage.rb +85 -0
  332. data/lib/cucumber/formatters/unicode.rb +7 -0
  333. data/lib/cucumber/languages.yml +532 -0
  334. data/lib/cucumber/parser/feature.rb +1787 -0
  335. data/lib/cucumber/parser/feature.tt +324 -0
  336. data/lib/cucumber/parser/i18n/language.rb +80 -0
  337. data/lib/cucumber/parser/i18n.tt +42 -0
  338. data/lib/cucumber/parser/table.rb +414 -0
  339. data/lib/cucumber/parser/table.tt +71 -0
  340. data/lib/cucumber/parser/treetop_ext.rb +52 -0
  341. data/lib/cucumber/parser.rb +6 -0
  342. data/lib/cucumber/platform.rb +23 -0
  343. data/lib/cucumber/rails/rspec.rb +10 -0
  344. data/lib/cucumber/rails/world.rb +99 -0
  345. data/lib/cucumber/rake/task.rb +233 -0
  346. data/lib/cucumber/rspec_neuter.rb +23 -0
  347. data/lib/cucumber/step_definition.rb +122 -0
  348. data/lib/cucumber/step_match.rb +61 -0
  349. data/lib/cucumber/step_mother.rb +362 -0
  350. data/lib/cucumber/version.rb +10 -0
  351. data/lib/cucumber/world.rb +53 -0
  352. data/lib/cucumber.rb +11 -0
  353. data/rails_generators/cucumber/USAGE +11 -0
  354. data/rails_generators/cucumber/cucumber_generator.rb +66 -0
  355. data/rails_generators/cucumber/templates/cucumber +8 -0
  356. data/rails_generators/cucumber/templates/cucumber.rake +20 -0
  357. data/rails_generators/cucumber/templates/cucumber_environment.rb +23 -0
  358. data/rails_generators/cucumber/templates/env.rb +26 -0
  359. data/rails_generators/cucumber/templates/paths.rb +27 -0
  360. data/rails_generators/cucumber/templates/spork_env.rb +36 -0
  361. data/rails_generators/cucumber/templates/webrat_steps.rb +147 -0
  362. data/rails_generators/feature/USAGE +12 -0
  363. data/rails_generators/feature/feature_generator.rb +40 -0
  364. data/rails_generators/feature/templates/feature.erb +31 -0
  365. data/rails_generators/feature/templates/steps.erb +20 -0
  366. data/spec/cucumber/ast/background_spec.rb +50 -0
  367. data/spec/cucumber/ast/feature_element_spec.rb +40 -0
  368. data/spec/cucumber/ast/feature_factory.rb +63 -0
  369. data/spec/cucumber/ast/feature_spec.rb +38 -0
  370. data/spec/cucumber/ast/py_string_spec.rb +51 -0
  371. data/spec/cucumber/ast/scenario_outline_spec.rb +67 -0
  372. data/spec/cucumber/ast/scenario_spec.rb +38 -0
  373. data/spec/cucumber/ast/step_collection_spec.rb +17 -0
  374. data/spec/cucumber/ast/step_spec.rb +66 -0
  375. data/spec/cucumber/ast/table_spec.rb +186 -0
  376. data/spec/cucumber/ast/visitor_spec.rb +27 -0
  377. data/spec/cucumber/broadcaster_spec.rb +15 -0
  378. data/spec/cucumber/cli/configuration_spec.rb +396 -0
  379. data/spec/cucumber/cli/drb_client_spec.rb +43 -0
  380. data/spec/cucumber/cli/main_spec.rb +140 -0
  381. data/spec/cucumber/core_ext/proc_spec.rb +54 -0
  382. data/spec/cucumber/core_ext/string_spec.rb +42 -0
  383. data/spec/cucumber/formatter/ansicolor_spec.rb +35 -0
  384. data/spec/cucumber/formatter/color_io_spec.rb +27 -0
  385. data/spec/cucumber/formatter/duration_spec.rb +22 -0
  386. data/spec/cucumber/formatter/progress_spec.rb +36 -0
  387. data/spec/cucumber/parser/feature_parser_spec.rb +387 -0
  388. data/spec/cucumber/parser/table_parser_spec.rb +48 -0
  389. data/spec/cucumber/rails/stubs/mini_rails.rb +18 -0
  390. data/spec/cucumber/rails/stubs/test_help.rb +1 -0
  391. data/spec/cucumber/rails/world_spec.rb +11 -0
  392. data/spec/cucumber/sell_cucumbers.feature +19 -0
  393. data/spec/cucumber/step_definition_spec.rb +101 -0
  394. data/spec/cucumber/step_mother_spec.rb +155 -0
  395. data/spec/cucumber/treetop_parser/empty_feature.feature +4 -0
  396. data/spec/cucumber/treetop_parser/empty_scenario.feature +9 -0
  397. data/spec/cucumber/treetop_parser/empty_scenario_outline.feature +3 -0
  398. data/spec/cucumber/treetop_parser/fit_scenario.feature +8 -0
  399. data/spec/cucumber/treetop_parser/given_scenario.feature +9 -0
  400. data/spec/cucumber/treetop_parser/invalid_scenario_outlines.feature +7 -0
  401. data/spec/cucumber/treetop_parser/multiline_steps.feature +17 -0
  402. data/spec/cucumber/treetop_parser/multiple_tables.feature +27 -0
  403. data/spec/cucumber/treetop_parser/scenario_outline.feature +16 -0
  404. data/spec/cucumber/treetop_parser/spaces.feature +12 -0
  405. data/spec/cucumber/treetop_parser/test_dos.feature +25 -0
  406. data/spec/cucumber/treetop_parser/with_comments.feature +10 -0
  407. data/spec/cucumber/treetop_parser/with_tags.feature +18 -0
  408. data/spec/cucumber/world/pending_spec.rb +47 -0
  409. data/spec/spec.opts +2 -0
  410. data/spec/spec_helper.rb +13 -0
  411. metadata +506 -0
@@ -0,0 +1,427 @@
1
+ module Cucumber
2
+ module Cli
3
+ class YmlLoadError < StandardError; end
4
+
5
+ class Configuration
6
+ BUILTIN_FORMATS = {
7
+ 'html' => 'Cucumber::Formatter::Html',
8
+ 'pretty' => 'Cucumber::Formatter::Pretty',
9
+ 'profile' => 'Cucumber::Formatter::Profile',
10
+ 'progress' => 'Cucumber::Formatter::Progress',
11
+ 'rerun' => 'Cucumber::Formatter::Rerun',
12
+ 'usage' => 'Cucumber::Formatter::Usage',
13
+ 'junit' => 'Cucumber::Formatter::Junit',
14
+ 'tag_cloud' => 'Cucumber::Formatter::TagCloud',
15
+ 'steps' => 'Cucumber::Formatter::Steps'
16
+ }
17
+ DRB_FLAG = '--drb'
18
+ PROFILE_SHORT_FLAG = '-p'
19
+ PROFILE_LONG_FLAG = '--profile'
20
+
21
+ attr_reader :paths
22
+ attr_reader :options
23
+
24
+ def initialize(out_stream = STDOUT, error_stream = STDERR)
25
+ @out_stream = out_stream
26
+ @error_stream = error_stream
27
+
28
+ @paths = []
29
+ @options = default_options
30
+ end
31
+
32
+ def parse!(args)
33
+ args.concat(%w{--profile default}) if args.empty?
34
+ @args = args
35
+ expand_profiles_into_args
36
+ return if parse_drb
37
+
38
+ @args.each do |arg|
39
+ if arg =~ /^(\w+)=(.*)$/
40
+ ENV[$1] = $2
41
+ @args.delete(arg)
42
+ end
43
+ end
44
+
45
+ @args.extend(::OptionParser::Arguable)
46
+
47
+ @args.options do |opts|
48
+ opts.banner = ["Usage: cucumber [options] [ [FILE|DIR|URL][:LINE[:LINE]*] ]+", "",
49
+ "Examples:",
50
+ "cucumber examples/i18n/en/features",
51
+ "cucumber --language it examples/i18n/it/features/somma.feature:6:98:113",
52
+ "cucumber -s -i http://rubyurl.com/eeCl", "", "",
53
+ ].join("\n")
54
+ opts.on("-r LIBRARY|DIR", "--require LIBRARY|DIR",
55
+ "Require files before executing the features. If this",
56
+ "option is not specified, all *.rb files that are",
57
+ "siblings or below the features will be loaded auto-",
58
+ "matically. Automatic loading is disabled when this",
59
+ "option is specified, and all loading becomes explicit.",
60
+ "Files under directories named \"support\" are always",
61
+ "loaded first.",
62
+ "This option can be specified multiple times.") do |v|
63
+ @options[:require] ||= []
64
+ @options[:require] << v
65
+ end
66
+ opts.on("-l LANG", "--language LANG",
67
+ "Specify language for features (Default: #{@options[:lang]})",
68
+ %{Run with "--language help" to see all languages},
69
+ %{Run with "--language LANG help" to list keywords for LANG}) do |v|
70
+ if v == 'help'
71
+ list_languages_and_exit
72
+ elsif args==['help']
73
+ list_keywords_and_exit(v)
74
+ else
75
+ @options[:lang] = v
76
+ end
77
+ end
78
+ opts.on("-f FORMAT", "--format FORMAT",
79
+ "How to format features (Default: pretty)",
80
+ "Available formats: #{BUILTIN_FORMATS.keys.sort.join(", ")}",
81
+ "FORMAT can also be the fully qualified class name of",
82
+ "your own custom formatter. If the class isn't loaded,",
83
+ "Cucumber will attempt to require a file with a relative",
84
+ "file name that is the underscore name of the class name.",
85
+ "Example: --format Foo::BarZap -> Cucumber will look for",
86
+ "foo/bar_zap.rb. You can place the file with this relative",
87
+ "path underneath your features/support directory or anywhere",
88
+ "on Ruby's LOAD_PATH, for example in a Ruby gem.") do |v|
89
+ @options[:formats] << [v, @out_stream]
90
+ @active_format = v
91
+ end
92
+ opts.on("-o", "--out [FILE|DIR]",
93
+ "Write output to a file/directory instead of STDOUT. This option",
94
+ "applies to the previously specified --format, or the",
95
+ "default format if no format is specified. Check the specific",
96
+ "formatter's docs to see whether to pass a file or a dir.") do |v|
97
+ @options[:formats] << ['pretty', nil] if @options[:formats].empty?
98
+ @options[:formats][-1][1] = v
99
+ end
100
+ opts.on("-t TAGS", "--tags TAGS",
101
+ "Only execute the features or scenarios with the specified tags.",
102
+ "TAGS must be comma-separated without spaces. Prefix tags with ~ to",
103
+ "exclude features or scenarios having that tag. Tags can be specified",
104
+ "with or without the @ prefix.") do |v|
105
+ include_tags, exclude_tags = *parse_tags(v)
106
+ @options[:include_tags] += include_tags
107
+ @options[:exclude_tags] += exclude_tags
108
+ end
109
+ opts.on("-n NAME", "--name NAME",
110
+ "Only execute the feature elements which match part of the given name.",
111
+ "If this option is given more than once, it will match against all the",
112
+ "given names.") do |v|
113
+ @options[:name_regexps] << /#{v}/
114
+ end
115
+ opts.on("-e", "--exclude PATTERN", "Don't run feature files or require ruby files matching PATTERN") do |v|
116
+ @options[:excludes] << Regexp.new(v)
117
+ end
118
+ opts.on(PROFILE_SHORT_FLAG, "#{PROFILE_LONG_FLAG} PROFILE", "Pull commandline arguments from cucumber.yml.") do |v|
119
+ # Processing of this is done previsouly so that the DRb flag can be detected within profiles.
120
+ end
121
+ opts.on("-c", "--[no-]color",
122
+ "Whether or not to use ANSI color in the output. Cucumber decides",
123
+ "based on your platform and the output destination if not specified.") do |v|
124
+ Term::ANSIColor.coloring = v
125
+ end
126
+ opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.",
127
+ "This also omits the loading of your support/env.rb file if it exists.",
128
+ "Implies --quiet.") do
129
+ @options[:dry_run] = true
130
+ @quiet = true
131
+ end
132
+ opts.on("-a", "--autoformat DIRECTORY",
133
+ "Reformats (pretty prints) feature files and write them to DIRECTORY.",
134
+ "Be careful if you choose to overwrite the originals.",
135
+ "Implies --dry-run --formatter pretty.") do |directory|
136
+ @options[:autoformat] = directory
137
+ Term::ANSIColor.coloring = false
138
+ @options[:dry_run] = true
139
+ @quiet = true
140
+ end
141
+ opts.on("-m", "--no-multiline",
142
+ "Don't print multiline strings and tables under steps.") do
143
+ @options[:no_multiline] = true
144
+ end
145
+ opts.on("-s", "--no-source",
146
+ "Don't print the file and line of the step definition with the steps.") do
147
+ @options[:source] = false
148
+ end
149
+ opts.on("-i", "--no-snippets", "Don't print snippets for pending steps.") do
150
+ @options[:snippets] = false
151
+ end
152
+ opts.on("-q", "--quiet", "Alias for --no-snippets --no-source.") do
153
+ @quiet = true
154
+ end
155
+ opts.on("-b", "--backtrace", "Show full backtrace for all errors.") do
156
+ Exception.cucumber_full_backtrace = true
157
+ end
158
+ opts.on("-S", "--strict", "Fail if there are any undefined steps.") do
159
+ @options[:strict] = true
160
+ end
161
+ opts.on("-w", "--wip", "Fail if there are any passing scenarios.") do
162
+ @options[:wip] = true
163
+ end
164
+ opts.on("-v", "--verbose", "Show the files and features loaded.") do
165
+ @options[:verbose] = true
166
+ end
167
+ opts.on("-g", "--guess", "Guess best match for Ambiguous steps.") do
168
+ @options[:guess] = true
169
+ end
170
+ opts.on("-x", "--expand", "Expand Scenario Outline Tables in output.") do
171
+ @options[:expand] = true
172
+ end
173
+ opts.on("--no-diff", "Disable diff output on failing expectations.") do
174
+ @options[:diff_enabled] = false
175
+ end
176
+ opts.on(DRB_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do
177
+ # Processing of this is done previsouly in order to short circuit args from being lost.
178
+ end
179
+ opts.on_tail("--version", "Show version.") do
180
+ @out_stream.puts VERSION::STRING
181
+ Kernel.exit
182
+ end
183
+ opts.on_tail("-h", "--help", "You're looking at it.") do
184
+ @out_stream.puts opts.help
185
+ Kernel.exit
186
+ end
187
+ end.parse!
188
+
189
+ arrange_formats
190
+
191
+ @options[:snippets] = true if !@quiet && @options[:snippets].nil?
192
+ @options[:source] = true if !@quiet && @options[:source].nil?
193
+
194
+ raise("You can't use both --strict and --wip") if @options[:strict] && @options[:wip]
195
+
196
+ # Whatever is left after option parsing is the FILE arguments
197
+ @paths += @args
198
+ end
199
+
200
+ def verbose?
201
+ @options[:verbose]
202
+ end
203
+
204
+ def strict?
205
+ @options[:strict]
206
+ end
207
+
208
+ def wip?
209
+ @options[:wip]
210
+ end
211
+
212
+ def guess?
213
+ @options[:guess]
214
+ end
215
+
216
+ def diff_enabled?
217
+ @options[:diff_enabled]
218
+ end
219
+
220
+ def drb?
221
+ @drb
222
+ end
223
+
224
+ def parse_tags(tag_string)
225
+ tag_names = tag_string.split(",")
226
+ excludes, includes = tag_names.partition{|tag| tag =~ /^~/}
227
+ excludes = excludes.map{|tag| tag[1..-1]}
228
+
229
+ # Strip @
230
+ includes = includes.map{|tag| Ast::Tags.strip_prefix(tag)}
231
+ excludes = excludes.map{|tag| Ast::Tags.strip_prefix(tag)}
232
+ [includes, excludes]
233
+ end
234
+
235
+ def build_formatter_broadcaster(step_mother)
236
+ return Formatter::Pretty.new(step_mother, nil, @options) if @options[:autoformat]
237
+ formatters = @options[:formats].map do |format_and_out|
238
+ format = format_and_out[0]
239
+ out = format_and_out[1]
240
+ if String === out # file name
241
+ unless File.directory?(out)
242
+ out = File.open(out, Cucumber.file_mode('w'))
243
+ at_exit do
244
+ out.flush
245
+ out.close
246
+ end
247
+ end
248
+ end
249
+
250
+ begin
251
+ formatter_class = formatter_class(format)
252
+ formatter_class.new(step_mother, out, @options)
253
+ rescue Exception => e
254
+ e.message << "\nError creating formatter: #{format}"
255
+ raise e
256
+ end
257
+ end
258
+
259
+ broadcaster = Broadcaster.new(formatters)
260
+ broadcaster.options = @options
261
+ return broadcaster
262
+ end
263
+
264
+ def formatter_class(format)
265
+ if(builtin = BUILTIN_FORMATS[format])
266
+ constantize(builtin)
267
+ else
268
+ constantize(format)
269
+ end
270
+ end
271
+
272
+ def files_to_require
273
+ requires = @options[:require] || feature_dirs
274
+ files = requires.map do |path|
275
+ path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
276
+ path = path.gsub(/\/$/, '') # Strip trailing slash.
277
+ File.directory?(path) ? Dir["#{path}/**/*.rb"] : path
278
+ end.flatten.uniq
279
+ sorted_files = files.sort { |a,b| (b =~ %r{/support/} || -1) <=> (a =~ %r{/support/} || -1) }.reject{|f| f =~ /^http/}
280
+ env_files = sorted_files.select {|f| f =~ %r{/support/env.rb} }
281
+ files = env_files + sorted_files.reject {|f| f =~ %r{/support/env.rb} }
282
+ remove_excluded_files_from(files)
283
+ files.reject! {|f| f =~ %r{/support/env.rb} } if @options[:dry_run]
284
+ files
285
+ end
286
+
287
+ def feature_files
288
+ potential_feature_files = @paths.map do |path|
289
+ path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
290
+ path = path.chomp('/')
291
+ File.directory?(path) ? Dir["#{path}/**/*.feature"] : path
292
+ end.flatten.uniq
293
+ remove_excluded_files_from(potential_feature_files)
294
+ potential_feature_files
295
+ end
296
+
297
+ protected
298
+
299
+ def arrange_formats
300
+ @options[:formats] << ['pretty', @out_stream] if @options[:formats].empty?
301
+ @options[:formats] = @options[:formats].sort_by{|f| f[1] == @out_stream ? -1 : 1}
302
+ if @options[:formats].length > 1 && @options[:formats][1][1] == @out_stream
303
+ raise "All but one formatter must use --out, only one can print to STDOUT"
304
+ end
305
+ end
306
+
307
+ def remove_excluded_files_from(files)
308
+ files.reject! {|path| @options[:excludes].detect {|pattern| path =~ pattern } }
309
+ end
310
+
311
+ def feature_dirs
312
+ @paths.map { |f| File.directory?(f) ? f : File.dirname(f) }.uniq
313
+ end
314
+
315
+ def constantize(camel_cased_word)
316
+ begin
317
+ names = camel_cased_word.split('::')
318
+ names.shift if names.empty? || names.first.empty?
319
+
320
+ constant = Object
321
+ names.each do |name|
322
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
323
+ end
324
+ constant
325
+ rescue NameError
326
+ require underscore(camel_cased_word)
327
+ retry
328
+ end
329
+ end
330
+
331
+ # Snagged from active_support
332
+ def underscore(camel_cased_word)
333
+ camel_cased_word.to_s.gsub(/::/, '/').
334
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
335
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
336
+ tr("-", "_").
337
+ downcase
338
+ end
339
+
340
+ def expand_profiles_into_args
341
+ while (profile_index = @args.index(PROFILE_SHORT_FLAG) || @args.index(PROFILE_LONG_FLAG)) do
342
+ @args.delete_at(profile_index)
343
+ @args[profile_index] = args_from_profile(@args[profile_index])
344
+ @args.flatten!
345
+ end
346
+ end
347
+
348
+ def args_from_profile(profile)
349
+ unless cucumber_yml.has_key?(profile)
350
+ raise(<<-END_OF_ERROR)
351
+ Could not find profile: '#{profile}'
352
+
353
+ Defined profiles in cucumber.yml:
354
+ * #{cucumber_yml.keys.join("\n * ")}
355
+ END_OF_ERROR
356
+ end
357
+
358
+ args_from_yml = cucumber_yml[profile] || ''
359
+
360
+ case(args_from_yml)
361
+ when String
362
+ raise "The '#{profile}' profile in cucumber.yml was blank. Please define the command line arguments for the '#{profile}' profile in cucumber.yml.\n" if args_from_yml =~ /^\s*$/
363
+ args_from_yml = args_from_yml.split(' ')
364
+ when Array
365
+ raise "The '#{profile}' profile in cucumber.yml was empty. Please define the command line arguments for the '#{profile}' profile in cucumber.yml.\n" if args_from_yml.empty?
366
+ else
367
+ raise "The '#{profile}' profile in cucumber.yml was a #{args_from_yml.class}. It must be a String or Array"
368
+ end
369
+ args_from_yml
370
+ end
371
+
372
+ def cucumber_yml
373
+ return @cucumber_yml if @cucumber_yml
374
+ unless File.exist?('cucumber.yml')
375
+ raise(YmlLoadError,"cucumber.yml was not found. Please refer to cucumber's documentation on defining profiles in cucumber.yml. You must define a 'default' profile to use the cucumber command without any arguments.\nType 'cucumber --help' for usage.\n")
376
+ end
377
+
378
+ require 'yaml'
379
+ begin
380
+ @cucumber_yml = YAML::load(IO.read('cucumber.yml'))
381
+ rescue StandardError => e
382
+ raise(YmlLoadError,"cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentation on correct profile usage.\n")
383
+ end
384
+
385
+ if @cucumber_yml.nil? || !@cucumber_yml.is_a?(Hash)
386
+ raise(YmlLoadError,"cucumber.yml was found, but was blank or malformed. Please refer to cucumber's documentation on correct profile usage.\n")
387
+ end
388
+
389
+ return @cucumber_yml
390
+ end
391
+
392
+ # TODO: Move to Language
393
+ def list_keywords_and_exit(lang)
394
+ unless Cucumber::LANGUAGES[lang]
395
+ raise("No language with key #{lang}")
396
+ end
397
+ LanguageHelpFormatter.list_keywords(@out_stream, lang)
398
+ Kernel.exit
399
+ end
400
+
401
+ def list_languages_and_exit
402
+ LanguageHelpFormatter.list_languages(@out_stream)
403
+ Kernel.exit
404
+ end
405
+
406
+ def parse_drb
407
+ @drb = @args.delete(DRB_FLAG) ? true : false
408
+ end
409
+
410
+ def default_options
411
+ {
412
+ :strict => false,
413
+ :require => nil,
414
+ :lang => nil,
415
+ :dry_run => false,
416
+ :formats => [],
417
+ :excludes => [],
418
+ :include_tags => [],
419
+ :exclude_tags => [],
420
+ :name_regexps => [],
421
+ :diff_enabled => true
422
+ }
423
+ end
424
+ end
425
+
426
+ end
427
+ end
@@ -0,0 +1,20 @@
1
+ require "drb/drb"
2
+ # This code was taken from the RSpec project and slightly modified.
3
+
4
+ module Cucumber
5
+ module Cli
6
+ class DRbClientError < StandardError
7
+ end
8
+ # Runs features on a DRB server, originally created with Spork compatibility in mind.
9
+ class DRbClient
10
+ def self.run(args, error_stream, out_stream)
11
+ # See http://redmine.ruby-lang.org/issues/show/496 as to why we specify localhost:0
12
+ DRb.start_service("druby://localhost:0")
13
+ feature_server = DRbObject.new_with_uri("druby://127.0.0.1:8990")
14
+ feature_server.run(args, error_stream, out_stream)
15
+ rescue DRb::DRbConnError
16
+ raise DRbClientError, "No DRb server is running."
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,59 @@
1
+ require 'cucumber/formatter/pretty'
2
+
3
+ module Cucumber
4
+ module Cli
5
+ class LanguageHelpFormatter < Formatter::Pretty
6
+ INCOMPLETE = %{
7
+ The Cucumber grammar has evolved since this translation was written.
8
+ Please help us complete the translation by translating the missing words in
9
+
10
+ #{Cucumber::LANGUAGE_FILE}
11
+
12
+ Then contribute back to the Cucumber project. Details here:
13
+ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
14
+ }
15
+
16
+ def self.list_languages(io)
17
+ raw = Cucumber::LANGUAGES.keys.sort.map do |lang|
18
+ [lang, Cucumber::LANGUAGES[lang]['name'], Cucumber::LANGUAGES[lang]['native']]
19
+ end
20
+ table = Ast::Table.new(raw)
21
+ new(nil, io, {:check_lang=>true}, '').visit_multiline_arg(table)
22
+ end
23
+
24
+ def self.list_keywords(io, lang)
25
+ raw = Cucumber::KEYWORD_KEYS.map do |key|
26
+ [key, Cucumber::LANGUAGES[lang][key]]
27
+ end
28
+ table = Ast::Table.new(raw)
29
+ new(nil, io, {:incomplete => Cucumber.language_incomplete?(lang)}, '').visit_multiline_arg(table)
30
+ end
31
+
32
+ def visit_multiline_arg(table)
33
+ if @options[:incomplete]
34
+ @io.puts(format_string(INCOMPLETE, :failed))
35
+ end
36
+ super
37
+ end
38
+
39
+ def visit_table_row(table_row)
40
+ @col = 1
41
+ super
42
+ end
43
+
44
+ def visit_table_cell_value(value, width, status)
45
+ if @col == 1
46
+ if(@options[:check_lang])
47
+ @incomplete = Cucumber.language_incomplete?(value)
48
+ end
49
+ status = :comment
50
+ elsif @incomplete
51
+ status = :undefined
52
+ end
53
+
54
+ @col += 1
55
+ super(value, width, status)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,136 @@
1
+ require 'optparse'
2
+ require 'cucumber'
3
+ require 'ostruct'
4
+ require 'cucumber/parser'
5
+ require 'cucumber/feature_file'
6
+ require 'cucumber/formatter/color_io'
7
+ require 'cucumber/cli/language_help_formatter'
8
+ require 'cucumber/cli/configuration'
9
+ require 'cucumber/cli/drb_client'
10
+
11
+ module Cucumber
12
+ module Cli
13
+ class Main
14
+ class << self
15
+ def step_mother
16
+ @step_mother
17
+ end
18
+
19
+ def step_mother=(step_mother)
20
+ @step_mother = step_mother
21
+ @step_mother.extend(StepMother)
22
+ @step_mother.snippet_generator = StepDefinition
23
+ end
24
+
25
+ def execute(args)
26
+ new(args).execute!(@step_mother)
27
+ end
28
+ end
29
+
30
+ def initialize(args, out_stream = STDOUT, error_stream = STDERR)
31
+ @args = args
32
+ @out_stream = out_stream == STDOUT ? Formatter::ColorIO.new : out_stream
33
+ @error_stream = error_stream
34
+ end
35
+
36
+ def execute!(step_mother)
37
+ if configuration.drb?
38
+ begin
39
+ return DRbClient.run(@args, @error_stream, @out_stream)
40
+ rescue DRbClientError => e
41
+ @error_stream.puts "WARNING: #{e.message} Running features locally:"
42
+ configuration.parse!(@args)
43
+ end
44
+ end
45
+ step_mother.options = configuration.options
46
+
47
+ features = load_plain_text_features
48
+ require_files
49
+ enable_diffing
50
+
51
+ visitor = configuration.build_formatter_broadcaster(step_mother)
52
+ step_mother.visitor = visitor # Needed to support World#announce
53
+ visitor.visit_features(features)
54
+
55
+ failure = if configuration.wip?
56
+ step_mother.scenarios(:passed).any?
57
+ else
58
+ step_mother.scenarios(:failed).any? ||
59
+ (configuration.strict? && step_mother.steps(:undefined).any?)
60
+ end
61
+ end
62
+
63
+ def load_plain_text_features
64
+ features = Ast::Features.new
65
+
66
+ verbose_log("Features:")
67
+ configuration.feature_files.each do |f|
68
+ feature_file = FeatureFile.new(f)
69
+ feature = feature_file.parse(configuration.options)
70
+ if feature
71
+ features.add_feature(feature)
72
+ verbose_log(" * #{f}")
73
+ end
74
+ end
75
+ verbose_log("\n"*2)
76
+ features
77
+ end
78
+
79
+ def configuration
80
+ return @configuration if @configuration
81
+
82
+ @configuration = Configuration.new(@out_stream, @error_stream)
83
+ @configuration.parse!(@args)
84
+ @configuration
85
+ end
86
+
87
+ def load_files
88
+ each_lib{|lib| load(lib)}
89
+ end
90
+
91
+ private
92
+
93
+ def require_files
94
+ each_lib{|lib| require lib}
95
+ end
96
+
97
+ def each_lib
98
+ requires = configuration.files_to_require
99
+ verbose_log("Ruby files required:")
100
+ verbose_log(requires.map{|lib| " * #{lib}"}.join("\n"))
101
+ requires.each do |lib|
102
+ begin
103
+ yield lib
104
+ rescue LoadError => e
105
+ e.message << "\nFailed to load #{lib}"
106
+ raise e
107
+ end
108
+ end
109
+ verbose_log("\n")
110
+ end
111
+
112
+ def verbose_log(string)
113
+ @out_stream.puts(string) if configuration.verbose?
114
+ end
115
+
116
+ def enable_diffing
117
+ if configuration.diff_enabled?
118
+ begin
119
+ require 'spec/expectations'
120
+ begin
121
+ require 'spec/runner/differs/default' # RSpec >=1.2.4
122
+ rescue ::LoadError
123
+ require 'spec/expectations/differs/default' # RSpec <=1.2.3
124
+ end
125
+ options = OpenStruct.new(:diff_format => :unified, :context_lines => 3)
126
+ ::Spec::Expectations.differ = ::Spec::Expectations::Differs::Default.new(options)
127
+ rescue ::LoadError => ignore
128
+ end
129
+ end
130
+ end
131
+
132
+ end
133
+ end
134
+ end
135
+
136
+ Cucumber::Cli::Main.step_mother = self
@@ -0,0 +1,53 @@
1
+ # Exception extension that tweaks Exception backtraces:
2
+ #
3
+ # * The line of the failing .feature line is appended to the backtrace
4
+ # * The line that calls #cucumber_instance_exec is replaced with the StepDefinition's regexp
5
+ # * Non intersting lines are stripped out
6
+ #
7
+ # The result is that backtraces look like this:
8
+ #
9
+ # features/step_definitions/the_step_definition.rb:in `/some step/'
10
+ # features/the_feature_file.feature:41:in `Given some step'
11
+ #
12
+ # or if the exception is raised in the tested code:
13
+ #
14
+ # lib/myapp/some_file.rb:in `/some_method/'
15
+ # lib/myapp/some_other_file.rb:in `/some_other_method/'
16
+ # features/step_definitions/the_step_definition.rb:in `/some step/'
17
+ # features/the_feature_file.feature:41:in `Given some step'
18
+ #
19
+ # All backtrace munging can be turned off with the <tt>--backtrace</tt> switch
20
+ #
21
+ class Exception
22
+ CUCUMBER_FILTER_PATTERNS = [
23
+ /vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\//
24
+ ]
25
+
26
+ INSTANCE_EXEC_OFFSET = (Cucumber::RUBY_1_9 || Cucumber::JRUBY) ? -3 : -4
27
+
28
+ def self.cucumber_full_backtrace=(v)
29
+ @@cucumber_full_backtrace = v
30
+ end
31
+ self.cucumber_full_backtrace = false
32
+
33
+ # Strips the backtrace from +line+ and down
34
+ def self.cucumber_strip_backtrace!(backtrace, instance_exec_invocation_line, pseudo_method)
35
+ return if @@cucumber_full_backtrace
36
+
37
+ instance_exec_pos = backtrace.index(instance_exec_invocation_line)
38
+ if instance_exec_pos
39
+ replacement_line = instance_exec_pos + INSTANCE_EXEC_OFFSET
40
+ backtrace[replacement_line].gsub!(/`.*'/, "`#{pseudo_method}'") if pseudo_method
41
+ backtrace[replacement_line+1..-1] = nil
42
+
43
+ backtrace.compact!
44
+ else
45
+ # This happens with rails, because they screw up the backtrace
46
+ # before we get here (injecting erb stacktrace and such)
47
+ end
48
+
49
+ backtrace.reject! do |line|
50
+ CUCUMBER_FILTER_PATTERNS.detect{|p| line =~ p}
51
+ end
52
+ end
53
+ end