pork 0.9.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/pork.rb CHANGED
@@ -1,247 +1,30 @@
1
1
 
2
- require 'thread'
3
-
4
- module Kernel
5
- def should message=nil, message_lazy=nil, &checker
6
- Pork::Should.new(self, message, message_lazy, &checker)
7
- end
8
- end
2
+ require 'pork/executor'
9
3
 
10
4
  module Pork
11
- Error = Class.new(StandardError)
12
- Failure = Class.new(Error)
13
- Skip = Class.new(Error)
14
-
15
- def self.stats ; @stats ||= Stats.new; end
16
- def self.reset ; @stats = nil ; end
17
- def self.report; stats.report; reset ; end
18
- def self.report_at_exit
19
- Pork.stats.start
20
- @report_at_exit ||= at_exit do
21
- stats.report
22
- exit stats.failures.size + stats.errors.size + ($! && 1).to_i
23
- end
24
- end
25
- # default to :auto while eliminating warnings for uninitialized ivar
26
- def self.inspect_failure_mode mode=nil; @mode = mode || @mode ||= :auto; end
27
- def self.inspect_failure *args
28
- lambda{ public_send("inspect_failure_#{inspect_failure_mode}", *args) }
29
- end
30
-
31
- def self.inspect_failure_auto object, msg, args, negate
32
- if args.size > 1
33
- inspect_failure_inline(object, msg, args, negate)
34
- elsif object.kind_of?(Hash) && args.first.kind_of?(Hash)
35
- inspect_failure_inline(Hash[object.sort], msg,
36
- [Hash[args.first.sort]], negate)
37
- elsif object.kind_of?(String) && object.size > 400 &&
38
- object.count("\n") > 4 && !`which diff`.empty?
39
- inspect_failure_diff(object, msg, args, negate)
40
- else
41
- ins = object.inspect
42
- if ins.size > 78
43
- inspect_failure_newline(object, msg, args, negate)
44
- else
45
- inspect_failure_inline( object, msg, args, negate)
46
- end
47
- end
48
- end
49
-
50
- def self.inspect_failure_inline object, msg, args, negate
51
- a = args.map(&:inspect).join(', ')
52
- "#{object.inspect}.#{msg}(#{a}) to return #{!negate}"
53
- end
54
-
55
- def self.inspect_failure_newline object, msg, args, negate
56
- a = args.map(&:inspect).join(",\n")
57
- "\n#{object.inspect}.#{msg}(\n#{a}) to return #{!negate}"
58
- end
59
-
60
- def self.inspect_failure_diff object, msg, args, negate
61
- require 'tempfile'
62
- Tempfile.open('pork-expect') do |expect|
63
- Tempfile.open('pork-was') do |was|
64
- expect.puts(object.to_s)
65
- expect.close
66
- was.puts(args.map(&:to_s).join(",\n"))
67
- was.close
68
- name = "#{object.class}##{msg}(\n"
69
- "#{name}#{`diff #{expect.path} #{was.path}`}) to return #{!negate}"
70
- end
71
- end
72
- end
73
-
74
5
  module API
75
6
  module_function
76
7
  def before █ Executor.before(&block); end
77
8
  def after █ Executor.after( &block); end
78
- def describe desc=:default, &suite; Executor.describe(desc, &suite); end
79
- def copy desc=:default, &suite; Executor.copy( desc, &suite); end
9
+ def copy desc=:default, █ Executor.copy( desc, &block); end
80
10
  def paste desc=:default, *args ; Executor.paste( desc, *args ); end
11
+ def describe desc=:default, &suite; Executor.describe(desc, &suite); end
81
12
  def would desc=:default, &test ; Executor.would( desc, &test ); end
82
13
  end
83
14
 
