guard-fast_spec 0.0.1
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/LICENSE +20 -0
- data/README.md +194 -0
- data/lib/guard/fast_spec/formatter.rb +49 -0
- data/lib/guard/fast_spec/formatters/notification_rspec.rb +13 -0
- data/lib/guard/fast_spec/formatters/notification_spec.rb +13 -0
- data/lib/guard/fast_spec/inspector.rb +72 -0
- data/lib/guard/fast_spec/runner.rb +204 -0
- data/lib/guard/fast_spec/templates/Guardfile +12 -0
- data/lib/guard/fast_spec/version.rb +5 -0
- data/lib/guard/fast_spec.rb +77 -0
- metadata +88 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010-2012 Thibaud Guillaume-Gentil
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
# Guard::RSpec [](http://travis-ci.org/guard/guard-rspec)
|
2
|
+
|
3
|
+
RSpec guard allows to automatically & intelligently launch specs when files are modified.
|
4
|
+
|
5
|
+
* Compatible with RSpec 1.x & RSpec 2.x (>= 2.4 needed for the notification feature).
|
6
|
+
* Tested against Ruby 1.8.7, 1.9.2, 1.9.3, REE and the latest versions of JRuby & Rubinius.
|
7
|
+
|
8
|
+
## Install
|
9
|
+
|
10
|
+
Please be sure to have [Guard](https://github.com/guard/guard) installed before continue.
|
11
|
+
|
12
|
+
Install the gem:
|
13
|
+
|
14
|
+
```
|
15
|
+
$ gem install guard-rspec
|
16
|
+
```
|
17
|
+
|
18
|
+
Add it to your Gemfile (inside development group):
|
19
|
+
|
20
|
+
``` ruby
|
21
|
+
group :development do
|
22
|
+
gem 'guard-rspec'
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
Add guard definition to your Guardfile by running this command:
|
27
|
+
|
28
|
+
```
|
29
|
+
$ guard init rspec
|
30
|
+
```
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
Please read [Guard usage doc](https://github.com/guard/guard#readme)
|
35
|
+
|
36
|
+
## Guardfile
|
37
|
+
|
38
|
+
RSpec guard can be really adapted to all kind of projects.
|
39
|
+
|
40
|
+
### Standard RubyGem project
|
41
|
+
|
42
|
+
``` ruby
|
43
|
+
guard 'rspec' do
|
44
|
+
watch(%r{^spec/.+_spec\.rb$})
|
45
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
46
|
+
watch('spec/spec_helper.rb') { "spec" }
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
### Typical Rails app
|
51
|
+
|
52
|
+
``` ruby
|
53
|
+
guard 'rspec' do
|
54
|
+
watch('spec/spec_helper.rb') { "spec" }
|
55
|
+
watch('config/routes.rb') { "spec/routing" }
|
56
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
57
|
+
watch(%r{^spec/.+_spec\.rb$})
|
58
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
59
|
+
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
60
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
61
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
Please read [Guard doc](https://github.com/guard/guard#readme) for more information about the Guardfile DSL.
|
66
|
+
|
67
|
+
## Options
|
68
|
+
|
69
|
+
By default, Guard::RSpec automatically detect your RSpec version (with the `spec_helper.rb` syntax or with Bundler) but you can force the version with the `:version` option:
|
70
|
+
|
71
|
+
``` ruby
|
72
|
+
guard 'rspec', :version => 2 do
|
73
|
+
# ...
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
You can pass any of the standard RSpec CLI options using the `:cli` option:
|
78
|
+
|
79
|
+
``` ruby
|
80
|
+
guard 'rspec', :cli => "--color --format nested --fail-fast --drb" do
|
81
|
+
# ...
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
By default, Guard::RSpec will only look for spec files within `spec` in your project root. You can configure Guard::RSpec to look in additional paths by using the `:spec_paths` option:
|
86
|
+
|
87
|
+
``` ruby
|
88
|
+
guard 'rspec', :spec_paths => ["spec", "vendor/engines/reset/spec"] do
|
89
|
+
# ...
|
90
|
+
end
|
91
|
+
```
|
92
|
+
If you have only one path to look, you can configure `:spec_paths` option with a string:
|
93
|
+
|
94
|
+
``` ruby
|
95
|
+
guard 'rspec', :spec_paths => "test" do
|
96
|
+
# ...
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
|
101
|
+
Former `:color`, `:drb`, `:fail_fast` and `:formatter` options are deprecated and have no effect anymore.
|
102
|
+
|
103
|
+
### List of available options:
|
104
|
+
|
105
|
+
``` ruby
|
106
|
+
:version => 1 # force use RSpec version 1, default: 2
|
107
|
+
:cli => "-c -f doc" # pass arbitrary RSpec CLI arguments, default: "-f progress"
|
108
|
+
:bundler => false # don't use "bundle exec" to run the RSpec command, default: true
|
109
|
+
:binstubs => true # use "bin/rspec" to run the RSpec command (implies :bundler => true), default: false
|
110
|
+
:rvm => ['1.8.7', '1.9.2'] # directly run your specs on multiple Rubies, default: nil
|
111
|
+
:notification => false # display Growl (or Libnotify) notification after the specs are done running, default: true
|
112
|
+
:all_after_pass => false # run all specs after changed specs pass, default: true
|
113
|
+
:all_on_start => false # run all the specs at startup, default: true
|
114
|
+
:keep_failed => false # keep failed specs until they pass, default: true
|
115
|
+
:run_all => { :cli => "-p" } # cli arguments to use when running all specs, default: same as :cli
|
116
|
+
:spec_paths => ["spec"] # specify an array of paths that contain spec files
|
117
|
+
```
|
118
|
+
|
119
|
+
### DRb mode
|
120
|
+
|
121
|
+
When you specify `--drb` within `:cli`, guard-rspec will circumvent the `rspec` command line tool by
|
122
|
+
directly communicating with the RSpec DRb server. This avoids the extra overhead incurred by your
|
123
|
+
shell, bundler and loading RSpec's environment just to send a DRb message. It shaves off a
|
124
|
+
second or two before the specs start to run; they should run almost immediately.
|
125
|
+
|
126
|
+
|
127
|
+
Notification
|
128
|
+
------------
|
129
|
+
|
130
|
+
The notification feature is only available for RSpec < 2, and RSpec >= 2.4 (due to the multiple-formatters feature that was present in RSpec 1, was removed in RSpec 2 and reintroduced in RSpec 2.4). So if you are using a version between 2 and 2.4, you should disable the notification with <tt>:notification => false</tt>. Otherwise, nothing will be displayed in the terminal when your specs will run.
|
131
|
+
|
132
|
+
The best solution is still to update RSpec to the latest version!
|
133
|
+
|
134
|
+
Formatters
|
135
|
+
----------
|
136
|
+
|
137
|
+
The `:formatter` option has been removed since CLI arguments can be passed through the `:cli` option. If you want to use the former Instafail formatter, you need to use [rspec-instafail](http://rubygems.org/gems/rspec-instafail) gem instead:
|
138
|
+
|
139
|
+
``` ruby
|
140
|
+
# in your Gemfile
|
141
|
+
gem 'rspec-instafail'
|
142
|
+
|
143
|
+
# in your Guardfile
|
144
|
+
guard 'rspec', :cli => '-r rspec/instafail -f RSpec::Instafail' do
|
145
|
+
# ...
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
Default formatter is the `progress` formatter (same as RSpec default).
|
150
|
+
|
151
|
+
Running a subset of all specs
|
152
|
+
-----------
|
153
|
+
|
154
|
+
The `:all_on_start` and `:all_after_pass` options cause all specs located in the `spec` directory to be run. If there
|
155
|
+
are some specs you want to skip, you can tag them with RSpec metadata (such as `:slow => true`)
|
156
|
+
and skip them with the cli `--tag` option (i.e. `--tag ~slow`).
|
157
|
+
|
158
|
+
You can also use option :spec_paths to override paths used when running all specs.
|
159
|
+
You can use this feature to create multiple groups of guarded specs with distinct paths, and execute each in own process:
|
160
|
+
|
161
|
+
``` ruby
|
162
|
+
# in your Guardfile
|
163
|
+
group 'acceptance-tests' do
|
164
|
+
guard 'rspec', :spec_paths => ['spec/acceptance'] do
|
165
|
+
# ...
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
group 'unit-tests' do
|
170
|
+
guard 'rspec', :spec_paths => ['spec/models', 'spec/controllers', 'spec/routing'] do
|
171
|
+
# ...
|
172
|
+
end
|
173
|
+
end
|
174
|
+
```
|
175
|
+
|
176
|
+
|
177
|
+
Development
|
178
|
+
-----------
|
179
|
+
|
180
|
+
* Source hosted at [GitHub](https://github.com/guard/guard-rspec)
|
181
|
+
* Report issues/Questions/Feature requests on [GitHub Issues](https://github.com/guard/guard-rspec/issues)
|
182
|
+
|
183
|
+
Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
|
184
|
+
you make.
|
185
|
+
|
186
|
+
Testing
|
187
|
+
-------
|
188
|
+
|
189
|
+
Please run `rake spec:prepare_fixtures` once before launching specs.
|
190
|
+
|
191
|
+
Author
|
192
|
+
------
|
193
|
+
|
194
|
+
[Thibaud Guillaume-Gentil](https://github.com/thibaudgg)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../fast_spec"
|
2
|
+
require 'guard/notifier'
|
3
|
+
|
4
|
+
module Guard::FastSpec::Formatter
|
5
|
+
|
6
|
+
def guard_message(example_count, failure_count, pending_count, duration)
|
7
|
+
message = "#{example_count} examples, #{failure_count} failures"
|
8
|
+
if pending_count > 0
|
9
|
+
message << " (#{pending_count} pending)"
|
10
|
+
end
|
11
|
+
message << "\nin #{round_float(duration)} seconds"
|
12
|
+
message
|
13
|
+
end
|
14
|
+
|
15
|
+
# failed | pending | success
|
16
|
+
def guard_image(failure_count, pending_count)
|
17
|
+
if failure_count > 0
|
18
|
+
:failed
|
19
|
+
elsif pending_count > 0
|
20
|
+
:pending
|
21
|
+
else
|
22
|
+
:success
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def priority(image)
|
27
|
+
{ :failed => 2,
|
28
|
+
:pending => -1,
|
29
|
+
:success => -2
|
30
|
+
}[image]
|
31
|
+
end
|
32
|
+
|
33
|
+
def notify(message, image)
|
34
|
+
Guard::Notifier.notify(message, :title => "FastSpec results", :image => image,
|
35
|
+
:priority => priority(image))
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def round_float(float, decimals = 4)
|
41
|
+
if Float.instance_method(:round).arity == 0 # Ruby 1.8
|
42
|
+
factor = 10**decimals
|
43
|
+
(float*factor).round / factor.to_f
|
44
|
+
else # Ruby 1.9
|
45
|
+
float.round(decimals)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../formatter"
|
2
|
+
require "rspec/core/formatters/base_formatter"
|
3
|
+
|
4
|
+
class Guard::FastSpec::Formatter::NotificationRSpec < RSpec::Core::Formatters::BaseFormatter
|
5
|
+
include Guard::FastSpec::Formatter
|
6
|
+
|
7
|
+
def dump_summary(duration, total, failures, pending)
|
8
|
+
message = guard_message(total, failures, pending, duration)
|
9
|
+
image = guard_image(failures, pending)
|
10
|
+
notify(message, image)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../formatter"
|
2
|
+
require "spec/runner/formatter/base_formatter"
|
3
|
+
|
4
|
+
class Guard::FastSpec::Formatter::NotificationSpec < Spec::Runner::Formatter::BaseFormatter
|
5
|
+
include Guard::FastSpec::Formatter
|
6
|
+
|
7
|
+
def dump_summary(duration, total, failures, pending)
|
8
|
+
message = guard_message(total, failures, pending, duration)
|
9
|
+
image = guard_image(failures, pending)
|
10
|
+
notify(message, image)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Guard
|
2
|
+
class FastSpec
|
3
|
+
class Inspector
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
self.excluded = options[:exclude]
|
7
|
+
self.spec_paths = options[:spec_paths]
|
8
|
+
end
|
9
|
+
|
10
|
+
def excluded
|
11
|
+
@excluded || []
|
12
|
+
end
|
13
|
+
|
14
|
+
def excluded=(pattern)
|
15
|
+
@excluded = Dir[pattern.to_s]
|
16
|
+
end
|
17
|
+
|
18
|
+
def spec_paths
|
19
|
+
@spec_paths || []
|
20
|
+
end
|
21
|
+
|
22
|
+
def spec_paths=(paths)
|
23
|
+
@spec_paths = Array(paths)
|
24
|
+
end
|
25
|
+
|
26
|
+
def clean(paths)
|
27
|
+
paths.uniq!
|
28
|
+
paths.compact!
|
29
|
+
clear_spec_files_list_after do
|
30
|
+
paths = paths.select { |path| should_run_spec_file?(path) }
|
31
|
+
end
|
32
|
+
paths.reject { |p| included_in_other_path?(p, paths) }
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def should_run_spec_file?(path)
|
38
|
+
(spec_file?(path) || feature_file?(path) || spec_folder?(path)) && !excluded.include?(path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def spec_file?(path)
|
42
|
+
spec_files.include?(path)
|
43
|
+
end
|
44
|
+
|
45
|
+
def feature_file?(path)
|
46
|
+
feature_files.include?(path)
|
47
|
+
end
|
48
|
+
|
49
|
+
def spec_folder?(path)
|
50
|
+
path.match(%r{^(#{spec_paths.join("|")})[^\.]*$})
|
51
|
+
end
|
52
|
+
|
53
|
+
def spec_files
|
54
|
+
@spec_files ||= spec_paths.collect { |path| Dir[File.join(path, "**{,/*/**}", "*_spec.rb")] }.flatten
|
55
|
+
end
|
56
|
+
|
57
|
+
def feature_files
|
58
|
+
@feature_files ||= spec_paths.collect { |path| Dir[File.join(path, "**{,/*/**}", "*.feature")] }.flatten
|
59
|
+
end
|
60
|
+
|
61
|
+
def clear_spec_files_list_after
|
62
|
+
yield
|
63
|
+
@spec_files = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def included_in_other_path?(path, paths)
|
67
|
+
(paths - [path]).any? { |p| path.include?(p) && path.sub(p, '').include?('/') }
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,204 @@
|
|
1
|
+
module Guard
|
2
|
+
class FastSpec
|
3
|
+
class Runner
|
4
|
+
attr_reader :fast_spec_version
|
5
|
+
|
6
|
+
FAILURE_EXIT_CODE = 2
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@options = {
|
10
|
+
:bundler => true,
|
11
|
+
:binstubs => false,
|
12
|
+
:rvm => nil,
|
13
|
+
:cli => nil,
|
14
|
+
:notification => true
|
15
|
+
}.merge(options)
|
16
|
+
|
17
|
+
deprecations_warnings
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(paths, options = {})
|
21
|
+
return false if paths.empty?
|
22
|
+
|
23
|
+
message = options[:message] || "Running: #{paths.join(' ')}"
|
24
|
+
UI.info(message, :reset => true)
|
25
|
+
|
26
|
+
options = @options.merge(options)
|
27
|
+
|
28
|
+
if drb_used?
|
29
|
+
run_via_drb(paths, options)
|
30
|
+
else
|
31
|
+
run_via_shell(paths, options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def fast_spec_version
|
36
|
+
@fast_spec_version ||= @options[:version] || determine_fast_spec_version
|
37
|
+
end
|
38
|
+
|
39
|
+
def fast_spec_executable
|
40
|
+
@fast_spec_executable ||= begin
|
41
|
+
exec = fast_spec_class.downcase
|
42
|
+
binstubs? ? "bin/#{exec}" : exec
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def failure_exit_code_supported?
|
47
|
+
@failure_exit_code_supported ||= begin
|
48
|
+
cmd_parts = []
|
49
|
+
cmd_parts << "bundle exec" if bundler?
|
50
|
+
cmd_parts << fast_spec_executable
|
51
|
+
cmd_parts << "--help"
|
52
|
+
`#{cmd_parts.join(' ')}`.include? "--failure-exit-code"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def fast_spec_class
|
57
|
+
@fast_spec_class ||= case fast_spec_version
|
58
|
+
when 1
|
59
|
+
"Spec"
|
60
|
+
when 2
|
61
|
+
"RSpec"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def fast_spec_arguments(paths, options)
|
68
|
+
arg_parts = []
|
69
|
+
arg_parts << options[:cli]
|
70
|
+
arg_parts << "-f progress" if !options[:cli] || options[:cli].split(/[\s=]/).none? { |w| %w[-f --format].include?(w) }
|
71
|
+
if @options[:notification]
|
72
|
+
arg_parts << "-r #{File.dirname(__FILE__)}/formatters/notification_#{fast_spec_class.downcase}.rb"
|
73
|
+
arg_parts << "-f Guard::FastSpec::Formatter::Notification#{fast_spec_class}#{fast_spec_version == 1 ? ":" : " --out "}/dev/null"
|
74
|
+
end
|
75
|
+
arg_parts << "--failure-exit-code #{FAILURE_EXIT_CODE}" if failure_exit_code_supported?
|
76
|
+
arg_parts << paths.join(' ')
|
77
|
+
|
78
|
+
arg_parts.compact.join(' ')
|
79
|
+
end
|
80
|
+
|
81
|
+
def fast_spec_command(paths, options)
|
82
|
+
cmd_parts = []
|
83
|
+
cmd_parts << "rvm #{@options[:rvm].join(',')} exec" if @options[:rvm].respond_to?(:join)
|
84
|
+
cmd_parts << "bundle exec" if bundler?
|
85
|
+
cmd_parts << fast_spec_executable
|
86
|
+
cmd_parts << fast_spec_arguments(paths, options)
|
87
|
+
|
88
|
+
cmd_parts.compact.join(' ')
|
89
|
+
end
|
90
|
+
|
91
|
+
def run_via_shell(paths, options)
|
92
|
+
success = system(fast_spec_command(paths, options))
|
93
|
+
|
94
|
+
if @options[:notification] && !drb_used? && !success && fast_spec_command_exited_with_an_exception?
|
95
|
+
Notifier.notify("Failed", :title => "FastSpec results", :image => :failed, :priority => 2)
|
96
|
+
end
|
97
|
+
|
98
|
+
success
|
99
|
+
end
|
100
|
+
|
101
|
+
def fast_spec_command_exited_with_an_exception?
|
102
|
+
failure_exit_code_supported? && $?.exitstatus != FAILURE_EXIT_CODE
|
103
|
+
end
|
104
|
+
|
105
|
+
# We can optimize this path by hitting up the drb server directly, circumventing the overhead
|
106
|
+
# of the user's shell, bundler and ruby environment.
|
107
|
+
def run_via_drb(paths, options)
|
108
|
+
require "shellwords"
|
109
|
+
argv = fast_spec_arguments(paths, options).shellsplit
|
110
|
+
|
111
|
+
# The user can specify --drb-port for fast_spec, we need to honor it.
|
112
|
+
if idx = argv.index("--drb-port")
|
113
|
+
port = argv[idx + 1].to_i
|
114
|
+
end
|
115
|
+
port = ENV["RSPEC_DRB"] || 8989 unless port && port > 0
|
116
|
+
|
117
|
+
ret = drb_service(port.to_i).run(argv, $stderr, $stdout)
|
118
|
+
ret == 0
|
119
|
+
rescue DRb::DRbConnError
|
120
|
+
# Fall back to the shell runner; we don't want to mangle the environment!
|
121
|
+
run_via_shell(paths, options)
|
122
|
+
end
|
123
|
+
|
124
|
+
def drb_used?
|
125
|
+
if @drb_used.nil?
|
126
|
+
@drb_used = @options[:cli] && @options[:cli].include?('--drb')
|
127
|
+
else
|
128
|
+
@drb_used
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# RSpec 1 & 2 use the same DRb call signature, and we can avoid loading a large chunk of fast_spec
|
133
|
+
# just to let DRb know what to do.
|
134
|
+
#
|
135
|
+
# For reference:
|
136
|
+
#
|
137
|
+
# * RSpec 1: https://github.com/myronmarston/rspec-1/blob/master/lib/spec/runner/drb_command_line.rb
|
138
|
+
# * RSpec 2: https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/drb_command_line.rb
|
139
|
+
def drb_service(port)
|
140
|
+
require "drb/drb"
|
141
|
+
|
142
|
+
# Make sure we have a listener running
|
143
|
+
unless @drb_listener_running
|
144
|
+
begin
|
145
|
+
DRb.start_service("druby://localhost:0")
|
146
|
+
rescue SocketError, Errno::EADDRNOTAVAIL
|
147
|
+
DRb.start_service("druby://:0")
|
148
|
+
end
|
149
|
+
|
150
|
+
@drb_listener_running = true
|
151
|
+
end
|
152
|
+
|
153
|
+
@drb_services ||= {}
|
154
|
+
@drb_services[port.to_i] ||= DRbObject.new_with_uri("druby://127.0.0.1:#{port}")
|
155
|
+
end
|
156
|
+
|
157
|
+
def bundler_allowed?
|
158
|
+
if @bundler_allowed.nil?
|
159
|
+
@bundler_allowed = File.exist?("#{Dir.pwd}/Gemfile")
|
160
|
+
else
|
161
|
+
@bundler_allowed
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def bundler?
|
166
|
+
if @bundler.nil?
|
167
|
+
@bundler = bundler_allowed? && @options[:bundler]
|
168
|
+
else
|
169
|
+
@bundler
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def binstubs?
|
174
|
+
if @binstubs.nil?
|
175
|
+
@binstubs = bundler? && @options[:binstubs]
|
176
|
+
else
|
177
|
+
@binstubs
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def determine_fast_spec_version
|
182
|
+
if File.exist?("#{Dir.pwd}/spec/spec_helper.rb")
|
183
|
+
File.new("#{Dir.pwd}/spec/spec_helper.rb").read.include?("Spec::Runner") ? 1 : 2
|
184
|
+
elsif bundler_allowed?
|
185
|
+
ENV['BUNDLE_GEMFILE'] = "#{Dir.pwd}/Gemfile"
|
186
|
+
`bundle show rspec`.include?("/rspec-1.") ? 1 : 2
|
187
|
+
else
|
188
|
+
2
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def deprecations_warnings
|
193
|
+
[:color, :drb, [:fail_fast, "fail-fast"], [:formatter, "format"]].each do |option|
|
194
|
+
key, value = option.is_a?(Array) ? option : [option, option.to_s]
|
195
|
+
if @options.key?(key)
|
196
|
+
@options.delete(key)
|
197
|
+
UI.info %{DEPRECATION WARNING: The :#{key} option is deprecated. Pass standard command line argument "--#{value}" to FastSpec with the :cli option.}
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
guard 'fast_spec', :cli => "-Ifast_specs -r turnip", :spec_paths => ["fast_specs"], :version => 2 do
|
2
|
+
watch(%r{^fast_specs/roles/.+_spec\.rb$})
|
3
|
+
watch(%r{^fast_specs/lib/(.+)\.rb$}) { |m| "fast_specs/lib/#{m[1]}_spec.rb" }
|
4
|
+
|
5
|
+
watch('fast_specs/spec_helper.rb') { "fast_specs" }
|
6
|
+
watch(%r{^fast_specs/support/(.+)\.rb$}) { "fast_specs" }
|
7
|
+
watch(%r{^fast_specs/roles/(.+)\.rb$}) { |m| "fast_specs/roles/#{m[1]}.rb" }
|
8
|
+
|
9
|
+
watch(%r{^app/roles/(.+)\.rb$}) { |m| "fast_specs/roles/#{m[1]}_spec.rb" }
|
10
|
+
end
|
11
|
+
|
12
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/guard'
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
class FastSpec < Guard
|
6
|
+
autoload :Runner, 'guard/fast_spec/runner'
|
7
|
+
autoload :Inspector, 'guard/fast_spec/inspector'
|
8
|
+
|
9
|
+
def initialize(watchers = [], options = {})
|
10
|
+
super
|
11
|
+
@options = {
|
12
|
+
:all_after_pass => true,
|
13
|
+
:all_on_start => true,
|
14
|
+
:keep_failed => true,
|
15
|
+
:spec_paths => ["fast_spec"],
|
16
|
+
:run_all => {}
|
17
|
+
}.merge(options)
|
18
|
+
@last_failed = false
|
19
|
+
@failed_paths = []
|
20
|
+
|
21
|
+
@inspector = Inspector.new(@options)
|
22
|
+
@runner = Runner.new(@options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Call once when guard starts
|
26
|
+
def start
|
27
|
+
UI.info "Guard::FastSpec is running, with RSpec #{@runner.fast_spec_version}!"
|
28
|
+
run_all if @options[:all_on_start]
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_all
|
32
|
+
passed = @runner.run(@options[:spec_paths], @options[:run_all].merge(:message => 'Running all fast_specs'))
|
33
|
+
|
34
|
+
unless @last_failed = !passed
|
35
|
+
@failed_paths = []
|
36
|
+
else
|
37
|
+
throw :task_has_failed
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def reload
|
42
|
+
@failed_paths = []
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_on_change(paths)
|
46
|
+
paths += @failed_paths if @options[:keep_failed]
|
47
|
+
paths = @inspector.clean(paths)
|
48
|
+
|
49
|
+
if passed = @runner.run(paths)
|
50
|
+
remove_failed(paths)
|
51
|
+
|
52
|
+
# run all the specs if the run before this one failed
|
53
|
+
if @last_failed && @options[:all_after_pass]
|
54
|
+
@last_failed = false
|
55
|
+
run_all
|
56
|
+
end
|
57
|
+
else
|
58
|
+
@last_failed = true
|
59
|
+
add_failed(paths)
|
60
|
+
|
61
|
+
throw :task_has_failed
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def remove_failed(paths)
|
68
|
+
@failed_paths -= paths if @options[:keep_failed]
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_failed(paths)
|
72
|
+
@failed_paths += paths if @options[:keep_failed]
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: guard-fast_spec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thibaud Guillaume-Gentil
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: guard
|
16
|
+
requirement: &70139249986840 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.10.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70139249986840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bundler
|
27
|
+
requirement: &70139249985560 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70139249985560
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &70139249983840 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.7'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70139249983840
|
47
|
+
description: Guard::FastSpec automatically run your specs (much like autotest).
|
48
|
+
email:
|
49
|
+
- thibaud@thibaud.me
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- lib/guard/fast_spec/formatter.rb
|
55
|
+
- lib/guard/fast_spec/formatters/notification_rspec.rb
|
56
|
+
- lib/guard/fast_spec/formatters/notification_spec.rb
|
57
|
+
- lib/guard/fast_spec/inspector.rb
|
58
|
+
- lib/guard/fast_spec/runner.rb
|
59
|
+
- lib/guard/fast_spec/templates/Guardfile
|
60
|
+
- lib/guard/fast_spec/version.rb
|
61
|
+
- lib/guard/fast_spec.rb
|
62
|
+
- LICENSE
|
63
|
+
- README.md
|
64
|
+
homepage: http://rubygems.org/gems/guard-fast_spec
|
65
|
+
licenses: []
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 1.3.6
|
82
|
+
requirements: []
|
83
|
+
rubyforge_project: guard-fast_spec
|
84
|
+
rubygems_version: 1.8.17
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: Guard gem for FastSpec (forked from guard-rspec)
|
88
|
+
test_files: []
|