qed 1.2 → 1.3

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/qed/config.rb ADDED
@@ -0,0 +1,25 @@
1
+ module QED
2
+
3
+ class Config
4
+
5
+ def initialize
6
+ @local = ['qed', 'demos', 'test/demos']
7
+
8
+ if file = File.glob('{.,}config/qed.{yml,yaml}')
9
+ YAML.load(File.new(file)).each do |k,v|
10
+ __send__("#{k}=", v)
11
+ end
12
+ end
13
+ end
14
+
15
+ attr_accessor :local
16
+
17
+ # How ot identify a header?
18
+ #attr_accessor :header
19
+
20
+ # How ot identify a footer?
21
+ #attr_accessor :footer
22
+
23
+ end
24
+
25
+ end
data/lib/qed/document.rb CHANGED
@@ -36,7 +36,7 @@ module QED
36
36
  @paths ||= []
37
37
 
38
38
  if @paths.empty?
39
- dir = Dir['{test/demos,demo,demos}'].first || DEFAULT_PATH
39
+ dir = Dir['{test/demos,demos,demo}'].first || DEFAULT_PATH
40
40
  @paths = File.join(dir, '**', '*')
41
41
  end
42
42
  end
@@ -19,7 +19,7 @@
19
19
  h1 { border-bottom: 2px solid silver; }
20
20
  h2 { border-bottom: 2px solid silver; padding-top: 0.5em; }
21
21
 
