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 +54 -69
- data/lib/guard/cucumber.rb +55 -12
- data/lib/guard/cucumber/inspector.rb +35 -1
- data/lib/guard/cucumber/notification_formatter.rb +44 -0
- data/lib/guard/cucumber/runner.rb +32 -1
- data/lib/guard/cucumber/version.rb +2 -1
- metadata +36 -9
- data/lib/guard/cucumber.rbc +0 -1753
- data/lib/guard/cucumber/inspector.rbc +0 -1216
- data/lib/guard/cucumber/notification_formatter.rbc +0 -966
- data/lib/guard/cucumber/runner.rbc +0 -1256
- data/lib/guard/cucumber/version.rbc +0 -203
data/README.md
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
# Guard::Cucumber
|
2
|
-
|
3
|
-

|
1
|
+
# Guard::Cucumber [](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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
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
|
-
|
73
|
-
:
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
92
|
-
|
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
|
-
|
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
|
-
|
99
|
-
|
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
|
-
|
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
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
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
|
-
-
|
166
|
-
-
|
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
|
-
|
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
|
|
data/lib/guard/cucumber.rb
CHANGED
@@ -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
|
-
|
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
|
16
|
-
:keep_failed
|
17
|
-
:cli
|
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
|
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
|
85
|
+
paths = Inspector.clean(paths)
|
51
86
|
options = @options[:change_format] ? change_format(@options[:change_format]) : @options
|
52
|
-
passed
|
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
|
-
|
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
|