84
- module Imp
85
- attr_reader :stash, :desc
86
- def before &block
87
- if block_given? then @before << block else @before end
88
- end
89
- def after &block
90
- if block_given? then @after << block else @after end
91
- end
92
- def describe desc=:default, &suite
93
- Class.new(self){ init("#{desc}: ") }.module_eval(&suite)
94
- end
95
- def copy desc=:default, &suite; stash[desc] = suite; end
96
- def paste desc=:default, *args
97
- module_exec(*args, &search_stash(desc))
98
- end
99
- def would desc=:default, &test
100
- assertions = Pork.stats.assertions
101
- context = new(desc)
102
- run_before(context)
103
- context.instance_eval(&test)
104
- if assertions == Pork.stats.assertions
105
- raise Error.new('Missing assertions')
106
- end
107
- rescue Error, StandardError => e
108
- case e
109
- when Skip
110
- Pork.stats.incr_skips
111
- when Failure
112
- Pork.stats.add_failure(e, description_for("would #{desc}"))
113
- when Error, StandardError
114
- Pork.stats.add_error( e, description_for("would #{desc}"))
115
- end
116
- else
117
- print '.'
118
- ensure
119
- Pork.stats.incr_tests
120
- run_after(context)
121
- end
122
-
123
- protected
124
- def init desc=''; @desc, @before, @after, @stash = desc, [], [], {}; end
125
- def super_executor
126
- @super_executor ||= ancestors[1..-1].find{ |a| a <= Executor }
127
- end
128
- def search_stash desc
129
- stash[desc] or super_executor && super_executor.search_stash(desc)
130
- end
131
- def description_for name=''
132
- "#{desc}#{super_executor && super_executor.description_for}#{name}"
133
- end
134
- def run_before context
135
- super_executor && super_executor.run_before(context)
136
- before.each{ |b| context.instance_eval(&b) }
137
- end
138
- def run_after context
139
- super_executor && super_executor.run_after(context)
140
- after.each{ |b| context.instance_eval(&b) }
141
- end
142
- end
143
-
144
- class Executor < Struct.new(:desc)
145
- extend Pork::Imp, Pork::API
146
- init
147
- def skip ; raise Skip.new("Skipping #{desc}"); end
148
- def flunk reason='Flunked'; raise Error.new(reason) ; end
149
- def ok ; Pork.stats.incr_assertions ; end
15
+ # default to :execute while eliminating warnings for uninitialized ivar
16
+ def self.execute_mode execute=nil
17
+ @execute = execute || @execute ||= :execute
150
18
  end
151
19
 
152
- class Should < BasicObject
153
- instance_methods.each{ |m| undef_method(m) unless m =~ /^__|^object_id$/ }
154
- def initialize object, message=nil, message_lazy=nil, &checker
155
- @object, @negate = object, false
156
- @message, @message_lazy = message, message_lazy
157
- satisfy(&checker) if checker
158
- end
159
-
160
- def method_missing msg, *args, &block
161
- satisfy(nil, ::Pork.inspect_failure(@object, msg, args, @negate)) do
162
- @object.public_send(msg, *args, &block)
163
- end
164
- end
165
-
166
- def satisfy desc=@object, desc_lazy=nil
167
- result = yield(@object)
168
- if !!result == @negate
169
- d = desc_lazy && desc_lazy.call || desc
170
- m = @message_lazy && @message_lazy.call || @message
171
- ::Kernel.raise Failure.new("Expect #{d}\n#{m}".chomp)
172
- else
173
- ::Pork.stats.incr_assertions
174
- end
175
- result
176
- end
177
-
178
- def not &checker
179
- @negate = !@negate
180
- satisfy(&checker) if checker
181
- self
182
- end
183
-
184
- def eq rhs; self == rhs; end
185
- def lt rhs; self < rhs; end
186
- def gt rhs; self > rhs; end
187
- def lte rhs; self <= rhs; end
188
- def gte rhs; self >= rhs; end
189
-
190
- def raise exception=::RuntimeError
191
- satisfy("#{__not__}raising #{exception}") do
192
- begin
193
- if ::Kernel.block_given? then yield else @object.call end
194
- rescue exception => e
195
- e
196
- else
197
- false
198
- end
199
- end
200
- end
201
-
202
- def throw msg
203
- satisfy("#{__not__}throwing #{msg}") do
204
- flag = true
205
- data = ::Kernel.catch(msg) do
206
- if ::Kernel.block_given? then yield else @object.call end
207
- flag = false
208
- end
209
- flag && [msg, data]
210
- end
211
- end
212
-
213
- private
214
- def __not__; if @negate == true then 'not ' else '' end; end
215
- end
216
-
217
- class Stats < Struct.new(:tests, :assertions, :skips, :failures, :errors)
218
- def initialize
219
- @mutex = Mutex.new
220
- super(0, 0, 0, [], [])
221
- end
222
- def incr_assertions; @mutex.synchronize{ self.assertions += 1 }; end
223
- def incr_tests ; @mutex.synchronize{ self.tests += 1 }; end
224
- def incr_skips ; @mutex.synchronize{ self.skips += 1; print('s')}; end
225
- def add_failure *e ; @mutex.synchronize{ failures << e; print('F')}; end
226
- def add_error *e ; @mutex.synchronize{ errors << e; print('E')}; end
227
- def numbers; [tests, assertions, failures.size, errors.size, skips]; end
228
- def start ; @start ||= Time.now ; end
229
- def report
230
- puts
231
- puts (failures + errors).map{ |(e, m)|
232
- "\n#{m}\n#{e.class}: #{e.message}\n #{backtrace(e)}"
233
- }
234
- printf("\nFinished in %f seconds.\n", Time.now - @start)
235
- printf("%d tests, %d assertions, %d failures, %d errors, %d skips\n",
236
- *numbers)
237
- end
238
- private
239
- def backtrace e
240
- if $VERBOSE
241
- e.backtrace
242
- else
243
- e.backtrace.reject{ |line| line =~ %r{/pork\.rb:\d+} }
244
- end.join("\n ")
20
+ def self.autorun auto=true
21
+ @auto = auto
22
+ @autorun ||= at_exit do
23
+ next unless @auto
24
+ require "pork/mode/#{execute_mode}" unless execute_mode == :execute
25
+ stat = Executor.public_send(execute_mode)
26
+ stat.report
27
+ exit stat.failures.size + stat.errors.size + ($! && 1).to_i
245
28
  end
