pork 0.9.2 → 1.0.0

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/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