guard-cucumber 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
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