guard-cucumber 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
- # Guard::Cucumber
2
-
3
- ![travis-ci](http://travis-ci.org/netzpirat/guard-cucumber.png)
1
+ # Guard::Cucumber [![Build Status](https://secure.travis-ci.org/netzpirat/guard-cucumber.png)](http://travis-ci.org/netzpirat/guard-cucumber)
4
2
 
5
3
  Guard::Cucumber allows you to automatically run Cucumber features when files are modified.
6
4
 
7
- Tested on MRI Ruby 1.8.7, 1.9.2 and the latest versions of JRuby & Rubinius.
5
+ Tested on MRI Ruby 1.8.7, 1.9.2, REE and the latest versions of JRuby & Rubinius.
8
6
 
9
7
  If you have any questions please join us on our [Google group](http://groups.google.com/group/guard-dev) or on `#guard` (irc.freenode.net).
10
8
 
@@ -14,21 +12,15 @@ Please be sure to have [Guard](https://github.com/guard/guard) installed before
14
12
 
15
13
  Install the gem:
16
14
 
17
- ```bash
18
- $ gem install guard-cucumber
19
- ```
15
+ $ gem install guard-cucumber
20
16
 
21
17
  Add it to your `Gemfile`, preferably inside the test group:
22
18
 
23
- ```ruby
24
- gem 'guard-cucumber'
25
- ```
19
+ gem 'guard-cucumber'
26
20
 
27
21
  Add the default Guard::Cucumber template to your `Guardfile` by running this command:
28
22
 
29
- ```bash
30
- $ guard init cucumber
31
- ```
23
+ $ guard init cucumber
32
24
 
33
25
  ## Usage
34
26
 
@@ -38,13 +30,11 @@ Please read the [Guard usage documentation](https://github.com/guard/guard#readm
38
30
 
39
31
  Guard::Cucumber can be adapted to all kind of projects and comes with a default template that looks like this:
40
32
 
41
- ```ruby
42
- guard 'cucumber' do
43
- watch(%r{^features/.+\.feature$})
44
- watch(%r{^features/support/.+$}) { 'features' }
45
- watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
46
- end
47
- ```
33
+ guard 'cucumber' do
34
+ watch(%r{^features/.+\.feature$})
35
+ watch(%r{^features/support/.+$}) { 'features' }
36
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
37
+ end
48
38
 
49
39
  Expressed in plain English, this configuration tells Guard::Cucumber:
50
40
 
@@ -60,44 +50,39 @@ Please read the [Guard documentation](http://github.com/guard/guard#readme) for
60
50
 
61
51
  You can pass any of the standard Cucumber CLI options using the :cli option:
62
52
 
63
- ```ruby
64
- guard 'cucumber', :cli => '-c --drb --port 1234 --profile guard' do
65
- end
66
- ```
53
+ guard 'cucumber', :cli => '-c --drb --port 1234 --profile guard'
67
54
 
68
55
  Former `:color`, `:drb`, `:port` and `:profile` options are thus deprecated and have no effect anymore.
69
56
 
70
57
  ### List of available options
71
58
 
72
- ```ruby
73
- :cli => '--profile guard -c' # Pass arbitrary Cucumber CLI arguments,
74
- # default: '--no-profile --color --format progress --strict'
59
+ :cli => '--profile guard -c' # Pass arbitrary Cucumber CLI arguments,
60
+ # default: '--no-profile --color --format progress --strict'
75
61
 
76
- :bundler => false # Don't use "bundle exec" to run the Cucumber command
77
- # default: true
62
+ :bundler => false # Don't use "bundle exec" to run the Cucumber command
63
+ # default: true
78
64
 
79
- :rvm => ['1.8.7', '1.9.2'] # Directly run your features on multiple ruby versions
80
- # default: nil
65
+ :rvm => ['1.8.7', '1.9.2'] # Directly run your features on multiple ruby versions
66
+ # default: nil
81
67
 
82
- :notification => false # Don't display Growl (or Libnotify) notification
83
- # default: true
68
+ :notification => false # Don't display Growl (or Libnotify) notification
69
+ # default: true
84
70
 
85
- :all_after_pass => false # Don't run all features after changed features pass
86
- # default: true
71
+ :all_after_pass => false # Don't run all features after changed features pass
72
+ # default: true
87
73
 
88
- :all_on_start => false # Don't run all the features at startup
89
- # default: true
74
+ :all_on_start => false # Don't run all the features at startup
75
+ # default: true
90
76
 
91
- :keep_failed => false # Keep failed features until them pass
92
- # default: true
77
+ :keep_failed => false # Keep failed features until they pass
78
+ # default: true
93
79
 
94
- :run_all => { :cli => "-p" } # Override any option when running all specs
95
- # default: {}
80
+ :run_all => { :cli => "-p" } # Override any option when running all specs
81
+ # default: {}
96
82
 
97
- :change_format => 'pretty' # Use a different cucumber format when running individual features
98
- # This replaces the Cucumber --format option within the :cli option
99
- # default: nil
100
- ```
83
+ :change_format => 'pretty' # Use a different cucumber format when running individual features
84
+ # This replaces the Cucumber --format option within the :cli option
85
+ # default: nil
101
86
 
102
87
  ## Cucumber configuration
103
88
 
@@ -117,9 +102,7 @@ If you want to configure Cucumber from Guard solely, then you should pass `--no-
117
102
 
118
103
  Since guard-cucumber version 0.3.2, the default `:cli` options are:
119
104
 
120
- ```ruby
121
- :cli => '--no-profile --color --format progress --strict'
122
- ```
105
+ :cli => '--no-profile --color --format progress --strict'
123
106
 
124
107
  This default configuration has been chosen to avoid strange behavior when mixing configurations form
125
108
  the cucumber.yml default profile with the guard-cucumber `:cli` option.
@@ -131,9 +114,7 @@ You can safely remove `config/cucumber.yml`, since all configuration is done in
131
114
  If you're using different profiles with Cucumber then you should create a profile for Guard in cucumber.yml,
132
115
  something like this:
133
116
 
134
- ```
135
- guard: --format progress --strict --tags ~@wip
136
- ```
117
+ guard: --format progress --strict --tags ~@wip
137
118
 
138
119
  Now you want to make guard-cucumber use that profile by passing '--profile guard' to the `:cli`.
139
120
 
@@ -142,30 +123,34 @@ Now you want to make guard-cucumber use that profile by passing '--profile guard
142
123
  To use Guard::Cucumber with [Spork](https://github.com/timcharper/spork), you should install
143
124
  [Guard::Spork](https://github.com/guard/guard-spork) and use the following configuration:
144
125
 
145
- ```ruby
146
- guard 'spork' do
147
- watch('config/application.rb')
148
- watch('config/environment.rb')
149
- watch(%r{^config/environments/.*\.rb$})
150
- watch(%r{^config/initializers/.*\.rb$})
151
- watch('spec/spec_helper.rb')
152
- end
153
-
154
- guard 'cucumber', :cli => '--drb --format progress --no-profile' do
155
- watch(%r{^features/.+\.feature$})
156
- watch(%r{^features/support/.+$}) { 'features' }
157
- watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
158
- end
159
- ```
126
+ guard 'spork' do
127
+ watch('config/application.rb')
128
+ watch('config/environment.rb')
129
+ watch(%r{^config/environments/.*\.rb$})
130
+ watch(%r{^config/initializers/.*\.rb$})
131
+ watch('spec/spec_helper.rb')
132
+ end
133
+
134
+ guard 'cucumber', :cli => '--drb --format progress --no-profile' do
135
+ watch(%r{^features/.+\.feature$})
136
+ watch(%r{^features/support/.+$}) { 'features' }
137
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
138
+ end
160
139
 
161
140
  There is a section with alternative configurations on the [Wiki](https://github.com/netzpirat/guard-cucumber/wiki/Spork-configurations).
162
141
 
163
142
  ## Development
164
143
 
165
- - Source hosted at [GitHub](https://github.com/netzpirat/guard-cucumber)
166
- - Report issues and feature requests to [GitHub Issues](https://github.com/netzpirat/guard-cucumber/issues)
144
+ - Documentation hosted at [RubyDoc](http://rubydoc.info/gems/guard-cucumber/frames).
145
+ - Source hosted at [GitHub](https://github.com/netzpirat/guard-cucumber).
146
+ - Report issues and feature requests to [GitHub Issues](https://github.com/netzpirat/guard-cucumber/issues).
147
+
148
+ Pull requests are very welcome! Please try to follow these simple "rules", though:
167
149
 
168
- Pull requests are very welcome! Make sure your patches are well tested.
150
+ - Please create a topic branch for every separate change you make.
151
+ - Make sure your patches are well tested.
152
+ - Update the README (if applicable).
153
+ - Please **do not change** the version number.
169
154
 
170
155
  For questions please join us on our [Google group](http://groups.google.com/group/guard-dev) or on `#guard` (irc.freenode.net).
171
156
 
@@ -3,30 +3,56 @@ require 'guard/guard'
3
3
  require 'cucumber'
4
4
 
5
5
  module Guard
6
+
7
+ # The Cucumber guard that gets notifications about the following
8
+ # Guard events: `start`, `stop`, `reload`, `run_all` and `run_on_change`.
9
+ #
6
10
  class Cucumber < Guard
7
11
 
8
12
  autoload :Runner, 'guard/cucumber/runner'
9
13
  autoload :Inspector, 'guard/cucumber/inspector'
10
14
 
11
- def initialize(watchers=[], options={})
15
+ # Initialize Guard::Cucumber.
16
+ #
17
+ # @param [Array<Guard::Watcher>] watchers the watchers in the Guard block
18
+ # @param [Hash] options the options for the Guard
19
+ # @option options [String] :cli any arbitrary Cucumber CLI arguments
20
+ # @option options [Boolean] :bundler use bundler or not
21
+ # @option options [Array<String>] :rvm a list of rvm version to use for the test
22
+ # @option options [Boolean] :notification show notifications
23
+ # @option options [Boolean] :all_after_pass run all features after changed features pass
24
+ # @option options [Boolean] :all_on_start run all the features at startup
25
+ # @option options [Boolean] :keep_failed Keep failed features until they pass
26
+ # @option options [Boolean] :run_all run override any option when running all specs
27
+ # @option options [Boolean] :change_format use a different cucumber format when running individual features
28
+ #
29
+ def initialize(watchers = [], options = { })
12
30
  super
13
31
  @options = {
14
32
  :all_after_pass => true,
15
- :all_on_start => true,
16
- :keep_failed => true,
17
- :cli => '--no-profile --color --format progress --strict'
33
+ :all_on_start => true,
34
+ :keep_failed => true,
35
+ :cli => '--no-profile --color --format progress --strict'
18
36
  }.update(options)
19
37
 
20
- @last_failed = false
38
+ @last_failed = false
21
39
  @failed_paths = []
22
40
  end
23
41
 
42
+ # Gets called once when Guard starts.
43
+ #
44
+ # @return [Boolean] when the start was successful
45
+ #
24
46
  def start
25
47
  run_all if @options[:all_on_start]
26
48
  end
27
49
 
50
+ # Gets called when all specs should be run.
51
+ #
52
+ # @return [Boolean] when running all specs was successful
53
+ #
28
54
  def run_all
29
- passed = Runner.run(['features'], options.merge(options[:run_all] || {}).merge(:message => 'Running all features'))
55
+ passed = Runner.run(['features'], options.merge(options[:run_all] || { }).merge(:message => 'Running all features'))
30
56
 
31
57
  if passed
32
58
  @failed_paths = []
@@ -35,21 +61,30 @@ module Guard
35
61
  end
36
62
 
37
63
  @last_failed = !passed
38
-
64
+
39
65
  passed
40
66
  end
41
67
 
68
+ # Gets called when the Guard should reload itself.
69
+ #
70
+ # @return [Boolean] when reloading was successful
71
+ #
42
72
  def reload
43
73
  @failed_paths = []
44
-
74
+
45
75
  true
46
76
  end
47
77
 
78
+ # Gets called when watched paths and files have changes.
79
+ #
80
+ # @param [Array<String>] paths the changed paths and files
81
+ # @return [Boolean] when running the changed specs was successful
82
+ #
48
83
  def run_on_change(paths)
49
84
  paths += @failed_paths if @options[:keep_failed]
50
- paths = Inspector.clean(paths)
85
+ paths = Inspector.clean(paths)
51
86
  options = @options[:change_format] ? change_format(@options[:change_format]) : @options
52
- passed = Runner.run(paths, paths.include?('features') ? options.merge({ :message => 'Running all features' }) : options)
87
+ passed = Runner.run(paths, paths.include?('features') ? options.merge({ :message => 'Running all features' }) : options)
53
88
 
54
89
  if passed
55
90
  # clean failed paths memory
@@ -62,12 +97,15 @@ module Guard
62
97
  # track whether the changed feature failed for the next change
63
98
  @last_failed = true
64
99
  end
65
-
66
- passed
67
100
  end
68
101
 
69
102
  private
70
103
 
104
+ # Read the failed features that from `rerun.txt`
105
+ #
106
+ # @see Guard::Cucumber::NotificationFormatter#write_rerun_features
107
+ # @return [Array<String>] the list of features
108
+ #
71
109
  def read_failed_features
72
110
  failed = []
73
111
 
@@ -79,6 +117,11 @@ module Guard
79
117
  failed
80
118
  end
81
119
 
120
+ # Change the `--format` cli option.
121
+ #
122
+ # @param [String] format the new format
123
+ # @return [Hash] the new options
124
+ #
82
125
  def change_format(format)
83
126
  cli_parts = @options[:cli].split(" ")
84
127
  cli_parts.each_with_index do |part, index|
@@ -1,8 +1,18 @@
1
1
  module Guard
2
2
  class Cucumber
3
+
4
+ # The inspector verifies of the changed paths are valid
5
+ # for Guard::Cucumber.
6
+ #
3
7
  module Inspector
4
8
  class << self
5
9
 
10
+ # Clean the changed paths and return only valid
11
+ # Cucumber features.
12
+ #
13
+ # @param [Array<String>] paths the changed paths
14
+ # @return [Array<String>] the valid feature files
15
+ #
6
16
  def clean(paths)
7
17
  paths.uniq!
8
18
  paths.compact!
@@ -12,24 +22,48 @@ module Guard
12
22
  paths
13
23
  end
14
24
 
15
- private
25
+ private
16
26
 
27
+ # Tests if the file is the features folder.
28
+ #
29
+ # @param [String] file the file
30
+ # @return [Boolean] when the file is the feature folder
31
+ #
17
32
  def cucumber_folder?(path)
18
33
  path.match(/^\/?features/) && !path.match(/\..+$/)
19
34
  end
20
35
 
36
+ # Tests if the file is valid.
37
+ #
38
+ # @param [String] file the file
39
+ # @return [Boolean] when the file valid
40
+ #
21
41
  def cucumber_file?(path)
22
42
  cucumber_files.include?(path.split(':').first)
23
43
  end
24
44
 
45
+ # Scans the project and keeps a list of all
46
+ # feature files in the `features` directory.
47
+ #
48
+ # @see #clear_jasmine_specs
49
+ # @return [Array<String>] the valid files
50
+ #
25
51
  def cucumber_files
26
52
  @cucumber_files ||= Dir.glob('features/**/*.feature')
27
53
  end
28
54
 
55
+ # Clears the list of features in this project.
56
+ #
29
57
  def clear_cucumber_files_list
30
58
  @cucumber_files = nil
31
59
  end
32
60
 
61
+ # Checks if the given path is already contained
62
+ # in the paths list.
63
+ #
64
+ # @param [Sting] path the path to test
65
+ # @param [Array<String>] paths the list of paths
66
+ #
33
67
  def included_in_other_path?(path, paths)
34
68
  paths = paths.select { |p| p != path }
35
69
  paths.any? { |p| path.include?(p) && (path.gsub(p, '')).include?('/') }
@@ -5,27 +5,52 @@ require 'cucumber/formatter/io'
5
5
 
6
6
  module Guard
7
7
  class Cucumber
8
+
9
+ # The notification formatter is a Cucumber formatter that Guard::Cucumber
10
+ # passes to the Cucumber binary. It writes the `rerun.txt` file with the failed features
11
+ # an creates system notifications.
12
+ #
13
+ # @see https://github.com/cucumber/cucumber/wiki/Custom-Formatters
14
+ #
8
15
  class NotificationFormatter
9
16
  include ::Cucumber::Formatter::Console
10
17
 
11
18
  attr_reader :step_mother
12
19
 
20
+ # Initialize the formatter.
21
+ #
22
+ # @param [Cucumber::Runtime] step_mother the step mother
23
+ # @param [String, IO] path_or_io the path or IO to the feature file
24
+ # @param [Hash] options the options
25
+ #
13
26
  def initialize(step_mother, path_or_io, options)
14
27
  @options = options
15
28
  @file_names = []
16
29
  @step_mother = step_mother
17
30
  end
18
31
 
32
+ # Notification after all features have completed.
33
+ #
34
+ # @param [Array[Cucumber::Ast::Feature]] features the ran features
35
+ #
19
36
  def after_features(features)
20
37
  notify_summary
21
38
  write_rerun_features if !@file_names.empty?
22
39
  end
23
40
 
41
+ # Before a feature gets run.
42
+ #
43
+ # @param [Cucumber::Ast::FeatureElement] feature_element
44
+ #
24
45
  def before_feature_element(feature_element)
25
46
  @rerun = false
26
47
  @feature_name = feature_element.name
27
48
  end
28
49
 
50
+ # After a feature gets run.
51
+ #
52
+ # @param [Cucumber::Ast::FeatureElement] feature_element
53
+ #
29
54
  def after_feature_element(feature_element)
30
55
  if @rerun
31
56
  @file_names << feature_element.file_colon_line
@@ -33,16 +58,28 @@ module Guard
33
58
  end
34
59
  end
35
60
 
61
+ # Gets called when a step is done.
62
+ #
63
+ # @param [String] keyword the keyword
64
+ # @param [Cucumber::StepMatch] step_match the step match
65
+ # @param [Symbol] status the status of the step
66
+ # @param [Integer] source_indent the source indentation
67
+ # @param [Cucumber::Ast::Background] background the feature background
68
+ #
36
69
  def step_name(keyword, step_match, status, source_indent, background)
37
70
  if [:failed, :pending, :undefined].index(status)
38
71
  @rerun = true
39
72
  step_name = step_match.format_args(lambda { |param| "*#{ param }*" })
73
+
40
74
  ::Guard::Notifier.notify step_name, :title => @feature_name, :image => icon_for(status)
41
75
  end
42
76
  end
43
77
 
44
78
  private
45
79
 
80
+ # Notify the user with a system notification about the
81
+ # result of the feature tests.
82
+ #
46
83
  def notify_summary
47
84
  icon, messages = nil, []
48
85
 
@@ -57,12 +94,19 @@ module Guard
57
94
  ::Guard::Notifier.notify messages.reverse.join(', '), :title => 'Cucumber Results', :image => icon
58
95
  end
59
96
 
97
+ # Writes the `rerun.txt` file containing all failed features.
98
+ #
60
99
  def write_rerun_features
61
100
  File.open('rerun.txt', 'w') do |f|
62
101
  f.puts @file_names.join(' ')
63
102
  end
64
103
  end
65
104
 
105
+ # Gives the icon name to use for the status.
106
+ #
107
+ # @param [Symbol] status the cucumber status
108
+ # @return [Symbol] the Guard notification symbol
109
+ #
66
110
  def icon_for(status)
67
111
  case status
68
112
  when :passed