schmurfy-bacon 1.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/bin/bacon ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+
4
+ require 'optparse'
5
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib/')
6
+ module Bacon; end
7
+
8
+ automatic = false
9
+ output = 'SpecDoxOutput'
10
+
11
+ opts = OptionParser.new("", 24, ' ') { |opts|
12
+ opts.banner = "Usage: bacon [options] [files | -a] [-- untouched arguments]"
13
+
14
+ opts.separator ""
15
+ opts.separator "Ruby options:"
16
+
17
+ lineno = 1
18
+ opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
19
+ eval line, TOPLEVEL_BINDING, "-e", lineno
20
+ lineno += 1
21
+ }
22
+
23
+ opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
24
+ $DEBUG = true
25
+ }
26
+ opts.on("-w", "--warn", "turn warnings on for your script") {
27
+ $-w = true
28
+ }
29
+
30
+ opts.on("-I", "--include PATH",
31
+ "specify $LOAD_PATH (may be used more than once)") { |path|
32
+ $LOAD_PATH.unshift(*path.split(":"))
33
+ }
34
+
35
+ opts.on("-r", "--require LIBRARY",
36
+ "require the library, before executing your script") { |library|
37
+ require library
38
+ }
39
+
40
+ opts.separator ""
41
+ opts.separator "bacon options:"
42
+
43
+ opts.on("-s", "--specdox", "do AgileDox-like output (default)") {
44
+ output = 'SpecDoxOutput'
45
+ }
46
+ opts.on("-q", "--quiet", "do Test::Unit-like non-verbose output") {
47
+ output = 'TestUnitOutput'
48
+ }
49
+ opts.on("-p", "--tap", "do TAP (Test Anything Protocol) output") {
50
+ output = 'TapOutput'
51
+ }
52
+ opts.on("-k", "--knock", "do Knock output") {
53
+ output = 'KnockOutput'
54
+ }
55
+
56
+ opts.on("-o", "--output FORMAT",
57
+ "do FORMAT (SpecDox/TestUnit/Tap) output") { |format|
58
+ output = format + "Output"
59
+ }
60
+ opts.on("-Q", "--no-backtrace", "don't print backtraces") {
61
+ Bacon.const_set :Backtraces, false
62
+ }
63
+
64
+ opts.on("-a", "--automatic", "gather tests from ./test/, include ./lib/") {
65
+ $LOAD_PATH.unshift "lib" if File.directory? "lib"
66
+ automatic = true
67
+ }
68
+
69
+ opts.on('-n', '--name NAME', String,
70
+ "runs tests matching regexp NAME") { |n|
71
+ Bacon.const_set :RestrictName, Regexp.new(n)
72
+ }
73
+
74
+ opts.on('-t', '--testcase TESTCASE', String,
75
+ "runs tests in TestCases matching regexp TESTCASE") { |t|
76
+ Bacon.const_set :RestrictContext, Regexp.new(t)
77
+ }
78
+
79
+ opts.separator ""
80
+ opts.separator "Common options:"
81
+
82
+ opts.on_tail("-h", "--help", "Show this message") do
83
+ puts opts
84
+ exit
85
+ end
86
+
87
+ opts.on_tail("--version", "Show version") do
88
+ require 'bacon'
89
+ puts "bacon #{Bacon::VERSION}"
90
+ exit
91
+ end
92
+
93
+ opts.parse! ARGV
94
+ }
95
+
96
+ files = ARGV
97
+
98
+ if automatic
99
+ files.concat Dir["test/**/test_*.rb"]
100
+ files.concat Dir["test/**/spec_*.rb"]
101
+ files.concat Dir["spec/**/spec_*.rb"]
102
+ files.concat Dir["spec/**/*_spec.rb"]
103
+ end
104
+
105
+ if files.empty?
106
+ puts opts.banner
107
+ exit 1
108
+ end
109
+
110
+ require 'bacon'
111
+
112
+ Bacon.extend Bacon.const_get(output) rescue abort "No such formatter: #{output}"
113
+ Bacon.summary_on_exit
114
+
115
+ files.each { |file|
116
+ load file
117
+ }
118
+
@@ -0,0 +1,36 @@
1
+ Autotest.add_hook :initialize do |att|
2
+ att.clear_mappings
3
+
4
+ att.add_mapping(%r%^(test|spec)/.*\.rb$%) do |filename, _|
5
+ filename
6
+ end
7
+
8
+ att.add_mapping(%r%^lib/(.*)\.rb$%) do |filename, m|
9
+ lib_path = m[1]
10
+ spec = File.basename(lib_path)
11
+ path = File.dirname(lib_path)
12
+ [
13
+ "test/#{path}/test_#{spec}.rb",
14
+ "test/#{path}/spec_#{spec}.rb",
15
+ "spec/#{path}/spec_#{spec}.rb",
16
+ # TODO : decide if the follow 'rspec style' name should be allowed?
17
+ # "spec/#{path}/#{spec}_spec.rb"
18
+ ]
19
+ end
20
+
21
+ false
22
+ end
23
+
24
+ class Autotest::Bacon < Autotest
25
+ def initialize
26
+ super
27
+ self.libs = %w[. lib test spec].join(File::PATH_SEPARATOR)
28
+ end
29
+
30
+ def make_test_cmd(files_to_test)
31
+ args = files_to_test.keys.flatten.join(' ')
32
+ args = '-a' if args.empty?
33
+ # TODO : make regex to pass to -n using values
34
+ "#{ruby} -S bacon -I#{libs} -o TestUnit #{args}"
35
+ end
36
+ end
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + '/bacon.rb'
2
+ class Autotest::BaconRspec < Autotest::Bacon; end
@@ -0,0 +1,9 @@
1
+ Autotest.add_discovery do
2
+ if File.exist?('spec/.bacon') || File.exist?('test/.bacon')
3
+ class Autotest
4
+ @@discoveries.delete_if { |d| d.inspect =~ /rspec/ }
5
+ warn 'Removing rspec from autotest!'
6
+ end
7
+ 'bacon'
8
+ end
9
+ end
data/lib/bacon.rb ADDED
@@ -0,0 +1,300 @@
1
+ # Bacon -- small RSpec clone.
2
+ #
3
+ # "Truth will sooner come out from error than from confusion." ---Francis Bacon
4
+
5
+ # Copyright (C) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
6
+ #
7
+ # Bacon is freely distributable under the terms of an MIT-style license.
8
+ # See COPYING or http://www.opensource.org/licenses/mit-license.php.
9
+
10
+ module Bacon
11
+ Counter = Hash.new(0)
12
+ ErrorLog = ""
13
+ Shared = Hash.new { |_, name|
14
+ raise NameError, "no such context: #{name.inspect}"
15
+ }
16
+
17
+ RestrictName = // unless defined? RestrictName
18
+ RestrictContext = // unless defined? RestrictContext
19
+
20
+ Backtraces = true unless defined? Backtraces
21
+
22
+
23
+ Dir[File.expand_path('../output/*_output.rb', __FILE__)].each do |path|
24
+ eval( File.read(path), nil, path )
25
+ end
26
+
27
+ # default output
28
+ extend BetterOutput
29
+
30
+ @backtrace_size = nil
31
+
32
+ def self.backtrace_size=(n)
33
+ @backtrace_size = n
34
+ end
35
+
36
+ def self.backtrace_size
37
+ @backtrace_size
38
+ end
39
+
40
+ def self.run_file(path)
41
+ # run test
42
+ load(path)
43
+ # handle_summary
44
+ Counter
45
+ end
46
+
47
+ def self.summary_on_exit
48
+ return if Counter[:installed_summary] > 0
49
+ @timer = Time.now
50
+ at_exit {
51
+ handle_summary
52
+ if $!
53
+ raise $!
54
+ elsif Counter[:errors] + Counter[:failed] > 0
55
+ exit 1
56
+ end
57
+ }
58
+ Counter[:installed_summary] += 1
59
+ end
60
+ class <<self; alias summary_at_exit summary_on_exit; end
61
+
62
+ class Error < RuntimeError
63
+ attr_accessor :count_as
64
+
65
+ def initialize(count_as, message)
66
+ @count_as = count_as
67
+ super message
68
+ end
69
+ end
70
+
71
+ class Context
72
+ attr_reader :name, :block
73
+
74
+ def initialize(name, &block)
75
+ @name = name
76
+ @before, @after = [], []
77
+ @block = block
78
+ end
79
+
80
+ def run
81
+ return unless name =~ RestrictContext
82
+ Counter[:context_depth] += 1
83
+ Bacon.handle_specification(name) { instance_eval(&block) }
84
+ Counter[:context_depth] -= 1
85
+ self
86
+ end
87
+
88
+ def before(&block); @before << block; end
89
+ def after(&block); @after << block; end
90
+
91
+ def behaves_like(*names)
92
+ names.each { |name| instance_eval(&Shared[name]) }
93
+ end
94
+
95
+ def it(description, &block)
96
+ return unless description =~ RestrictName
97
+ block ||= lambda { should.flunk "not implemented" }
98
+ Counter[:specifications] += 1
99
+ run_requirement description, block
100
+ end
101
+
102
+ def should(*args, &block)
103
+ if Counter[:depth]==0
104
+ it('should '+args.first,&block)
105
+ else
106
+ super(*args,&block)
107
+ end
108
+ end
109
+
110
+ def run_requirement(description, spec)
111
+ Bacon.handle_requirement description do
112
+ begin
113
+ Counter[:depth] += 1
114
+ rescued = false
115
+ begin
116
+ @before.each { |block| instance_eval(&block) }
117
+ prev_req = Counter[:requirements]
118
+ instance_eval(&spec)
119
+ rescue Object => e
120
+ rescued = true
121
+ raise e
122
+ ensure
123
+ if Counter[:requirements] == prev_req and not rescued
124
+ raise Error.new(:missing,
125
+ "empty specification: #{@name} #{description}")
126
+ end
127
+ begin
128
+ @after.each { |block| instance_eval(&block) }
129
+ rescue Object => e
130
+ raise e unless rescued
131
+ end
132
+ end
133
+ rescue Object => e
134
+ ErrorLog << "#{e.class}: #{e.message}\n"
135
+
136
+ backtrace = e.backtrace.find_all { |line| line !~ /bin\/bacon|\/bacon\.rb:\d+/ && line !~ /guard|fsevent|thor/ }
137
+ backtrace = backtrace[0, Bacon.backtrace_size] if Bacon.backtrace_size
138
+
139
+ backtrace.each_with_index do |line, i|
140
+ ErrorLog << " #{line}#{i==0 ? ": #@name - #{description}" : ""}\n"
141
+ end
142
+
143
+ ErrorLog << "\n"
144
+
145
+ if e.kind_of? Error
146
+ Counter[e.count_as] += 1
147
+ e.count_as.to_s.upcase
148
+ [:failed]
149
+ else
150
+ Counter[:errors] += 1
151
+ [:error, e]
152
+ end
153
+ else
154
+ ""
155
+ ensure
156
+ Counter[:depth] -= 1
157
+ end
158
+ end
159
+ end
160
+
161
+ def describe(*args, &block)
162
+ context = Bacon::Context.new(args.join(' '), &block)
163
+ (parent_context = self).methods(false).each {|e|
164
+ class<<context; self end.send(:define_method, e) {|*args| parent_context.send(e, *args)}
165
+ }
166
+ @before.each { |b| context.before(&b) }
167
+ @after.each { |b| context.after(&b) }
168
+ context.run
169
+ end
170
+
171
+ def raise?(*args, &block); block.raise?(*args); end
172
+ def throw?(*args, &block); block.throw?(*args); end
173
+ def change?(*args, &block); block.change?(*args); end
174
+ end
175
+ end
176
+
177
+
178
+ class Object
179
+ def true?; false; end
180
+ def false?; false; end
181
+ end
182
+
183
+ class TrueClass
184
+ def true?; true; end
185
+ end
186
+
187
+ class FalseClass
188
+ def false?; true; end
189
+ end
190
+
191
+ class Proc
192
+ def raise?(*exceptions)
193
+ call
194
+ rescue *(exceptions.empty? ? RuntimeError : exceptions) => e
195
+ e
196
+ else
197
+ false
198
+ end
199
+
200
+ def throw?(sym)
201
+ catch(sym) {
202
+ call
203
+ return false
204
+ }
205
+ return true
206
+ end
207
+
208
+ def change?
209
+ pre_result = yield
210
+ called = call
211
+ post_result = yield
212
+ pre_result != post_result
213
+ end
214
+ end
215
+
216
+ class Numeric
217
+ def close?(to, delta)
218
+ (to.to_f - self).abs <= delta.to_f rescue false
219
+ end
220
+ end
221
+
222
+
223
+ class Object
224
+ def should(*args, &block) Should.new(self).be(*args, &block) end
225
+ end
226
+
227
+ module Kernel
228
+ private
229
+ def describe(*args, &block) Bacon::Context.new(args.join(' '), &block).run end
230
+ def shared(name, &block) Bacon::Shared[name] = block end
231
+ end
232
+
233
+ class Should
234
+ # Kills ==, ===, =~, eql?, equal?, frozen?, instance_of?, is_a?,
235
+ # kind_of?, nil?, respond_to?, tainted?
236
+ instance_methods.each { |name| undef_method name if name =~ /\?|^\W+$/ }
237
+
238
+ def initialize(object)
239
+ @object = object
240
+ @negated = false
241
+ end
242
+
243
+ def not(*args, &block)
244
+ @negated = !@negated
245
+
246
+ if args.empty?
247
+ self
248
+ else
249
+ be(*args, &block)
250
+ end
251
+ end
252
+
253
+ def be(*args, &block)
254
+ if args.empty?
255
+ self
256
+ else
257
+ block = args.shift unless block_given?
258
+ satisfy(*args, &block)
259
+ end
260
+ end
261
+
262
+ alias a be
263
+ alias an be
264
+
265
+ def satisfy(*args, &block)
266
+ if args.size == 1 && String === args.first
267
+ description = args.shift
268
+ else
269
+ description = ""
270
+ end
271
+
272
+ r = yield(@object, *args)
273
+ if Bacon::Counter[:depth] > 0
274
+ Bacon::Counter[:requirements] += 1
275
+ raise Bacon::Error.new(:failed, description) unless @negated ^ r
276
+ r
277
+ else
278
+ @negated ? !r : !!r
279
+ end
280
+ end
281
+
282
+ def method_missing(name, *args, &block)
283
+ name = "#{name}?" if name.to_s =~ /\w[^?]\z/
284
+
285
+ desc = @negated ? "not " : ""
286
+ desc << @object.inspect << "." << name.to_s
287
+ desc << "(" << args.map{|x|x.inspect}.join(", ") << ") failed"
288
+
289
+ satisfy(desc) { |x| x.__send__(name, *args, &block) }
290
+ end
291
+
292
+ def equal(value) self == value end
293
+ def match(value) self =~ value end
294
+ def identical_to(value) self.equal? value end
295
+ alias same_as identical_to
296
+
297
+ def flunk(reason="Flunked")
298
+ raise Bacon::Error.new(:failed, reason)
299
+ end
300
+ end