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.
Files changed (4) hide show
  1. data/README.md +35 -0
  2. data/bin/polyamory +24 -0
  3. data/lib/polyamory.rb +204 -0
  4. metadata +66 -0
@@ -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
@@ -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
@@ -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
+