mattwynne-cucover 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. data/.gitignore +6 -0
  2. data/Licence.txt +22 -0
  3. data/README.markdown +23 -7
  4. data/Rakefile +86 -0
  5. data/VERSION +1 -0
  6. data/bin/cucover +1 -1
  7. data/cucover.gemspec +305 -0
  8. data/examples/self_test/rails/.gitignore +2 -0
  9. data/examples/self_test/rails/README +256 -0
  10. data/examples/self_test/rails/Rakefile +10 -0
  11. data/examples/self_test/rails/app/controllers/application.rb +2 -0
  12. data/examples/self_test/rails/app/controllers/widgets_controller.rb +2 -0
  13. data/examples/self_test/rails/app/views/widgets/index.html.erb +1 -0
  14. data/examples/self_test/rails/config/boot.rb +109 -0
  15. data/examples/self_test/rails/config/database.yml +19 -0
  16. data/examples/self_test/rails/config/environment.rb +68 -0
  17. data/examples/self_test/rails/config/environments/development.rb +17 -0
  18. data/examples/self_test/rails/config/environments/production.rb +22 -0
  19. data/examples/self_test/rails/config/environments/test.rb +22 -0
  20. data/examples/self_test/rails/config/routes.rb +43 -0
  21. data/examples/self_test/rails/db/test.sqlite3 +0 -0
  22. data/examples/self_test/rails/features/see_widgets.feature +7 -0
  23. data/examples/self_test/rails/features/step_definitions/env.rb +0 -0
  24. data/examples/self_test/rails/features/step_definitions/webrat_steps.rb +7 -0
  25. data/examples/self_test/rails/features/support/env.rb +17 -0
  26. data/examples/self_test/rails/lib/tasks/cucumber.rake +15 -0
  27. data/examples/self_test/rails/public/404.html +30 -0
  28. data/examples/self_test/rails/public/422.html +30 -0
  29. data/examples/self_test/rails/public/500.html +30 -0
  30. data/examples/self_test/rails/public/dispatch.cgi +10 -0
  31. data/examples/self_test/rails/public/dispatch.fcgi +24 -0
  32. data/examples/self_test/rails/public/dispatch.rb +10 -0
  33. data/examples/self_test/rails/public/favicon.ico +0 -0
  34. data/examples/self_test/rails/public/images/rails.png +0 -0
  35. data/examples/self_test/rails/public/index.html +274 -0
  36. data/examples/self_test/rails/public/javascripts/application.js +2 -0
  37. data/examples/self_test/rails/public/javascripts/controls.js +963 -0
  38. data/examples/self_test/rails/public/javascripts/dragdrop.js +972 -0
  39. data/examples/self_test/rails/public/javascripts/effects.js +1120 -0
  40. data/examples/self_test/rails/public/javascripts/prototype.js +4225 -0
  41. data/examples/self_test/rails/public/robots.txt +5 -0
  42. data/examples/self_test/rails/script/about +4 -0
  43. data/examples/self_test/rails/script/console +3 -0
  44. data/examples/self_test/rails/script/cucumber +8 -0
  45. data/examples/self_test/rails/script/dbconsole +3 -0
  46. data/examples/self_test/rails/script/destroy +3 -0
  47. data/examples/self_test/rails/script/generate +3 -0
  48. data/examples/self_test/rails/script/performance/benchmarker +3 -0
  49. data/examples/self_test/rails/script/performance/profiler +3 -0
  50. data/examples/self_test/rails/script/performance/request +3 -0
  51. data/examples/self_test/rails/script/plugin +3 -0
  52. data/examples/self_test/rails/script/process/inspector +3 -0
  53. data/examples/self_test/rails/script/process/reaper +3 -0
  54. data/examples/self_test/rails/script/process/spawner +3 -0
  55. data/examples/self_test/rails/script/runner +3 -0
  56. data/examples/self_test/rails/script/server +3 -0
  57. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/.specification +148 -0
  58. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/History.txt +324 -0
  59. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/MIT-LICENSE.txt +19 -0
  60. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/README.rdoc +85 -0
  61. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/Rakefile +151 -0
  62. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/install.rb +1 -0
  63. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/configuration.rb +98 -0
  64. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/area.rb +31 -0
  65. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/element.rb +33 -0
  66. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/field.rb +403 -0
  67. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/form.rb +103 -0
  68. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/label.rb +31 -0
  69. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/link.rb +92 -0
  70. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/select_option.rb +35 -0
  71. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/area_locator.rb +38 -0
  72. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/button_locator.rb +54 -0
  73. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
  74. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
  75. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_locator.rb +25 -0
  76. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_named_locator.rb +41 -0
  77. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/form_locator.rb +19 -0
  78. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/label_locator.rb +34 -0
  79. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/link_locator.rb +66 -0
  80. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/locator.rb +20 -0
  81. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/select_option_locator.rb +59 -0
  82. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators.rb +20 -0
  83. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/logging.rb +21 -0
  84. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_content.rb +73 -0
  85. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_selector.rb +74 -0
  86. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_tag.rb +21 -0
  87. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_xpath.rb +147 -0
  88. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers.rb +4 -0
  89. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/methods.rb +61 -0
  90. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/mime.rb +29 -0
  91. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/save_and_open_page.rb +50 -0
  92. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/scope.rb +350 -0
  93. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/session.rb +281 -0
  94. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml/hpricot.rb +19 -0
  95. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml/nokogiri.rb +76 -0
  96. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml/rexml.rb +24 -0
  97. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml.rb +115 -0
  98. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core.rb +14 -0
  99. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/blank.rb +58 -0
  100. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/deprecate.rb +8 -0
  101. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/detect_mapped.rb +12 -0
  102. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/meta_class.rb +6 -0
  103. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/nil_to_param.rb +5 -0
  104. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/tcp_socket.rb +27 -0
  105. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/mechanize.rb +74 -0
  106. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/merb.rb +9 -0
  107. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/merb_session.rb +65 -0
  108. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/rack.rb +24 -0
  109. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/rails.rb +105 -0
  110. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/rspec-rails.rb +13 -0
  111. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/application_server.rb +71 -0
  112. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/button.js +12 -0
  113. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
  114. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
  115. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webratlink.js +9 -0
  116. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
  117. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
  118. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_content.rb +66 -0
  119. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_selector.rb +49 -0
  120. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_tag.rb +72 -0
  121. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_xpath.rb +45 -0
  122. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers.rb +4 -0
  123. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/merb_application_server.rb +48 -0
  124. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/rails_application_server.rb +42 -0
  125. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/selenium_extensions.js +6 -0
  126. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/selenium_rc_server.rb +80 -0
  127. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/selenium_session.rb +241 -0
  128. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/sinatra_application_server.rb +35 -0
  129. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium.rb +80 -0
  130. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/sinatra.rb +44 -0
  131. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat.rb +34 -0
  132. data/examples/self_test/rails/vendor/gems/webrat-0.4.4/vendor/selenium-server.jar +0 -0
  133. data/examples/self_test/simple/features/call_foo.feature +4 -0
  134. data/examples/self_test/simple/features/call_foo_and_bar_together.feature +5 -0
  135. data/examples/self_test/simple/features/call_foo_from_background_then_bar.feature +7 -0
  136. data/examples/self_test/simple/features/call_foo_from_background_then_bar_then_baz.feature +10 -0
  137. data/examples/self_test/simple/features/call_foo_then_bar.feature +7 -0
  138. data/examples/self_test/simple/features/call_foo_then_bar_from_scenario_outline_examples.feature +9 -0
  139. data/examples/self_test/simple/features/fail.feature +10 -0
  140. data/examples/self_test/simple/features/step_definitions/main_steps.rb +15 -0
  141. data/examples/self_test/simple/lib/bar.rb +5 -0
  142. data/examples/self_test/simple/lib/baz.rb +5 -0
  143. data/examples/self_test/simple/lib/foo.rb +9 -0
  144. data/features/call_foo.feature +0 -0
  145. data/features/coverage_of.feature +44 -0
  146. data/features/fail.feature +54 -0
  147. data/features/lazy_run.feature +79 -0
  148. data/features/lazy_run_per_scenario.feature +113 -0
  149. data/features/lazy_run_per_scenario_outline_example.feature +31 -0
  150. data/features/lazy_run_triggered_by_rails_view_change.feature +42 -0
  151. data/features/run.feature +25 -0
  152. data/features/show_recordings.feature +28 -0
  153. data/features/step_definitions/main_steps.rb +36 -0
  154. data/features/support/env.rb +48 -0
  155. data/lib/cucover/cli.rb +26 -0
  156. data/lib/cucover/cli_commands/coverage_of.rb +36 -0
  157. data/lib/cucover/cli_commands/cucumber.rb +25 -0
  158. data/lib/cucover/cli_commands/show_recordings.rb +29 -0
  159. data/lib/cucover/controller.rb +28 -0
  160. data/lib/cucover/cucumber_hooks.rb +29 -0
  161. data/lib/cucover/logging_config.rb +16 -0
  162. data/lib/cucover/monkey.rb +14 -0
  163. data/lib/cucover/rails.rb +20 -0
  164. data/lib/cucover/recorder.rb +37 -0
  165. data/lib/cucover/recording/covered_file.rb +53 -0
  166. data/lib/cucover/recording.rb +64 -0
  167. data/lib/cucover/store.rb +70 -0
  168. data/lib/cucover.rb +35 -212
  169. data/lib/dependencies.rb +10 -0
  170. data/spec/cucover/cli_spec.rb +31 -0
  171. data/spec/cucover/controller_spec.rb +16 -0
  172. data/spec/cucover/recording/covered_file_spec.rb +20 -0
  173. data/spec/cucover/store_spec.rb +28 -0
  174. data/spec/spec_helper.rb +7 -0
  175. data/tmp/.gitignore +0 -0
  176. metadata +304 -21