246
29
  end
247
30
  end
data/lib/pork/auto.rb CHANGED
@@ -1,4 +1,5 @@
1
1
 
2
2
  require 'pork'
3
+ require 'pork/should'
3
4
  extend Pork::API
4
- Pork.report_at_exit
5
+ Pork.autorun
@@ -0,0 +1,24 @@
1
+
2
+ require 'pork/expect'
3
+ require 'pork/error'
4
+
5
+ module Pork
6
+ module Context
7
+ private
8
+ def expect *args, &block
9
+ Expect.new(pork_stat, *args, &block)
10
+ end
11
+
12
+ def skip
13
+ raise Skip.new
14
+ end
15
+
16
+ def flunk reason='Flunked'
17
+ raise Error.new(reason)
18
+ end
19
+
20
+ def ok
21
+ pork_stat.incr_assertions
22
+ end
23
+ end
24
+ end
data/lib/pork/env.rb ADDED
@@ -0,0 +1,18 @@
1
+
2
+ module Pork
3
+ class Env < Struct.new(:super_env, :before, :after)
4
+ def initialize se=nil
5
+ super(se, [], [])
6
+ end
7
+
8
+ def run_before context
9
+ super_env && super_env.run_before(context)
10
+ before.each{ |b| context.instance_eval(&b) }
11
+ end
12
+
13
+ def run_after context
14
+ super_env && super_env.run_after(context)
15
+ after.each{ |b| context.instance_eval(&b) }
16
+ end
17
+ end
18
+ end
data/lib/pork/error.rb ADDED
@@ -0,0 +1,6 @@
1
+
2
+ module Pork
3
+ Error = Class.new(StandardError)
4
+ Failure = Class.new(Error)
5
+ Skip = Class.new(Error)
6
+ end
@@ -0,0 +1,11 @@
1
+
2
+ require 'pork/imp'
3
+ require 'pork/context'
4
+
5
+ module Pork
6
+ class Executor < Struct.new(:pork_stat)
7
+ extend Imp
8
+ include Context
9
+ init
10
+ end
11
+ end
@@ -0,0 +1,69 @@
1
+
2
+ require 'pork/inspect'
3
+
4
+ module Pork
5
+ class Expect < BasicObject
6
+ instance_methods.each{ |m| undef_method(m) unless m =~ /^__|^object_id$/ }
7
+ def initialize stat, object=nil, message=nil, message_lazy=nil, &checker
8
+ @stat, @object, @negate = stat, object, false
9
+ @message, @message_lazy = message, message_lazy
10
+ satisfy(&checker) if checker
11
+ end
12
+
13
+ def method_missing msg, *args, &block
14
+ satisfy(nil, Inspect.with(@object, msg, args, @negate)) do
15
+ @object.public_send(msg, *args, &block)
16
+ end
17
+ end
18
+
19
+ def satisfy desc=@object, desc_lazy=nil
20
+ result = yield(@object)
21
+ if !!result == @negate
22
+ d = desc_lazy && desc_lazy.call || desc
23
+ m = @message_lazy && @message_lazy.call || @message
24
+ ::Kernel.raise Failure.new("Expect #{d}\n#{m}".chomp)
25
+ else
26
+ @stat.incr_assertions
27
+ end
28
+ result
29
+ end
30
+
31
+ def not &checker
32
+ @negate = !@negate
33
+ satisfy(&checker) if checker
34
+ self
35
+ end
36
+
37
+ def eq rhs; self == rhs; end
38
+ def lt rhs; self < rhs; end
39
+ def gt rhs; self > rhs; end
40
+ def lte rhs; self <= rhs; end
41
+ def gte rhs; self >= rhs; end
42
+
43
+ def raise exception=::RuntimeError
44
+ satisfy("#{__not__}raising #{exception}") do
45
+ begin
46
+ if ::Kernel.block_given? then yield else @object.call end
47
+ rescue exception => e
48
+ e
49
+ else
50
+ false
51
+ end
52
+ end
53
+ end
54
+
55
+ def throw msg
56
+ satisfy("#{__not__}throwing #{msg}") do
57
+ flag = true
58
+ data = ::Kernel.catch(msg) do
59
+ if ::Kernel.block_given? then yield else @object.call end
60
+ flag = false
61
+ end
62
+ flag && [msg, data]
63
+ end
64
+ end
65
+
66
+ private
67
+ def __not__; if @negate == true then 'not ' else '' end; end
68
+ end
69
+ end
data/lib/pork/imp.rb ADDED
@@ -0,0 +1,103 @@
1
+
2
+ require 'pork/env'
3
+ require 'pork/stat'
4
+ require 'pork/error'
5
+ require 'pork/expect'
6
+
7
+ module Pork
8
+ module Imp
9
+ attr_reader :desc, :tests
10
+
11
+ def before &block; @tests << [:before, block]; end
12
+ def after &block; @tests << [:after , block]; end
13
+
14
+ def copy desc=:default, &suite
15
+ @stash[desc] = suite
16
+ end
17
+ def paste desc=:default, *args
18
+ module_exec(*args, &search_stash(desc))
19
+ end
20
+
21
+ def describe desc=:default, &suite
22
+ executor = Class.new(self){ init("#{desc}: ") }
23
+ executor.module_eval(&suite)
24
+ @tests << [:describe, executor]
25
+ end
26
+
27
+ def would desc=:default, &test
28
+ @tests << [:would, desc, test]
29
+ end
30
+
31
+ def execute stat=Stat.new
32
+ if block_given?
33
+ yield(stat)
34
+ else
35
+ execute_with_parent(stat)
36
+ end
37
+ stat
38
+ end
39
+
40
+ private
41
+ def init desc=''
42
+ @desc, @tests, @stash = desc, [], {}
43
+ @super_executor = ancestors[1..-1].find{ |a| a <= Executor }
44
+ end
45
+
46
+ def run desc, test, stat, env
47
+ assertions = stat.assertions
48
+ context = new(stat)
49
+ run_protected(desc, stat) do
50
+ env.run_before(context)
51
+ context.instance_eval(&test)
52
+ if assertions == stat.assertions
53
+ raise Error.new('Missing assertions')
54
+ end
55
+ stat.io.print '.'
56
+ end
57
+ ensure
58
+ stat.incr_tests
59
+ run_protected(desc, stat){ env.run_after(context) }
60
+ end
61
+
62
+ def run_protected desc, stat
63
+ yield
64
+ rescue Error, StandardError => e
65
+ case e
66
+ when Skip
67
+ stat.incr_skips
68
+ stat.io.print 's'
69
+ when Failure
70
+ stat.add_failure(e, description_for("would #{desc}"))
71
+ stat.io.print 'F'
72
+ when Error, StandardError
73
+ stat.add_error( e, description_for("would #{desc}"))
74
+ stat.io.print 'E'
75
+ end
76
+ end
77
+
78
+ protected
79
+ def execute_with_parent stat, super_env=nil
80
+ env = Env.new(super_env)
81
+ @tests.each do |(type, arg, test)|
82
+ case type
83
+ when :before
84
+ env.before << arg
85
+ when :after
86
+ env.after << arg
87
+ when :describe
88
+ arg.execute_with_parent(stat, env)
89
+ when :would
90
+ run(arg, test, stat, env)
91
+ end
92
+ end
93
+ end
94
+
95
+ def search_stash desc
96
+ @stash[desc] or @super_executor && @super_executor.search_stash(desc)
97
+ end
98
+
99
+ def description_for name=''
100
+ "#{@desc}#{@super_executor && @super_executor.description_for}#{name}"
101
+ end
102
+ end
103
+ end