22
- hr { border: 1px solid silver; }
22
+ hr { color: #ccc; margin-top: 1.6em; }
23
23
 
24
24
  p { color: #222; text-align: justify; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.4em; }
25
25
 
@@ -0,0 +1,72 @@
1
+ module QED
2
+ module Reporter #:nodoc:
3
+
4
+ require 'qed/reporter/base'
5
+
6
+ # = DotProgress Reporter
7
+ #
8
+ class Ditto < BaseClass
9
+
10
+ #
11
+ def report_intro
12
+ #@start_time = Time.now
13
+ #io.puts "Started"
14
+ end
15
+
16
+ #
17
+ def report_step(step)
18
+ super
19
+ #if step.code
20
+ io.print "."
21
+ #str = "(%s) %s" % [count.join('.'), str.tab(6).strip]
22
+ #puts "* #{step.text.tab(2).strip}"
23
+ #puts "\n#{step.code}\n" if $VERBOSE
24
+ #else
25
+ #puts "\n#{step.text}"
26
+ #end
27
+ end
28
+
29
+ #def report(str)
30
+ # count[-1] += 1 unless count.empty?
31
+ # str = str.chomp('.') + '.'
32
+ # str = count.join('.') + ' ' + str
33
+ # puts str.strip
34
+ #end
35
+
36
+ def report_summary
37
+ io.puts "\nFinished in #{Time.now - @start_time} seconds.\n\n"
38
+
39
+ @error.each do |step, exception|
40
+ backtrace = clean_backtrace(exception.backtrace[0])
41
+ io.puts ANSICode.red("***** ERROR *****")
42
+ io.puts "#{exception}"
43
+ io.puts ":#{backtrace}:"
44
+ #io.puts ":#{exception.backtrace[1]}:"
45
+ #io.puts exception.backtrace[1..-1] if $VERBOSE
46
+ io.puts
47
+ end
48
+
49
+ @fail.each do |step, assertion|
50
+ backtrace = clean_backtrace(assertion.backtrace[0])
51
+ io.puts ANSICode.red("***** FAIL *****")
52
+ io.puts ANSICode.bold("#{assertion}")
53
+ io.puts ":#{backtrace}:"
54
+ #io.puts assertion if $VERBOSE
55
+ io.puts
56
+ end
57
+
58
+ io.puts "%s demos, %s steps, %s failures, %s errors" % [@demos, @steps, @fail.size, @error.size] #, @pass.size ]
59
+ end
60
+
61
+ private
62
+
63
+ #
64
+ def clean_backtrace(btrace)
65
+ btrace.chomp(":in `_binding'")
66
+ end
67
+
68
+ end#class DotProgress
69
+
70
+ end#module Reporter
71
+ end#module QED
72
+
@@ -37,18 +37,20 @@ module Reporter #:nodoc:
37
37
  io.puts "\nFinished in #{Time.now - @start_time} seconds.\n\n"
38
38
 
39
39
  @error.each do |step, exception|
40
+ backtrace = clean_backtrace(exception.backtrace[0])
40
41
  io.puts ANSICode.red("***** ERROR *****")
41
42
  io.puts "#{exception}"
42
- io.puts ":#{exception.backtrace[0]}:"
43
+ io.puts ":#{backtrace}:"
43
44
  #io.puts ":#{exception.backtrace[1]}:"
44
45
  #io.puts exception.backtrace[1..-1] if $VERBOSE
45
46
  io.puts
46
47
  end
47
48
 
48
49
  @fail.each do |step, assertion|
50
+ backtrace = clean_backtrace(assertion.backtrace[0])
49
51
  io.puts ANSICode.red("***** FAIL *****")
50
52
  io.puts ANSICode.bold("#{assertion}")
51
- io.puts ":#{assertion.backtrace[2]}:"
53
+ io.puts ":#{backtrace}:"
52
54
  #io.puts assertion if $VERBOSE
53
55
  io.puts
54
56
  end
@@ -56,6 +58,13 @@ module Reporter #:nodoc:
56
58
  io.puts "%s demos, %s steps, %s failures, %s errors" % [@demos, @steps, @fail.size, @error.size] #, @pass.size ]
57
59
  end
58
60
 
61
+ private
62
+
63
+ #
64
+ def clean_backtrace(btrace)
65
+ btrace.chomp(":in `_binding'")
66
+ end
67
+
59
68
  end#class DotProgress
60
69
 
61
70
  end#module Reporter
data/lib/qed/runner.rb CHANGED
@@ -1,6 +1,3 @@
1
- #require 'quarry/behave'
2
- #require 'quarry/runner/context'
3
-
4
1
  module QED
5
2
 
6
3
  require 'qed/script'
@@ -16,7 +13,7 @@ module QED
16
13
  #
17
14
  class Runner
18
15
 
19
- # QED::Spec::Runner.configure do
16
+ # QED::Runner.configure do
20
17
  # def setup(spec)
21
18
  # ...
22
19
  # end
@@ -35,8 +32,26 @@ module QED
35
32
  # end
36
33
  #end
37
34
 
35
+ def self.configure(&block)
36
+ class_eval(&block)
37
+ end
38
+
39
+ def self.start(&block)
40
+ define_method(:start, &block)
41
+ end
42
+
43
+ def self.finish(&block)
44
+ define_method(:finish, &block)
45
+ end
46
+
47
+ #
38
48
  attr :specs
39
- attr :output
49
+
50
+ #
51
+ attr_accessor :format
52
+
53
+ #
54
+ attr_accessor :trace
40
55
 
41
56
  #attr :context
42
57
  #attr :count
@@ -45,30 +60,59 @@ module QED
45
60
  #attr_accessor :after
46
61
 
47
62
  # New Specification
48
- def initialize(specs, output=nil)
49
- @specs = [specs].flatten
50
- @output = output || Reporter::DotProgress.new #(self)
63
+ def initialize(specs, options={})
64
+ @specs = [specs].flatten
65
+
66
+ @format = :dotprogress
67
+ @trace = false
68
+
69
+ options.each do |k,v|
70
+ __send__("#{k}=", v) if v
71
+ end
72
+ end
73
+
74
+ # Instance of selected Reporter subclass.
75
+ def reporter
76
+ case format
77
+ when :dotprogress
78
+ Reporter::DotProgress.new(reporter_options)
79
+ when :verbatim
80
+ Reporter::Verbatim.new(reporter_options)
81
+ when :summary
82
+ Reporter::Summary.new(reporter_options)
83
+ when :script #ditto ?
84
+ # TODO
85
+ else
86
+ Reporter::DotProgress.new(reporter_options)
87
+ end
88
+ end
89
+
90
+ # Report options.
91
+ #--
92
+ # TODO: rename :verbose to :trace
93
+ #++
94
+ def reporter_options
95
+ { :verbose => @trace }
96
+ end
97
+
98
+ #
99
+ def output
100
+ @output ||= reporter
51
101
  end
52
102
 
53
103
  #
54
104
  def check
105
+ start
55
106
  output.report_intro
56
- # loop through each specification and run it
57
- specs.each do |spec|
58
- # create a run context for the spec
59
- #@context = Context.new(spec)
60
- # run the specification
61
- run_spec(spec)
107
+ specs.each do |spec| # loop through each specification and run it
108
+ run_spec(spec) # run the specification
62
109
  end
63
110
  output.report_summary
111
+ finish
64
112
  end
65
113
 
66
114
  # Run a specification.
67
- #
68
115
  def run_spec(spec)
69
- #report(spec.description)
70
-
71
- #script = Script.load(spec, output)
72
116
  script = Script.new(spec, output)
73
117
 
74
118
  # pretty sure this is the thing to do
@@ -142,7 +186,13 @@ module QED
142
186
  end
143
187
  =end
144
188
 
189
+ def start
190
+ end
191
+
192
+ def finish
193
+ end
194
+
145
195
  end#class Runner
146
196
 
147
- end#module Quarry
197
+ end#module QED
148
198
 
data/lib/qed/script.rb CHANGED
@@ -11,6 +11,18 @@ module QED
11
11
  #Assertion = AE::Assertion
12
12
  Expectation = Assertor
13
13
 
14
+ # Global Before
15
+ def self.Before(&procedure)
16
+ @_before = procedure if procedure
17
+ @_before
18
+ end
19
+
20
+ # Global After
21
+ def self.After(&procedure)
22
+ @_after = procedure if procedure
23
+ @_after
24
+ end
25
+
14
26
  # New Specification
15
27
  #def initialize(specs, output=nil)
16
28
  # @specs = [specs].flatten
@@ -24,19 +36,20 @@ module QED
24
36
  # new(File.read(file), output)
25
37
  #end
26
38
 
39
+ # Path of demonstration script.
27
40
  attr :file
41
+
42
+ # Reporter object to issue output calls.
28
43
  attr :output
29
44
 
45
+ # List of helper scripts to require.
46
+ attr :helpers
47
+
30
48
  # New Script
31
49
  def initialize(file, output=nil)
32
- @file = file
33
- @output = output || Reporter::Verbatim.new #(self)
34
-
35
- source = File.read(file)
36
- index = source.rindex('---') || source.size
37
-
38
- @source = source[0...index]
39
- @helper = source[index+3...-1].to_s.strip
50
+ @file = file
51
+ @output = output || Reporter::Verbatim.new #(self)
52
+ parse_document(file)
40
53
  end
41
54
 
42
55
  # File basename less extension.
@@ -44,14 +57,23 @@ module QED
44
57
  @name ||= File.basename(file).chomp(File.extname(file))
45
58
  end
46
59
 
60
+ #
61
+ def directory
62
+ @directory ||= Dir.pwd #File.dirname(File.expand_path(file))
63
+ end
64
+
47
65
  #def convert
48
66
  # @source.gsub(/^\w/, '# \1')
49
67
  #end
50
68
 
51
69
  # Run the script.
52
70
  def run
53
- #steps = @source.split(/\n\s*$/)
54
- eval(@helper, context._binding, @file) if @helper
71
+ @lineno = 0
72
+
73
+ $LOAD_PATH.unshift(directory)
74
+
75
+ import_helpers
76
+
55
77
  steps.each do |step|
56
78
  output.report_step(step)
57
79
  case step
@@ -71,17 +93,31 @@ module QED
71
93
  run_step(step)
72
94
  #end
73
95
  end
96
+ @lineno += step.count("\n")
74
97
  end
98
+
99
+ $LOAD_PATH.index(directory){ |i| $LOAD_PATH.delete_at(i) }
75
100
  end
76
101
 
77
- #
102
+ #--
103
+ # NOTE: The Around code is in place should we decide
104
+ # to use it. I'm not sure yet if it's really neccessary,
105
+ # since we have Before and After.
106
+ #++
78
107
  def run_step(step=nil, &blk)
108
+ QED.Before.call if QED.Before
79
109
  context.Before.call if context.Before
80
110
  begin
81
- if blk
111
+ if blk # TODO: Is this still used?
82
112
  blk.call #eval(step, context._binding)
83
113
  else
84
- eval(step, context._binding, @file) # TODO: would be nice to know file and lineno here
114
+ #if context.Around
115
+ # context.Around.call do
116
+ # eval(step, context._binding, @file, @lineno+1)
117
+ # end
118
+ #else
119
+ eval(step, context._binding, @file, @lineno+1)
120
+ #end
85
121
  end
86
122
  output.report_pass(step) if step
87
123
  rescue Assertion => error
@@ -90,6 +126,7 @@ module QED
90
126
  output.report_error(step, error)
91
127
  ensure
92
128
  context.After.call if context.After
129
+ QED.After.call if QED.After
93
130
  end
94
131
  end
95
132
 
@@ -182,6 +219,88 @@ module QED
182
219
  @context ||= Context.new(self)
183
220
  end
184
221
 
222
+ #
223
+ def import(helper)
224
+ code = File.read(helper)
225
+ eval(code, context._binding)
226
+ end
227
+
228
+ private
229
+
230
+ # Splits the document into main source and footer
231
+ # and extract the helper document references from
232
+ # the footer.
233
+ #
234
+ def parse_document(file)
235
+ text = File.read(file)
236
+ index = text.rindex('---') || text.size
237
+ source = text[0...index]
238
+ footer = text[index+3..-1].to_s.strip
239
+ helpers = parse_helpers(footer)
240
+ @source = source
241
+ @helpers = helpers
242
+ end
243
+
244
+ #
245
+ def parse_helpers(footer)
246
+ helpers = []
247
+ footer.split("\n").each do |line|
248
+ next if line.strip == ''
249
+ case line
250
+ when /\[(.*?)\]\((.*?)\)/
251
+ helpers << $2
252
+ when /(.*?)\[(.*?)\]/
253
+ helpers << $2
254
+ end
255
+ end
256
+ helpers
257
+ end
258
+
259
+ =begin
260
+ # Looks for a master +helper.rb+ file and a special
261
+ # helpers/<name>.rb file. Both of these, when found, will
262
+ # be imported when this script is run.
263
+
264
+ def collect_helpers
265
+ dir = File.dirname(file)
266
+ list = []
267
+ list << "helper.rb" if File.exist?(File.join(dir, "helper.rb"))
268
+ list << "helpers/#{name}.rb" if File.exist?(File.join(dir, "helpers/#{name}.rb"))
269
+ list
270
+ end
271
+ =end
272
+
273
+ # TODO: How to determine where to find the env.rb file?
274
+ #def require_environment
275
+ # dir = File.dirname(file)
276
+ # dir = File.expand_path(dir)
277
+ # env = loop do
278
+ # file = File.join(dir, 'env.rb')
279
+ # break file if File.exist?(file)
280
+ # break nil if ['demo', 'demos', 'doc', 'docs', 'test', 'tests'].include? File.basename(dir)
281
+ # break nil if dir == Dir.pwd
282
+ # dir = File.dirname(dir)
283
+ # end
284
+ # require(env) if env
285
+ #end
286
+
287
+ # FIXME: where to stop looking for helpers.
288
+ def import_helpers
289
+ hlp = []
290
+ dir = Dir.pwd #File.expand_path(dir)
291
+ env = loop do
292
+ helpers.each do |helper|
293
+ file = File.join(dir, 'helpers', helper)
294
+ if File.exist?(file)
295
+ hlp << file
296
+ end
297
+ end
298
+ break if ['qed', 'demo', 'demos', 'doc', 'docs', 'test', 'tests'].include? File.basename(dir)
299
+ dir = File.dirname(dir)
300
+ end
301
+ hlp.each{ |helper| import(helper) }
302
+ end
303
+
185
304
  end
186
305
 
187
306
  #
@@ -211,6 +330,27 @@ module QED
211
330
  @_after
212
331
  end
213
332
 
333
+ # Run code around each step.
334
+ #
335
+ # Around procedures must take a block, in which the step is run.
336
+ #
337
+ # Around do |&step|
338
+ # ... do something here ...
339
+ # step.call
340
+ # ... do stiff stuff ...
341
+ # end
342
+ #
343
+ #def Around(&procedure)
344
+ # @_around = procedure if procedure
345
+ # @_around
346
+ #end
347
+
348
+ # Comment match procedure.
349
+ #
350
+ # This is useful for creating unobtrusive setup and (albeit more
351
+ # limited) teardown code. A pattern is matched against each comment
352
+ # as it is processed. If there is match, the code procedure is
353
+ # triggered, passing in any mathcing expression arguments.
214
354
  #
215
355
  def When(pattern=nil, &procedure)
216
356
  return @_when unless procedure
@@ -221,6 +361,24 @@ module QED
221
361
  @_when << [pattern, procedure]
222
362
  end
223
363
 
364
+ # Code match-and-transform procedure.
365
+ #
366
+ # This is useful to transform human readable code examples
367
+ # into proper exectuable code. For example, say you want to
368
+ # run shell code, but want to make if look like typical
369
+ # shelle examples:
370
+ #
371
+ # $ cp fixture/a.rb fixture/b.rb
372
+ #
373
+ # You can use a transform to convert lines starting with '$'
374
+ # into executable Ruby using #system.
375
+ #
376
+ # system('cp fixture/a.rb fixture/b.rb')
377
+ #
378
+ #def Transform(pattern=nil, &procedure)
379
+ #
380
+ #end
381
+
224
382
  # Table-based steps.
225
383
  def Table(file=nil, &blk)
226
384
  file = file || @_tables.last