@@ -0,0 +1,79 @@
1
+ Feature: Lazy Run
2
+ In order to get rapid feedback, stay motivated and keep my concentration
3
+ As a developer
4
+ I want to be able to run only the features that could have been affected by the changes I've made
5
+
6
+ Background:
7
+ And I am using the simple example app
8
+ And I have run cucover -- features/call_foo.feature
9
+
10
+ Scenario: Change nothing and run same feature again
11
+ When I run cucover -- -q features/call_foo.feature
12
+ Then it should pass with:
13
+ """
14
+ Feature: Call Foo
15
+
16
+ Scenario: Call Foo
17
+
18
+ [ Cucover - Skipping clean scenario ]
19
+ When I call Foo
20
+
21
+ 1 scenario (1 skipped)
22
+ 1 step (1 skipped)
23
+
24
+ """
25
+
26
+ Scenario: Change irrelevant source file and run same feature again
27
+ When I edit the source file lib/bar.rb
28
+ When I run cucover -- features/call_foo.feature
29
+ Then it should pass with:
30
+ """
31
+ Feature: Call Foo
32
+
33
+ Scenario: Call Foo # features/call_foo.feature:3
34
+
35
+ [ Cucover - Skipping clean scenario ]
36
+ When I call Foo # features/step_definitions/main_steps.rb:9
37
+
38
+ 1 scenario (1 skipped)
39
+ 1 step (1 skipped)
40
+
41
+ """
42
+
43
+ Scenario: Touch feature file and run same feature again
44
+ When I edit the source file features/call_foo.feature
45
+ And I run cucover -- features/call_foo.feature
46
+ Then it should pass with:
47
+ """
48
+ Feature: Call Foo
49
+
50
+ Scenario: Call Foo # features/call_foo.feature:3
51
+ When I call Foo # features/step_definitions/main_steps.rb:9
52
+
53
+ 1 scenario (1 passed)
54
+ 1 step (1 passed)
55
+
56
+ """
57
+
58
+ Scenario: Touch one source file and try to run lots of features
59
+ When I edit the source file lib/bar.rb
60
+ And I run cucover -- features/call_foo.feature features/call_foo_and_bar_together.feature
61
+ Then it should pass with:
62
+ """
63
+ Feature: Call Foo
64
+
65
+ Scenario: Call Foo # features/call_foo.feature:3
66
+
67
+ [ Cucover - Skipping clean scenario ]
68
+ When I call Foo # features/step_definitions/main_steps.rb:9
69
+
70
+ Feature: Call Foo and Bar Together
71
+
72
+ Scenario: Call Foo and Bar # features/call_foo_and_bar_together.feature:3
73
+ When I call Foo # features/step_definitions/main_steps.rb:9
74
+ And I call Bar # features/step_definitions/main_steps.rb:9
75
+
76
+ 2 scenarios (1 skipped, 1 passed)
77
+ 3 steps (1 skipped, 2 passed)
78
+
79
+ """
@@ -0,0 +1,113 @@
1
+ Feature: Lazy Run per Scenario
2
+ In order to work with a single feature
3
+ As a developer
4
+ I want to skip the scenarios that don't need to be run
5
+
6
+ Background:
7
+ Given I am using the simple example app
8
+
9
+ Scenario: Change nothing and run same feature again
10
+ Given I have run cucover -- features/call_foo_then_bar.feature
11
+ When I run cucover -- features/call_foo_then_bar.feature
12
+ Then it should pass with:
13
+ """
14
+ Feature: Call Foo then Bar
15
+
16
+ Scenario: Call Foo # features/call_foo_then_bar.feature:3
17
+
18
+ [ Cucover - Skipping clean scenario ]
19
+ When I call Foo # features/step_definitions/main_steps.rb:9
20
+
21
+ Scenario: Call Bar # features/call_foo_then_bar.feature:6
22
+
23
+ [ Cucover - Skipping clean scenario ]
24
+ When I call Bar # features/step_definitions/main_steps.rb:9
25
+
26
+ 2 scenarios (2 skipped)
27
+ 2 steps (2 skipped)
28
+
29
+ """
30
+
31
+ Scenario: Edit source file covered by only one scenario and run same feature again
32
+ Given I have run cucover -- features/call_foo_then_bar.feature
33
+ When I edit the source file lib/foo.rb
34
+ And I run cucover -- features/call_foo_then_bar.feature
35
+ Then it should pass with:
36
+ """
37
+ Feature: Call Foo then Bar
38
+
39
+ Scenario: Call Foo # features/call_foo_then_bar.feature:3
40
+ When I call Foo # features/step_definitions/main_steps.rb:9
41
+
42
+ Scenario: Call Bar # features/call_foo_then_bar.feature:6
43
+
44
+ [ Cucover - Skipping clean scenario ]
45
+ When I call Bar # features/step_definitions/main_steps.rb:9
46
+
47
+ 2 scenarios (1 skipped, 1 passed)
48
+ 2 steps (1 skipped, 1 passed)
49
+
50
+ """
51
+
52
+ Scenario: Run a feature with a background twice
53
+ Given I have run cucover -- features/call_foo_from_background_then_bar.feature
54
+ When I run cucover -- features/call_foo_from_background_then_bar.feature
55
+ Then it should pass with:
56
+ """
57
+ Feature: Call Foo from Background then Bar
58
+
59
+ Background: # features/call_foo_from_background_then_bar.feature:3
60
+
61
+ [ Cucover - Skipping clean scenario ]
62
+ Given I have called Foo # features/step_definitions/main_steps.rb:5
63
+
64
+ Scenario: Call Bar # features/call_foo_from_background_then_bar.feature:6
65
+ When I call Bar # features/step_definitions/main_steps.rb:9
66
+
67
+ 1 scenario (1 skipped)
68
+ 2 steps (2 skipped)
69
+
70
+ """
71
+
72
+ Scenario: Edit source file covered by the background of a feature
73
+ Given I have run cucover -- features/call_foo_from_background_then_bar.feature
74
+ When I edit the source file lib/foo.rb
75
+ And I run cucover -- features/call_foo_from_background_then_bar.feature
76
+ Then it should pass with:
77
+ """
78
+ Feature: Call Foo from Background then Bar
79
+
80
+ Background: # features/call_foo_from_background_then_bar.feature:3
81
+ Given I have called Foo # features/step_definitions/main_steps.rb:5
82
+
83
+ Scenario: Call Bar # features/call_foo_from_background_then_bar.feature:6
84
+ When I call Bar # features/step_definitions/main_steps.rb:9
85
+
86
+ 1 scenario (1 passed)
87
+ 2 steps (2 passed)
88
+
89
+ """
90
+
91
+ Scenario: Edit source file covered by a scenario with a background
92
+ Given I have run cucover -- features/call_foo_from_background_then_bar_then_baz.feature
93
+ When I edit the source file lib/bar.rb
94
+ And I run cucover -- features/call_foo_from_background_then_bar_then_baz.feature
95
+ Then it should pass with:
96
+ """
97
+ Feature: Call Foo from Background then Bar then Baz
98
+
99
+ Background: # features/call_foo_from_background_then_bar_then_baz.feature:3
100
+ Given I have called Foo # features/step_definitions/main_steps.rb:5
101
+
102
+ Scenario: Call Bar # features/call_foo_from_background_then_bar_then_baz.feature:6
103
+ When I call Bar # features/step_definitions/main_steps.rb:9
104
+
105
+ Scenario: Call Baz # features/call_foo_from_background_then_bar_then_baz.feature:9
106
+
107
+ [ Cucover - Skipping clean scenario ]
108
+ When I call Baz # features/step_definitions/main_steps.rb:9
109
+
110
+ 2 scenarios (1 skipped, 1 passed)
111
+ 4 steps (2 skipped, 2 passed)
112
+
113
+ """
@@ -0,0 +1,31 @@
1
+ Feature: Lazy Run per Scenario Outline Example
2
+ In order save time
3
+ As a developer working on a feature with Scenario Outlines
4
+ I want to run only the examples that could fail
5
+
6
+ Background:
7
+ Given I am using the simple example app
8
+ And I have run cucover -- features/call_foo_then_bar_from_scenario_outline_examples.feature
9
+
10
+ Scenario: Edit a source file that should trigger just one of the examples to be run
11
+ When I edit the source file lib/bar.rb
12
+ And I run cucover -- -q features/call_foo_then_bar_from_scenario_outline_examples.feature
13
+ Then it should pass with:
14
+ """
15
+ Feature: Call Foo then Bar from Scenario Outline Examples
16
+
17
+ Scenario Outline: Call Something
18
+ When I call <Code>
19
+
20
+ Examples:
21
+ | Code |
22
+ |
23
+ [ Cucover - Skipping clean scenario ]
24
+ Foo |
25
+ | Bar |
26
+
27
+ 2 scenarios (1 skipped, 1 passed)
28
+ 2 steps (1 skipped, 1 passed)
29
+
30
+ """
31
+ # Which is a bit ugly, but that's down the the formatter
@@ -0,0 +1,42 @@
1
+ @slow
2
+ Feature: Lazy Run Triggered By Rails View Change
3
+ In order to feel the cucover love
4
+ As a front-end developer
5
+ I want the changes I make to rails views to trigger cucover runs, the same as Ruby code does
6
+
7
+ Background:
8
+ And I am using the rails example app
9
+ And I have run cucover -- features/see_widgets.feature
10
+
11
+ Scenario: Change nothing and run cucover again
12
+ When I run cucover -- features/see_widgets.feature
13
+ Then it should pass with:
14
+ """
15
+ Feature: See widgets
16
+
17
+ Scenario: See widgets # features/see_widgets.feature:3
18
+
19
+ [ Cucover - Skipping clean scenario ]
20
+ When I go to /widgets # features/step_definitions/webrat_steps.rb:1
21
+ Then I should see "Look at all these lovely widgets" # features/step_definitions/webrat_steps.rb:5
22
+
23
+ 1 scenario (1 skipped)
24
+ 2 steps (2 skipped)
25
+
26
+ """
27
+
28
+ Scenario: Edit a view and run cucover again
29
+ When I edit the source file app/views/widgets/index.html.erb
30
+ When I run cucover -- features/see_widgets.feature
31
+ Then it should pass with:
32
+ """
33
+ Feature: See widgets
34
+
35
+ Scenario: See widgets # features/see_widgets.feature:3
36
+ When I go to /widgets # features/step_definitions/webrat_steps.rb:1
37
+ Then I should see "Look at all these lovely widgets" # features/step_definitions/webrat_steps.rb:5
38
+
39
+ 1 scenario (1 passed)
40
+ 2 steps (2 passed)
41
+
42
+ """
@@ -0,0 +1,25 @@
1
+ Feature: Run
2
+ In order to trust cucover and not have to switch between testing tools
3
+ As a developer
4
+ I want to be able to run features and get useful feedback through cucover
5
+
6
+ Scenario: Run features, minimal output
7
+ Given I am using the simple example app
8
+ When I run cucover -- features/call_foo.feature features/call_foo_and_bar_together.feature
9
+ Then it should pass with:
10
+ """
11
+ Feature: Call Foo
12
+
13
+ Scenario: Call Foo # features/call_foo.feature:3
14
+ When I call Foo # features/step_definitions/main_steps.rb:9
15
+
16
+ Feature: Call Foo and Bar Together
17
+
18
+ Scenario: Call Foo and Bar # features/call_foo_and_bar_together.feature:3
19
+ When I call Foo # features/step_definitions/main_steps.rb:9
20
+ And I call Bar # features/step_definitions/main_steps.rb:9
21
+
22
+ 2 scenarios (2 passed)
23
+ 3 steps (3 passed)
24
+
25
+ """
@@ -0,0 +1,28 @@
1
+ Feature: Show Recordings
2
+ In order to see what's going on inside Cucover
3
+ As a developer of Cucover
4
+ I want to be able to see a human-readable summary of the recordings
5
+
6
+ Background:
7
+ Given I am using the simple example app
8
+
9
+ Scenario: Run a couple of features, see the recordings
10
+ Given I have run cucover -- features/call_foo.feature
11
+ And I have run cucover -- features/call_foo_and_bar_together.feature
12
+ When I run cucover --show-recordings
13
+ Then it should pass with:
14
+ """
15
+
16
+ features/call_foo.feature:3
17
+ features/step_definitions/main_steps.rb:6:10
18
+ lib/foo.rb:2:3:4
19
+ features/call_foo.feature:<unknown lines>
20
+
21
+ features/call_foo_and_bar_together.feature:3
22
+ lib/foo.rb:2:3:4
23
+ features/step_definitions/main_steps.rb:6:10
24
+ lib/bar.rb:2:3:4
25
+ features/call_foo_and_bar_together.feature:<unknown lines>
26
+
27
+
28
+ """
@@ -0,0 +1,36 @@
1
+ Given /^I have (tried to |)run cucover (.*)$/ do |tried, args|
2
+ When %{I run cucover #{args}}
3
+ if tried.blank?
4
+ assert(@status == 0, @out)
5
+ end
6
+ end
7
+
8
+ Given /^I am using the (.*) example app$/ do |app_name|
9
+ @example_app = app_name
10
+ clear_cache!
11
+ end
12
+
13
+ When /^I run cucover (.*)$/ do |args|
14
+ cucover_binary = File.expand_path(File.dirname(__FILE__) + '../../../bin/cucover')
15
+ within_examples_dir do
16
+ full_cmd = "#{Cucumber::RUBY_BINARY} #{cucover_binary} #{args}"
17
+ @out = `#{full_cmd}`
18
+ @status = $?.exitstatus
19
+ end
20
+ end
21
+
22
+ When /^I edit the source file (.*)$/ do |source_file|
23
+ within_examples_dir do
24
+ edit source_file
25
+ end
26
+ end
27
+
28
+ Then /^it should (pass|fail) with:$/ do |expected_status, expected_text|
29
+ expected_status_code = expected_status == "pass" ? 0 : 1
30
+
31
+ unless @status == expected_status_code
32
+ raise "Expected #{expected_status} but return code was #{@status}: #{@out}"
33
+ end
34
+
35
+ strip_duration(@out).should == expected_text
36
+ end
@@ -0,0 +1,48 @@
1
+ # require File.dirname(__FILE__) + '/../../lib/cucover'
2
+ require 'spec'
3
+ require 'test/unit/assertions'
4
+
5
+ module CucoverHelper
6
+ def edit(file)
7
+ original_mtime = File.mtime(file)
8
+ FileUtils.touch(file)
9
+ @edited_files ||= {}
10
+ @edited_files[file] = original_mtime
11
+ end
12
+
13
+ def restore_file_mtimes
14
+ return unless @edited_files
15
+ @edited_files.each do |file, original_mtime|
16
+ `touch -t #{original_mtime.strftime('%Y%m%d%H%M.%S')} #{examples_dir}/#{file}`
17
+ end
18
+ end
19
+
20
+ def strip_duration(s)
21
+ s.gsub(/^\d+m\d+\.\d+s\n/m, "")
22
+ end
23
+
24
+ def clear_cache!
25
+ `find examples -name cucover.data | xargs rm -rf`
26
+ end
27
+
28
+ def example_app
29
+ @example_app || raise("Please call the step 'Given I am using the .... example app' so I know which example app to run these features in.")
30
+ end
31
+
32
+ def within_examples_dir
33
+ Dir.chdir(examples_dir) do
34
+ yield
35
+ end
36
+ end
37
+
38
+ def examples_dir
39
+ File.expand_path(File.dirname(__FILE__) + "/../../examples/self_test/#{example_app}")
40
+ end
41
+ end
42
+
43
+ World CucoverHelper, Test::Unit::Assertions
44
+
45
+ After do
46
+ clear_cache!
47
+ restore_file_mtimes
48
+ end
@@ -0,0 +1,26 @@
1
+ module Cucover
2
+ class Cli
3
+ def initialize(args)
4
+ @args = args
5
+ end
6
+
7
+ def start
8
+ command_type.new(@args).execute
9
+ end
10
+
11
+ private
12
+
13
+ def command_type
14
+ if @args.index('--')
15
+ CliCommands::Cucumber
16
+ elsif @args.index('--coverage-of')
17
+ CliCommands::CoverageOf
18
+ elsif @args.index('--show-recordings')
19
+ CliCommands::ShowRecordings
20
+ else
21
+ raise("Sorry: I don't understand these command line arguments: #{@args.inspect}. Soon I will say something more helpful here.")
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ module Cucover
2
+ module CliCommands
3
+ class CoverageOf
4
+ CODE_COLUMN_WIDTH = 15
5
+
6
+ def initialize(cli_args)
7
+ @filespec = cli_args[1]
8
+ @store = Store.new
9
+ end
10
+
11
+ def execute
12
+ return unless recordings.any?
13
+
14
+ File.open(@filespec).each_with_index do |line_content, index|
15
+ line_number = index + 1
16
+ coverage_text = coverage(line_number).join(', ')
17
+ line_content.rstrip!
18
+ if line_content.length > CODE_COLUMN_WIDTH
19
+ truncated_line_content = "#{line_content[0..(CODE_COLUMN_WIDTH - 1)]}.."
20
+ else
21
+ truncated_line_content = "#{line_content} "
22
+ end
23
+ puts "#{line_number} #{truncated_line_content.ljust(CODE_COLUMN_WIDTH + 2)} #{coverage_text}"
24
+ end
25
+ end
26
+
27
+ def coverage(line_number)
28
+ recordings.select{ |r| r.covers_line?(@filespec, line_number) }.map{ |r| r.file_colon_line }
29
+ end
30
+
31
+ def recordings
32
+ @recordings ||= @store.recordings_covering(@filespec)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ module Cucover
2
+ module CliCommands
3
+ class Cucumber
4
+ def initialize(cli_args)
5
+ @cli_args = cli_args
6
+ end
7
+
8
+ def execute
9
+ require 'cucover/cucumber_hooks'
10
+ ARGV.replace cucumber_args
11
+ Kernel.load ::Cucumber::BINARY
12
+ ARGV.replace @cli_args
13
+ end
14
+
15
+ private
16
+
17
+ def cucumber_args
18
+ return nil unless @cli_args.index('--')
19
+ first = @cli_args.index('--') + 1
20
+ last = @cli_args.length - 1
21
+ @cli_args[first..last]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ module Cucover
2
+ module CliCommands
3
+ class ShowRecordings
4
+ def initialize(cli_args)
5
+ @store = Store.new
6
+ end
7
+
8
+ def execute
9
+ unless recordings.any?
10
+ puts "No recordings to show. Run some tests with cucover first."
11
+ return
12
+ end
13
+
14
+ recordings.each do |recording|
15
+ puts
16
+ puts "#{recording.file_colon_line}" # (#{recording.start_time.strftime('%Y-%m-%d %H:%M:%S')})
17
+ recording.covered_files.each do |covered_file|
18
+ puts " #{covered_file.to_s}"
19
+ end
20
+ end
21
+ puts
22
+ end
23
+
24
+ def recordings
25
+ @recordings ||= @store.latest_recordings.sort{ |x, y| x.file_colon_line <=> y.file_colon_line }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ module Cucover
2
+ class Controller
3
+ def initialize(file_colon_line, store)
4
+ @file_colon_line = file_colon_line
5
+ @store = store
6
+ end
7
+
8
+ def should_execute?
9
+ dirty? or failed_on_last_run?
10
+ end
11
+
12
+ private
13
+
14
+ def failed_on_last_run?
15
+ return false unless recording
16
+ recording.failed?
17
+ end
18
+
19
+ def dirty?
20
+ Cucover.logger.debug("Assuming dirty as no recording found") and return true unless recording
21
+ recording.covered_files.any?{ |f| f.dirty? }
22
+ end
23
+
24
+ def recording
25
+ @recording ||= @store.latest_recording(@file_colon_line)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Cucover
2
+ module ExampleRowExtensions
3
+ def file_colon_line
4
+ "#{file}:#{line}"
5
+ end
6
+
7
+ def file
8
+ @scenario_outline.file_colon_line.split(':').first
9
+ end
10
+ end
11
+ end
12
+
13
+ Cucover::Monkey.extend_every Cucumber::Ast::OutlineTable::ExampleRow => Cucover::ExampleRowExtensions
14
+
15
+ Before do |scenario_or_table_row|
16
+ Cucover.logger.info("Starting #{scenario_or_table_row.class} #{scenario_or_table_row.file_colon_line}")
17
+ Cucover::Rails.patch_if_necessary
18
+
19
+ if Cucover.should_execute?(scenario_or_table_row)
20
+ Cucover.start_recording!(scenario_or_table_row)
21
+ else
22
+ announce "[ Cucover - Skipping clean scenario ]"
23
+ scenario_or_table_row.skip_invoke!
24
+ end
25
+ end
26
+
27
+ After do
28
+ Cucover.stop_recording!
29
+ end
@@ -0,0 +1,16 @@
1
+ Logging.configure do
2
+ logger('Cucover') do
3
+ level :debug
4
+ appenders 'logfile'
5
+ end
6
+
7
+ appender('logfile') do
8
+ type 'File'
9
+ level :debug
10
+ filename File.dirname(__FILE__) + '/../../tmp/cucover.log'
11
+ layout do
12
+ type 'Pattern'
13
+ pattern '[%d] %l %c : %m\n'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module Cucover
2
+ module Monkey
3
+ def self.extend_every(args)
4
+ class_to_extend = args.keys.first
5
+ module_to_extend_with = args.values.first
6
+
7
+ class_to_extend.instance_eval <<-PATCH
8
+ def new(*args)
9
+ super(*args).extend(#{module_to_extend_with})
10
+ end
11
+ PATCH
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ module Cucover
2
+ module Rails
3
+ class << self
4
+ def patch_if_necessary
5
+ return if @patched
6
+ return unless defined?(ActionView)
7
+
8
+ Monkey.extend_every ActionView::Template => Cucover::Rails::RecordsRenders
9
+ @patched = true
10
+ end
11
+ end
12
+
13
+ module RecordsRenders
14
+ def render
15
+ Cucover.record_file(@filename)
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ module Cucover
2
+ class Recorder
3
+ def initialize(scenario_or_table_row)
4
+ @scenario_or_table_row = scenario_or_table_row
5
+ @analyzer = Rcov::CodeCoverageAnalyzer.new
6
+ @additional_covered_files = []
7
+ end
8
+
9
+ def record_file!(source_file)
10
+ unless @additional_covered_files.include?(source_file)
11
+ @additional_covered_files << source_file
12
+ end
13
+ end
14
+
15
+ def start!
16
+ @start_time = Time.now
17
+ @analyzer.install_hook
18
+ end
19
+
20
+ def stop!
21
+ @end_time = Time.now
22
+ @analyzer.remove_hook
23
+ Cucover.logger.info("Finished recording #{@scenario_or_table_row.file_colon_line}.")
24
+ Cucover.logger.debug("Covered files: #{@analyzer.analyzed_files.join(',')}")
25
+ Cucover.logger.debug("Additional Covered files: #{@additional_covered_files.join(',')}")
26
+ end
27
+
28
+ def recording
29
+ Recording.new(
30
+ @scenario_or_table_row.file_colon_line,
31
+ @scenario_or_table_row.exception,
32
+ @additional_covered_files,
33
+ @analyzer,
34
+ @start_time, @end_time)
35
+ end
36
+ end
37
+ end