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.
- data/.gitignore +6 -0
- data/Licence.txt +22 -0
- data/README.markdown +23 -7
- data/Rakefile +86 -0
- data/VERSION +1 -0
- data/bin/cucover +1 -1
- data/cucover.gemspec +305 -0
- data/examples/self_test/rails/.gitignore +2 -0
- data/examples/self_test/rails/README +256 -0
- data/examples/self_test/rails/Rakefile +10 -0
- data/examples/self_test/rails/app/controllers/application.rb +2 -0
- data/examples/self_test/rails/app/controllers/widgets_controller.rb +2 -0
- data/examples/self_test/rails/app/views/widgets/index.html.erb +1 -0
- data/examples/self_test/rails/config/boot.rb +109 -0
- data/examples/self_test/rails/config/database.yml +19 -0
- data/examples/self_test/rails/config/environment.rb +68 -0
- data/examples/self_test/rails/config/environments/development.rb +17 -0
- data/examples/self_test/rails/config/environments/production.rb +22 -0
- data/examples/self_test/rails/config/environments/test.rb +22 -0
- data/examples/self_test/rails/config/routes.rb +43 -0
- data/examples/self_test/rails/db/test.sqlite3 +0 -0
- data/examples/self_test/rails/features/see_widgets.feature +7 -0
- data/examples/self_test/rails/features/step_definitions/env.rb +0 -0
- data/examples/self_test/rails/features/step_definitions/webrat_steps.rb +7 -0
- data/examples/self_test/rails/features/support/env.rb +17 -0
- data/examples/self_test/rails/lib/tasks/cucumber.rake +15 -0
- data/examples/self_test/rails/public/404.html +30 -0
- data/examples/self_test/rails/public/422.html +30 -0
- data/examples/self_test/rails/public/500.html +30 -0
- data/examples/self_test/rails/public/dispatch.cgi +10 -0
- data/examples/self_test/rails/public/dispatch.fcgi +24 -0
- data/examples/self_test/rails/public/dispatch.rb +10 -0
- data/examples/self_test/rails/public/favicon.ico +0 -0
- data/examples/self_test/rails/public/images/rails.png +0 -0
- data/examples/self_test/rails/public/index.html +274 -0
- data/examples/self_test/rails/public/javascripts/application.js +2 -0
- data/examples/self_test/rails/public/javascripts/controls.js +963 -0
- data/examples/self_test/rails/public/javascripts/dragdrop.js +972 -0
- data/examples/self_test/rails/public/javascripts/effects.js +1120 -0
- data/examples/self_test/rails/public/javascripts/prototype.js +4225 -0
- data/examples/self_test/rails/public/robots.txt +5 -0
- data/examples/self_test/rails/script/about +4 -0
- data/examples/self_test/rails/script/console +3 -0
- data/examples/self_test/rails/script/cucumber +8 -0
- data/examples/self_test/rails/script/dbconsole +3 -0
- data/examples/self_test/rails/script/destroy +3 -0
- data/examples/self_test/rails/script/generate +3 -0
- data/examples/self_test/rails/script/performance/benchmarker +3 -0
- data/examples/self_test/rails/script/performance/profiler +3 -0
- data/examples/self_test/rails/script/performance/request +3 -0
- data/examples/self_test/rails/script/plugin +3 -0
- data/examples/self_test/rails/script/process/inspector +3 -0
- data/examples/self_test/rails/script/process/reaper +3 -0
- data/examples/self_test/rails/script/process/spawner +3 -0
- data/examples/self_test/rails/script/runner +3 -0
- data/examples/self_test/rails/script/server +3 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/.specification +148 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/History.txt +324 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/MIT-LICENSE.txt +19 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/README.rdoc +85 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/Rakefile +151 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/install.rb +1 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/configuration.rb +98 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/area.rb +31 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/element.rb +33 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/field.rb +403 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/form.rb +103 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/label.rb +31 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/link.rb +92 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/elements/select_option.rb +35 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/area_locator.rb +38 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/button_locator.rb +54 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_by_id_locator.rb +37 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_labeled_locator.rb +56 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_locator.rb +25 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/field_named_locator.rb +41 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/form_locator.rb +19 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/label_locator.rb +34 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/link_locator.rb +66 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/locator.rb +20 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators/select_option_locator.rb +59 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/locators.rb +20 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/logging.rb +21 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_content.rb +73 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_selector.rb +74 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_tag.rb +21 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers/have_xpath.rb +147 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/matchers.rb +4 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/methods.rb +61 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/mime.rb +29 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/save_and_open_page.rb +50 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/scope.rb +350 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/session.rb +281 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml/hpricot.rb +19 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml/nokogiri.rb +76 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml/rexml.rb +24 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core/xml.rb +115 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core.rb +14 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/blank.rb +58 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/deprecate.rb +8 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/detect_mapped.rb +12 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/meta_class.rb +6 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/nil_to_param.rb +5 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/core_extensions/tcp_socket.rb +27 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/mechanize.rb +74 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/merb.rb +9 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/merb_session.rb +65 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/rack.rb +24 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/rails.rb +105 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/rspec-rails.rb +13 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/application_server.rb +71 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/button.js +12 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/label.js +16 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webrat.js +5 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webratlink.js +9 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webratlinkwithin.js +15 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/location_strategy_javascript/webratselectwithoption.js +5 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_content.rb +66 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_selector.rb +49 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_tag.rb +72 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers/have_xpath.rb +45 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/matchers.rb +4 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/merb_application_server.rb +48 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/rails_application_server.rb +42 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/selenium_extensions.js +6 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/selenium_rc_server.rb +80 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/selenium_session.rb +241 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium/sinatra_application_server.rb +35 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/selenium.rb +80 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat/sinatra.rb +44 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/lib/webrat.rb +34 -0
- data/examples/self_test/rails/vendor/gems/webrat-0.4.4/vendor/selenium-server.jar +0 -0
- data/examples/self_test/simple/features/call_foo.feature +4 -0
- data/examples/self_test/simple/features/call_foo_and_bar_together.feature +5 -0
- data/examples/self_test/simple/features/call_foo_from_background_then_bar.feature +7 -0
- data/examples/self_test/simple/features/call_foo_from_background_then_bar_then_baz.feature +10 -0
- data/examples/self_test/simple/features/call_foo_then_bar.feature +7 -0
- data/examples/self_test/simple/features/call_foo_then_bar_from_scenario_outline_examples.feature +9 -0
- data/examples/self_test/simple/features/fail.feature +10 -0
- data/examples/self_test/simple/features/step_definitions/main_steps.rb +15 -0
- data/examples/self_test/simple/lib/bar.rb +5 -0
- data/examples/self_test/simple/lib/baz.rb +5 -0
- data/examples/self_test/simple/lib/foo.rb +9 -0
- data/features/call_foo.feature +0 -0
- data/features/coverage_of.feature +44 -0
- data/features/fail.feature +54 -0
- data/features/lazy_run.feature +79 -0
- data/features/lazy_run_per_scenario.feature +113 -0
- data/features/lazy_run_per_scenario_outline_example.feature +31 -0
- data/features/lazy_run_triggered_by_rails_view_change.feature +42 -0
- data/features/run.feature +25 -0
- data/features/show_recordings.feature +28 -0
- data/features/step_definitions/main_steps.rb +36 -0
- data/features/support/env.rb +48 -0
- data/lib/cucover/cli.rb +26 -0
- data/lib/cucover/cli_commands/coverage_of.rb +36 -0
- data/lib/cucover/cli_commands/cucumber.rb +25 -0
- data/lib/cucover/cli_commands/show_recordings.rb +29 -0
- data/lib/cucover/controller.rb +28 -0
- data/lib/cucover/cucumber_hooks.rb +29 -0
- data/lib/cucover/logging_config.rb +16 -0
- data/lib/cucover/monkey.rb +14 -0
- data/lib/cucover/rails.rb +20 -0
- data/lib/cucover/recorder.rb +37 -0
- data/lib/cucover/recording/covered_file.rb +53 -0
- data/lib/cucover/recording.rb +64 -0
- data/lib/cucover/store.rb +70 -0
- data/lib/cucover.rb +35 -212
- data/lib/dependencies.rb +10 -0
- data/spec/cucover/cli_spec.rb +31 -0
- data/spec/cucover/controller_spec.rb +16 -0
- data/spec/cucover/recording/covered_file_spec.rb +20 -0
- data/spec/cucover/store_spec.rb +28 -0
- data/spec/spec_helper.rb +7 -0
- data/tmp/.gitignore +0 -0
- 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
|
data/lib/cucover/cli.rb
ADDED
@@ -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
|