polyamory 0.0.2
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 +35 -0
- data/bin/polyamory +24 -0
- data/lib/polyamory.rb +204 -0
- metadata +66 -0
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Polyamory
|
2
|
+
|
3
|
+
Polyamory loves *all* of your testing frameworks. It is a command-line tool that is able to run your test files regardless of the framework being used.
|
4
|
+
|
5
|
+
Features:
|
6
|
+
|
7
|
+
* easily run the full test suite for any project: just type `polyamory`
|
8
|
+
* use a directory name on the command line to run everything inside that directory
|
9
|
+
* use a keyword to run all test files which contain that word
|
10
|
+
* Bundler support
|
11
|
+
|
12
|
+
Frameworks supported:
|
13
|
+
|
14
|
+
* Cucumber in `"features/**/*.feature"`
|
15
|
+
* RSpec + Shoulda in `"spec/**/*_spec.rb"`
|
16
|
+
* test/unit, Shoulda, or anything else in `"test/**/*_test.rb"`
|
17
|
+
|
18
|
+
## Examples
|
19
|
+
|
20
|
+
Here, `polyamory` is aliased as `pam` for brevity.
|
21
|
+
|
22
|
+
# run everything
|
23
|
+
$ pam
|
24
|
+
> rspec spec &&
|
25
|
+
cucumber -f progress -t ~@wip features &&
|
26
|
+
polyamory -t test
|
27
|
+
|
28
|
+
# everyting inside a single directory
|
29
|
+
$ pam test/unit
|
30
|
+
> polyamory -t test/unit
|
31
|
+
|
32
|
+
# run test files matching keyword
|
33
|
+
$ pam user
|
34
|
+
> polyamory -t spec/models/user_spec.rb spec/controllers/user_controller.rb &&
|
35
|
+
cucumber -f progress -t ~@wip features/user_registration.feature
|
data/bin/polyamory
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
if ARGV.delete '-t'
|
3
|
+
test_files = ARGV.map { |arg|
|
4
|
+
unless arg.index('-') == 0
|
5
|
+
if File.directory? arg
|
6
|
+
Dir["#{arg}/**/*_test.rb"]
|
7
|
+
else
|
8
|
+
arg
|
9
|
+
end
|
10
|
+
end
|
11
|
+
}.compact.flatten
|
12
|
+
|
13
|
+
if test_files.empty?
|
14
|
+
warn "polyamory: nothing to load"
|
15
|
+
exit 1
|
16
|
+
else
|
17
|
+
test_files.each { |f| load f }
|
18
|
+
end
|
19
|
+
else
|
20
|
+
require 'polyamory'
|
21
|
+
options = {}
|
22
|
+
options[:noop] = !!ARGV.delete('-n')
|
23
|
+
Polyamory.run ARGV, Dir.pwd, options
|
24
|
+
end
|
data/lib/polyamory.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
class Polyamory
|
4
|
+
def self.run(*args)
|
5
|
+
new(*args).run
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(names, root, options = {})
|
9
|
+
@names = names
|
10
|
+
@root = Pathname.new(root).expand_path
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def noop?
|
15
|
+
@options[:noop]
|
16
|
+
end
|
17
|
+
|
18
|
+
def file_exists?(path)
|
19
|
+
(@root + path).exist?
|
20
|
+
end
|
21
|
+
|
22
|
+
def bundler?
|
23
|
+
file_exists? 'Gemfile'
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_dir
|
27
|
+
@root + 'test'
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_glob(dir = test_dir)
|
31
|
+
"#{dir}/**/*_test.rb"
|
32
|
+
end
|
33
|
+
|
34
|
+
def spec_dir
|
35
|
+
@root + 'spec'
|
36
|
+
end
|
37
|
+
|
38
|
+
def spec_glob(dir = spec_dir)
|
39
|
+
"#{dir}/**/*_spec.rb"
|
40
|
+
end
|
41
|
+
|
42
|
+
def features_dir
|
43
|
+
@root + 'features'
|
44
|
+
end
|
45
|
+
|
46
|
+
def features_glob(dir = features_dir)
|
47
|
+
"#{dir}/**/*.feature"
|
48
|
+
end
|
49
|
+
|
50
|
+
class Pathname < Pathname
|
51
|
+
attr_reader :root
|
52
|
+
|
53
|
+
def self.glob(patterns, root)
|
54
|
+
patterns = Array(patterns)
|
55
|
+
Dir[*patterns].map do |path|
|
56
|
+
self.new(path, root)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize(path, root_path = nil)
|
61
|
+
super(path)
|
62
|
+
self.root = root_path
|
63
|
+
end
|
64
|
+
|
65
|
+
def root=(path)
|
66
|
+
@relativized = nil
|
67
|
+
@root = path
|
68
|
+
end
|
69
|
+
|
70
|
+
def relative
|
71
|
+
@relativized ||= relative_path_from root
|
72
|
+
end
|
73
|
+
|
74
|
+
def =~(pattern)
|
75
|
+
relative.to_s =~ pattern
|
76
|
+
end
|
77
|
+
|
78
|
+
def +(other)
|
79
|
+
result = self.class.new(plus(@path, other.to_s))
|
80
|
+
result.root ||= self
|
81
|
+
result
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def find_files
|
86
|
+
all_paths = Pathname.glob([test_glob, spec_glob, features_glob], @root)
|
87
|
+
|
88
|
+
if @names.any?
|
89
|
+
@names.map { |name|
|
90
|
+
path = @root + name
|
91
|
+
pattern = /\b#{Regexp.escape name}(\b|_)/
|
92
|
+
|
93
|
+
if path.directory? or not path.extname.empty?
|
94
|
+
path
|
95
|
+
else
|
96
|
+
all_paths.select { |p| p =~ pattern }
|
97
|
+
end
|
98
|
+
}.flatten
|
99
|
+
else
|
100
|
+
[test_dir, spec_dir, features_dir].select { |p| p.directory? }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def relativize(paths)
|
105
|
+
Array(paths).map { |p| p.relative }
|
106
|
+
end
|
107
|
+
|
108
|
+
def run
|
109
|
+
paths = relativize(find_files)
|
110
|
+
if paths.empty?
|
111
|
+
warn "nothing found to run"
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
|
115
|
+
jobs = index_by_path_prefix(paths).map do |prefix, files|
|
116
|
+
[runner_for_prefix(prefix), *files].flatten
|
117
|
+
end
|
118
|
+
|
119
|
+
prepare_env
|
120
|
+
execute_jobs jobs
|
121
|
+
end
|
122
|
+
|
123
|
+
def runner_for_prefix(prefix)
|
124
|
+
case prefix
|
125
|
+
when 'features' then %w[cucumber -f progress -t ~@wip]
|
126
|
+
when 'spec' then detect_rspec_version
|
127
|
+
when 'test' then %w[polyamory -t]
|
128
|
+
else
|
129
|
+
raise ArgumentError, "don't know a runner for #{prefix}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def detect_rspec_version
|
134
|
+
helper = 'spec/spec_helper.rb'
|
135
|
+
|
136
|
+
if file_exists? 'spec/spec.opts' or file_exists? 'lib/tasks/rspec.rake'
|
137
|
+
'spec'
|
138
|
+
elsif file_exists? '.rspec'
|
139
|
+
'rspec'
|
140
|
+
elsif helper.exist?
|
141
|
+
File.open(helper) do |file|
|
142
|
+
while file.gets
|
143
|
+
return $&.downcase if $_ =~ /\bR?Spec\b/
|
144
|
+
end
|
145
|
+
end
|
146
|
+
'rspec'
|
147
|
+
else
|
148
|
+
'rspec'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def index_by_path_prefix(paths)
|
153
|
+
paths.inject(Hash.new {|h,k| h[k] = [] }) do |index, path|
|
154
|
+
prefix = path.to_s.split('/', 2).first
|
155
|
+
index[prefix] << path
|
156
|
+
index
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def execute_jobs(jobs)
|
161
|
+
if jobs.size > 1
|
162
|
+
jobs.each { |j| cmd(j, true) }
|
163
|
+
else
|
164
|
+
cmd(jobs.first)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def prepare_cmdline(args)
|
169
|
+
args = args.map { |p| p.to_s }
|
170
|
+
args = %w[bundle exec] + args if args.first != 'polyamory' and bundler?
|
171
|
+
args
|
172
|
+
end
|
173
|
+
|
174
|
+
def cmd(args, many = false)
|
175
|
+
args = prepare_cmdline(args)
|
176
|
+
puts args.join(' ')
|
177
|
+
|
178
|
+
# TODO: hack; make this configurable, use bundler
|
179
|
+
with_rubyopt(args.first == 'polyamory' ? '-rubygems' : nil) do
|
180
|
+
if many
|
181
|
+
system(*args)
|
182
|
+
exit $?.exitstatus unless $?.success?
|
183
|
+
else
|
184
|
+
exec(*args)
|
185
|
+
end
|
186
|
+
end unless noop?
|
187
|
+
end
|
188
|
+
|
189
|
+
def with_rubyopt(value)
|
190
|
+
old_value = ENV['RUBYOPT']
|
191
|
+
ENV['RUBYOPT'] = "#{value} #{old_value}"
|
192
|
+
|
193
|
+
begin
|
194
|
+
yield
|
195
|
+
ensure
|
196
|
+
ENV['RUBYOPT'] = old_value
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def prepare_env
|
201
|
+
# TODO: make this per-job
|
202
|
+
ENV['RUBYOPT'] = ENV['RUBYOPT'].gsub(/(^| )-w( |$)/, '\1\2') if ENV['RUBYOPT']
|
203
|
+
end
|
204
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: polyamory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- "Mislav Marohni\xC4\x87"
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-12-30 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: A tool that knows how to run your tests regardless of framework
|
22
|
+
email: mislav.marohnic@gmail.com
|
23
|
+
executables:
|
24
|
+
- polyamory
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- bin/polyamory
|
31
|
+
- lib/polyamory.rb
|
32
|
+
- README.md
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/mislav/polyamory
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
segments:
|
48
|
+
- 0
|
49
|
+
version: "0"
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.7
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Runs your tests
|
65
|
+
test_files: []
|
66
|
+
|