qed 1.3 → 2.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/CHANGELOG.txt +647 -0
- data/HISTORY +16 -0
- data/bin/qedoc +2 -51
- data/demo/error.rdoc +21 -0
- data/demo/{03_site.qed → website.rdoc} +0 -0
- data/doc/qedoc/index.html +160 -69
- data/lib/qed.rb +2 -2
- data/lib/qed/advice.rb +61 -0
- data/lib/qed/advice/events.rb +54 -0
- data/lib/qed/advice/patterns.rb +64 -0
- data/lib/qed/command.rb +76 -65
- data/lib/qed/config.rb +48 -13
- data/lib/qed/evaluator.rb +124 -0
- data/lib/qed/reporter/base.rb +93 -39
- data/lib/qed/reporter/bullet.rb +79 -0
- data/lib/qed/reporter/dotprogress.rb +9 -29
- data/lib/qed/reporter/html.rb +61 -0
- data/lib/qed/reporter/verbatim.rb +41 -47
- data/lib/qed/scope.rb +77 -0
- data/lib/qed/script.rb +66 -399
- data/lib/qed/session.rb +95 -0
- data/lib/qedoc/command.rb +76 -0
- data/lib/{qed → qedoc}/document.rb +31 -22
- data/lib/{qed → qedoc}/document/jquery.js +0 -0
- data/lib/{qed → qedoc}/document/markup.rb +0 -0
- data/lib/{qed → qedoc}/document/template.rhtml +0 -0
- data/meta/requires +2 -0
- data/meta/version +1 -1
- metadata +71 -34
- data/Syckfile +0 -70
- data/demo/01_spec.qed +0 -175
- data/demo/02_err.qed +0 -18
- data/demo/data.txt +0 -1
- data/demo/helpers/sample.rb +0 -4
- data/demo/table.yml +0 -5
- data/lib/qed/extract.rb +0 -137
- data/lib/qed/reporter/ditto.rb +0 -72
- data/lib/qed/reporter/summary.rb +0 -68
- data/lib/qed/runner.rb +0 -198
- data/lib/qed/script1.rb +0 -495
data/lib/qed/reporter/summary.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
module QED
|
2
|
-
module Reporter #:nodoc:
|
3
|
-
|
4
|
-
require 'qed/reporter/base'
|
5
|
-
|
6
|
-
# = Summary Reporter
|
7
|
-
#
|
8
|
-
# Similar to the Verbatim reporter, but does
|
9
|
-
# not display test code for passing tests.
|
10
|
-
class Summary < BaseClass
|
11
|
-
|
12
|
-
def report_header(step)
|
13
|
-
io.puts ANSICode.bold("#{step}")
|
14
|
-
end
|
15
|
-
|
16
|
-
def report_comment(step)
|
17
|
-
txt = step.to_s.strip.tabto(2)
|
18
|
-
txt[0,1] = "*"
|
19
|
-
io.puts txt
|
20
|
-
io.puts
|
21
|
-
end
|
22
|
-
|
23
|
-
def report_macro(step)
|
24
|
-
txt = step.to_s.tabto(2)
|
25
|
-
txt[0,1] = "*"
|
26
|
-
io.puts txt
|
27
|
-
#io.puts
|
28
|
-
#io.puts ANSICode.magenta("#{step}")
|
29
|
-
end
|
30
|
-
|
31
|
-
def report_pass(step)
|
32
|
-
#io.puts ANSICode.green("#{step}")
|
33
|
-
end
|
34
|
-
|
35
|
-
def report_fail(step, assertion)
|
36
|
-
msg = ''
|
37
|
-
msg << " ##### FAIL #####\n"
|
38
|
-
msg << " # " + assertion.to_s
|
39
|
-
msg = ANSICode.magenta(msg)
|
40
|
-
io.puts msg
|
41
|
-
#io.puts
|
42
|
-
io.puts ANSICode.red("#{step}")
|
43
|
-
end
|
44
|
-
|
45
|
-
def report_error(step, exception)
|
46
|
-
raise exception if $DEBUG
|
47
|
-
msg = ''
|
48
|
-
msg << " ##### ERROR #####\n"
|
49
|
-
msg << " # " + exception.to_s + "\n"
|
50
|
-
msg << " # " + exception.backtrace[0]
|
51
|
-
msg = ANSICode.magenta(msg)
|
52
|
-
io.puts msg
|
53
|
-
#io.puts
|
54
|
-
io.puts ANSICode.red("#{step}")
|
55
|
-
end
|
56
|
-
|
57
|
-
#def report(str)
|
58
|
-
# count[-1] += 1 unless count.empty?
|
59
|
-
# str = str.chomp('.') + '.'
|
60
|
-
# str = count.join('.') + ' ' + str
|
61
|
-
# io.puts str.strip
|
62
|
-
#end
|
63
|
-
|
64
|
-
end #class Summary
|
65
|
-
|
66
|
-
end#module Reporter
|
67
|
-
end#module QED
|
68
|
-
|
data/lib/qed/runner.rb
DELETED
@@ -1,198 +0,0 @@
|
|
1
|
-
module QED
|
2
|
-
|
3
|
-
require 'qed/script'
|
4
|
-
|
5
|
-
# = Specificaton Runner
|
6
|
-
#
|
7
|
-
# The Runner class loops through a set of specifications
|
8
|
-
# and executes each one in turn.
|
9
|
-
#
|
10
|
-
# The current working directory is changed to that of the
|
11
|
-
# specification script's. So any relative file references
|
12
|
-
# within a spec must take that into account.
|
13
|
-
#
|
14
|
-
class Runner
|
15
|
-
|
16
|
-
# QED::Runner.configure do
|
17
|
-
# def setup(spec)
|
18
|
-
# ...
|
19
|
-
# end
|
20
|
-
# def teardown(spec)
|
21
|
-
# ...
|
22
|
-
# end
|
23
|
-
# end
|
24
|
-
#def self.configure(plugin=nil, &block)
|
25
|
-
# if block_given?
|
26
|
-
# m = Module.new(&block)
|
27
|
-
# m.extend m
|
28
|
-
# @config << m
|
29
|
-
# end
|
30
|
-
# if plugin
|
31
|
-
# @config << plugin
|
32
|
-
# end
|
33
|
-
#end
|
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
|
-
#
|
48
|
-
attr :specs
|
49
|
-
|
50
|
-
#
|
51
|
-
attr_accessor :format
|
52
|
-
|
53
|
-
#
|
54
|
-
attr_accessor :trace
|
55
|
-
|
56
|
-
#attr :context
|
57
|
-
#attr :count
|
58
|
-
|
59
|
-
#attr_accessor :before
|
60
|
-
#attr_accessor :after
|
61
|
-
|
62
|
-
# New Specification
|
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
|
101
|
-
end
|
102
|
-
|
103
|
-
#
|
104
|
-
def check
|
105
|
-
start
|
106
|
-
output.report_intro
|
107
|
-
specs.each do |spec| # loop through each specification and run it
|
108
|
-
run_spec(spec) # run the specification
|
109
|
-
end
|
110
|
-
output.report_summary
|
111
|
-
finish
|
112
|
-
end
|
113
|
-
|
114
|
-
# Run a specification.
|
115
|
-
def run_spec(spec)
|
116
|
-
script = Script.new(spec, output)
|
117
|
-
|
118
|
-
# pretty sure this is the thing to do
|
119
|
-
Dir.chdir(File.dirname(spec)) do
|
120
|
-
|
121
|
-
output.report_start(spec)
|
122
|
-
|
123
|
-
# TODO <-- plugin in here start (how to set?)
|
124
|
-
#context.instance_eval(&spec.given) if spec.given
|
125
|
-
|
126
|
-
script.run
|
127
|
-
|
128
|
-
#spec.steps.each do |step|
|
129
|
-
#output.report_step(self)
|
130
|
-
#step.run(self, spec, context, output)
|
131
|
-
#output.report_step_end(self)
|
132
|
-
#end
|
133
|
-
|
134
|
-
# TODO <-- plugin in here end
|
135
|
-
#context.instance_eval(&spec.complete) if spec.complete
|
136
|
-
|
137
|
-
output.report_end(spec)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
=begin
|
142
|
-
# Run a specification step.
|
143
|
-
#
|
144
|
-
def run_step(spec, step)
|
145
|
-
output.report_step(step)
|
146
|
-
# TODO: Would spec.before + spec.code be better?
|
147
|
-
context.instance_eval(@before, spec.file) if @before
|
148
|
-
begin
|
149
|
-
context.instance_eval(step.code, spec.file, step.lineno)
|
150
|
-
output.report_pass(step)
|
151
|
-
rescue Assertion => error
|
152
|
-
output.report_fail(step, error)
|
153
|
-
rescue Exception => error
|
154
|
-
output.report_error(step, error)
|
155
|
-
ensure
|
156
|
-
context.instance_eval(@after, spec.file) if @after
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
# Run a specification tabular step.
|
161
|
-
#
|
162
|
-
# TODO: Table reporting needs to be improved. Big time!
|
163
|
-
def run_table(spec, step)
|
164
|
-
table = YAML.load(File.new(step.file)) # yaml or csv ?
|
165
|
-
|
166
|
-
vars = *table[0]
|
167
|
-
rows = table[1..-1]
|
168
|
-
|
169
|
-
output.report_step(step)
|
170
|
-
context.instance_eval(@before, spec.file) if @before
|
171
|
-
rows.each do |row|
|
172
|
-
set = vars.zip(row).map{ |a| "#{a[0]}=#{a[1].inspect}" }.join(';')
|
173
|
-
code = set + "\n" + step.code
|
174
|
-
begin
|
175
|
-
context.instance_eval(code, spec.file, step.lineno)
|
176
|
-
#output.report_literal(set)
|
177
|
-
output.report_pass(step)
|
178
|
-
rescue Assertion => error
|
179
|
-
output.report_fail(step, error)
|
180
|
-
rescue Exception => error
|
181
|
-
output.report_error(step, error)
|
182
|
-
ensure
|
183
|
-
context.instance_eval(@after, spec.file) if @after
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
=end
|
188
|
-
|
189
|
-
def start
|
190
|
-
end
|
191
|
-
|
192
|
-
def finish
|
193
|
-
end
|
194
|
-
|
195
|
-
end#class Runner
|
196
|
-
|
197
|
-
end#module QED
|
198
|
-
|
data/lib/qed/script1.rb
DELETED
@@ -1,495 +0,0 @@
|
|
1
|
-
module QED
|
2
|
-
require 'yaml'
|
3
|
-
require 'facets/dir/ascend'
|
4
|
-
|
5
|
-
require 'ae'
|
6
|
-
|
7
|
-
require 'qed/reporter/dotprogress'
|
8
|
-
require 'qed/reporter/summary'
|
9
|
-
require 'qed/reporter/verbatim'
|
10
|
-
|
11
|
-
#Assertion = AE::Assertion
|
12
|
-
Expectation = Assertor
|
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
|
-
|
26
|
-
# New Specification
|
27
|
-
#def initialize(specs, output=nil)
|
28
|
-
# @specs = [specs].flatten
|
29
|
-
#end
|
30
|
-
|
31
|
-
# = Script
|
32
|
-
#
|
33
|
-
class Script
|
34
|
-
|
35
|
-
#def self.load(file, output=nil)
|
36
|
-
# new(File.read(file), output)
|
37
|
-
#end
|
38
|
-
|
39
|
-
# Path of demonstration script.
|
40
|
-
attr :file
|
41
|
-
|
42
|
-
# Reporter object to issue output calls.
|
43
|
-
attr :output
|
44
|
-
|
45
|
-
# List of helper scripts to require.
|
46
|
-
attr :helpers
|
47
|
-
|
48
|
-
# New Script
|
49
|
-
def initialize(file, output=nil)
|
50
|
-
@file = file
|
51
|
-
@output = output || Reporter::Verbatim.new #(self)
|
52
|
-
parse #_document(file)
|
53
|
-
end
|
54
|
-
|
55
|
-
# File basename less extension.
|
56
|
-
def name
|
57
|
-
@name ||= File.basename(file).chomp(File.extname(file))
|
58
|
-
end
|
59
|
-
|
60
|
-
#
|
61
|
-
def directory
|
62
|
-
@directory ||= Dir.pwd #File.dirname(File.expand_path(file))
|
63
|
-
end
|
64
|
-
|
65
|
-
#def convert
|
66
|
-
# @source.gsub(/^\w/, '# \1')
|
67
|
-
#end
|
68
|
-
|
69
|
-
# Run the script.
|
70
|
-
def run
|
71
|
-
@lineno = 0
|
72
|
-
|
73
|
-
$LOAD_PATH.unshift(directory)
|
74
|
-
|
75
|
-
import_helpers
|
76
|
-
|
77
|
-
steps.each do |step|
|
78
|
-
output.report_step(step)
|
79
|
-
case step
|
80
|
-
when /^[=#]/
|
81
|
-
output.report_header(step)
|
82
|
-
when /^\S/
|
83
|
-
output.report_comment(step)
|
84
|
-
context.When.each do |(regex, proc)|
|
85
|
-
if md = regex.match(step)
|
86
|
-
proc.call(*md[1..-1])
|
87
|
-
end
|
88
|
-
end
|
89
|
-
else
|
90
|
-
#if context.table
|
91
|
-
# run_table(step)
|
92
|
-
#else
|
93
|
-
run_step(step)
|
94
|
-
#end
|
95
|
-
end
|
96
|
-
@lineno += step.count("\n")
|
97
|
-
end
|
98
|
-
|
99
|
-
$LOAD_PATH.index(directory){ |i| $LOAD_PATH.delete_at(i) }
|
100
|
-
end
|
101
|
-
|
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
|
-
#++
|
107
|
-
def run_step(step=nil, &blk)
|
108
|
-
QED.Before.call if QED.Before
|
109
|
-
context.Before.call if context.Before
|
110
|
-
begin
|
111
|
-
if blk # TODO: Is this still used?
|
112
|
-
blk.call #eval(step, context._binding)
|
113
|
-
else
|
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
|
121
|
-
end
|
122
|
-
output.report_pass(step) if step
|
123
|
-
rescue Assertion => error
|
124
|
-
output.report_fail(step, error)
|
125
|
-
rescue Exception => error
|
126
|
-
output.report_error(step, error)
|
127
|
-
ensure
|
128
|
-
context.After.call if context.After
|
129
|
-
QED.After.call if QED.After
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
=begin
|
134
|
-
#
|
135
|
-
def run_table(step)
|
136
|
-
file = context.table
|
137
|
-
Dir.ascend(Dir.pwd) do |path|
|
138
|
-
f1 = File.join(path, file)
|
139
|
-
f2 = File.join(path, 'fixtures', file)
|
140
|
-
fr = File.file?(f1) ? f1 : File.exist?(f2) ? f2 : nil
|
141
|
-
(file = fr; break) if fr
|
142
|
-
end
|
143
|
-
output.report_pass(step) #step)
|
144
|
-
|
145
|
-
tbl = YAML.load(File.new(file))
|
146
|
-
key = tbl.shift
|
147
|
-
tbl.each do |set|
|
148
|
-
assign = key.zip(set).map{ |k, v| "#{k}=#{v.inspect};" }.join
|
149
|
-
run_table_step(assign + step, set)
|
150
|
-
#run_step(set.inspect.tabto(4)){ blk.call(set) }
|
151
|
-
#@_script.run_step(set.to_yaml.tabto(2)){ blk.call(set) }
|
152
|
-
#@_script.output.report_table(set)
|
153
|
-
end
|
154
|
-
#output.report_pass(step) #step)
|
155
|
-
context.table = nil
|
156
|
-
end
|
157
|
-
|
158
|
-
#
|
159
|
-
#def run_table_step(step, set)
|
160
|
-
def run_table_step(set, &blk)
|
161
|
-
context.before.call if context.before
|
162
|
-
begin
|
163
|
-
#eval(step, context._binding, @file) # TODO: would be nice to know file and lineno here
|
164
|
-
blk.call(*set)
|
165
|
-
output.report_pass(' ' + set.inspect) #step)
|
166
|
-
rescue Assertion => error
|
167
|
-
output.report_fail(set.inspect, error)
|
168
|
-
rescue Exception => error
|
169
|
-
output.report_error(set.inspect, error)
|
170
|
-
ensure
|
171
|
-
context.after.call if context.after
|
172
|
-
end
|
173
|
-
end
|
174
|
-
=end
|
175
|
-
|
176
|
-
# Cut-up script into steps.
|
177
|
-
def steps
|
178
|
-
@steps ||= (
|
179
|
-
code = false
|
180
|
-
str = ''
|
181
|
-
steps = []
|
182
|
-
@source.each_line do |line|
|
183
|
-
if /^\s*$/.match line
|
184
|
-
str << line
|
185
|
-
elsif /^[=]/.match line
|
186
|
-
steps << str #.chomp("\n")
|
187
|
-
steps << line #.chomp("\n")
|
188
|
-
str = ''
|
189
|
-
#str << line
|
190
|
-
code = false
|
191
|
-
elsif /^\S/.match line
|
192
|
-
if code
|
193
|
-
steps << str #.chomp("\n")
|
194
|
-
str = ''
|
195
|
-
str << line
|
196
|
-
code = false
|
197
|
-
else
|
198
|
-
str << line
|
199
|
-
end
|
200
|
-
else
|
201
|
-
if code
|
202
|
-
str << line
|
203
|
-
else
|
204
|
-
steps << str
|
205
|
-
str = ''
|
206
|
-
str << line
|
207
|
-
code = true
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
steps << str
|
212
|
-
#steps.map{ |s| s.chomp("\n") }
|
213
|
-
steps
|
214
|
-
)
|
215
|
-
end
|
216
|
-
|
217
|
-
#
|
218
|
-
def to_html
|
219
|
-
require 'tilt'
|
220
|
-
Tilt.new(file).render
|
221
|
-
end
|
222
|
-
|
223
|
-
#
|
224
|
-
def parse
|
225
|
-
steps = []
|
226
|
-
require 'nokogiri'
|
227
|
-
doc = Nokogiri::HTML(to_html)
|
228
|
-
doc.root.traverse do |elem|
|
229
|
-
case elem.name
|
230
|
-
when /h*/
|
231
|
-
steps << Head.new(elem.text)
|
232
|
-
when "p"
|
233
|
-
steps << Text.new(elem.text)
|
234
|
-
when 'pre'
|
235
|
-
steps << Code.new(elem.text)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
steps
|
239
|
-
end
|
240
|
-
|
241
|
-
class Head
|
242
|
-
attr :text
|
243
|
-
def initialize(text)
|
244
|
-
@text = text
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
class Code
|
249
|
-
attr :text
|
250
|
-
def initialize(text)
|
251
|
-
@text = text
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
class Text
|
256
|
-
attr :text
|
257
|
-
def initialize(text)
|
258
|
-
@text = text
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
# The run context.
|
263
|
-
def context
|
264
|
-
@context ||= Context.new(self)
|
265
|
-
end
|
266
|
-
|
267
|
-
#
|
268
|
-
def import(helper)
|
269
|
-
code = File.read(helper)
|
270
|
-
eval(code, context._binding)
|
271
|
-
end
|
272
|
-
|
273
|
-
private
|
274
|
-
|
275
|
-
# Splits the document into main source and footer
|
276
|
-
# and extract the helper document references from
|
277
|
-
# the footer.
|
278
|
-
#
|
279
|
-
def parse_document(file)
|
280
|
-
text = File.read(file)
|
281
|
-
index = text.rindex('---') || text.size
|
282
|
-
source = text[0...index]
|
283
|
-
footer = text[index+3..-1].to_s.strip
|
284
|
-
#helpers = parse_helpers(footer)
|
285
|
-
@source = source
|
286
|
-
@footer = footer
|
287
|
-
end
|
288
|
-
|
289
|
-
#
|
290
|
-
def parse_helpers(footer)
|
291
|
-
helpers = []
|
292
|
-
footer.split("\n").each do |line|
|
293
|
-
next if line.strip == ''
|
294
|
-
case line
|
295
|
-
when /\[(.*?)\]\((.*?)\)/
|
296
|
-
helpers << $2
|
297
|
-
when /(.*?)\[(.*?)\]/
|
298
|
-
helpers << $2
|
299
|
-
end
|
300
|
-
end
|
301
|
-
helpers
|
302
|
-
end
|
303
|
-
|
304
|
-
=begin
|
305
|
-
# Looks for a master +helper.rb+ file and a special
|
306
|
-
# helpers/<name>.rb file. Both of these, when found, will
|
307
|
-
# be imported when this script is run.
|
308
|
-
|
309
|
-
def collect_helpers
|
310
|
-
dir = File.dirname(file)
|
311
|
-
list = []
|
312
|
-
list << "helper.rb" if File.exist?(File.join(dir, "helper.rb"))
|
313
|
-
list << "helpers/#{name}.rb" if File.exist?(File.join(dir, "helpers/#{name}.rb"))
|
314
|
-
list
|
315
|
-
end
|
316
|
-
=end
|
317
|
-
|
318
|
-
# TODO: How to determine where to find the env.rb file?
|
319
|
-
#def require_environment
|
320
|
-
# dir = File.dirname(file)
|
321
|
-
# dir = File.expand_path(dir)
|
322
|
-
# env = loop do
|
323
|
-
# file = File.join(dir, 'env.rb')
|
324
|
-
# break file if File.exist?(file)
|
325
|
-
# break nil if ['demo', 'demos', 'doc', 'docs', 'test', 'tests'].include? File.basename(dir)
|
326
|
-
# break nil if dir == Dir.pwd
|
327
|
-
# dir = File.dirname(dir)
|
328
|
-
# end
|
329
|
-
# require(env) if env
|
330
|
-
#end
|
331
|
-
|
332
|
-
# FIXME: where to stop looking for helpers.
|
333
|
-
def import_helpers
|
334
|
-
hlp = []
|
335
|
-
dir = Dir.pwd #File.expand_path(dir)
|
336
|
-
env = loop do
|
337
|
-
helpers.each do |helper|
|
338
|
-
file = File.join(dir, 'helpers', helper)
|
339
|
-
if File.exist?(file)
|
340
|
-
hlp << file
|
341
|
-
end
|
342
|
-
end
|
343
|
-
break if ['qed', 'demo', 'demos', 'doc', 'docs', 'test', 'tests'].include? File.basename(dir)
|
344
|
-
dir = File.dirname(dir)
|
345
|
-
end
|
346
|
-
hlp.each{ |helper| import(helper) }
|
347
|
-
end
|
348
|
-
|
349
|
-
end
|
350
|
-
|
351
|
-
#
|
352
|
-
class Context < Module
|
353
|
-
|
354
|
-
TABLE = /^TABLE\[(.*?)\]/i
|
355
|
-
|
356
|
-
def initialize(script)
|
357
|
-
@_script = script
|
358
|
-
@_when = []
|
359
|
-
@_tables = []
|
360
|
-
end
|
361
|
-
|
362
|
-
def _binding
|
363
|
-
@_binding ||= binding
|
364
|
-
end
|
365
|
-
|
366
|
-
# Before each step.
|
367
|
-
def Before(&procedure)
|
368
|
-
@_before = procedure if procedure
|
369
|
-
@_before
|
370
|
-
end
|
371
|
-
|
372
|
-
# After each step.
|
373
|
-
def After(&procedure)
|
374
|
-
@_after = procedure if procedure
|
375
|
-
@_after
|
376
|
-
end
|
377
|
-
|
378
|
-
# Run code around each step.
|
379
|
-
#
|
380
|
-
# Around procedures must take a block, in which the step is run.
|
381
|
-
#
|
382
|
-
# Around do |&step|
|
383
|
-
# ... do something here ...
|
384
|
-
# step.call
|
385
|
-
# ... do stiff stuff ...
|
386
|
-
# end
|
387
|
-
#
|
388
|
-
#def Around(&procedure)
|
389
|
-
# @_around = procedure if procedure
|
390
|
-
# @_around
|
391
|
-
#end
|
392
|
-
|
393
|
-
# Comment match procedure.
|
394
|
-
#
|
395
|
-
# This is useful for creating unobtrusive setup and (albeit more
|
396
|
-
# limited) teardown code. A pattern is matched against each comment
|
397
|
-
# as it is processed. If there is match, the code procedure is
|
398
|
-
# triggered, passing in any mathcing expression arguments.
|
399
|
-
#
|
400
|
-
def When(pattern=nil, &procedure)
|
401
|
-
return @_when unless procedure
|
402
|
-
raise ArgumentError unless pattern
|
403
|
-
unless Regexp === pattern
|
404
|
-
pattern = __when_string_to_regexp(pattern)
|
405
|
-
end
|
406
|
-
@_when << [pattern, procedure]
|
407
|
-
end
|
408
|
-
|
409
|
-
# Code match-and-transform procedure.
|
410
|
-
#
|
411
|
-
# This is useful to transform human readable code examples
|
412
|
-
# into proper exectuable code. For example, say you want to
|
413
|
-
# run shell code, but want to make if look like typical
|
414
|
-
# shelle examples:
|
415
|
-
#
|
416
|
-
# $ cp fixture/a.rb fixture/b.rb
|
417
|
-
#
|
418
|
-
# You can use a transform to convert lines starting with '$'
|
419
|
-
# into executable Ruby using #system.
|
420
|
-
#
|
421
|
-
# system('cp fixture/a.rb fixture/b.rb')
|
422
|
-
#
|
423
|
-
#def Transform(pattern=nil, &procedure)
|
424
|
-
#
|
425
|
-
#end
|
426
|
-
|
427
|
-
# Table-based steps.
|
428
|
-
def Table(file=nil, &blk)
|
429
|
-
file = file || @_tables.last
|
430
|
-
tbl = YAML.load(File.new(file))
|
431
|
-
tbl.each do |set|
|
432
|
-
blk.call(*set)
|
433
|
-
end
|
434
|
-
@_tables << file
|
435
|
-
end
|
436
|
-
|
437
|
-
# Read/Write a fixture.
|
438
|
-
def Data(file, &content)
|
439
|
-
raise if File.directory?(file)
|
440
|
-
if content
|
441
|
-
FileUtils.mkdir_p(File.dirname(fname))
|
442
|
-
case File.extname(file)
|
443
|
-
when '.yml', '.yaml'
|
444
|
-
File.open(file, 'w'){ |f| f << content.call.to_yaml }
|
445
|
-
else
|
446
|
-
File.open(file, 'w'){ |f| f << content.call }
|
447
|
-
end
|
448
|
-
else
|
449
|
-
#raise LoadError, "no such fixture file -- #{fname}" unless File.exist?(fname)
|
450
|
-
case File.extname(file)
|
451
|
-
when '.yml', '.yaml'
|
452
|
-
YAML.load(File.new(file))
|
453
|
-
else
|
454
|
-
File.read(file)
|
455
|
-
end
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
|
-
private
|
460
|
-
|
461
|
-
def __when_string_to_regexp(str)
|
462
|
-
str = str.split(/(\(\(.*?\)\))(?!\))/).map{ |x|
|
463
|
-
x =~ /\A\(\((.*)\)\)\z/ ? $1 : Regexp.escape(x)
|
464
|
-
}.join
|
465
|
-
str = str.gsub(/(\\\ )+/, '\s+')
|
466
|
-
Regexp.new(str, Regexp::IGNORECASE)
|
467
|
-
|
468
|
-
#rexps = []
|
469
|
-
#str = str.gsub(/\(\((.*?)\)\)/) do |m|
|
470
|
-
# rexps << '(' + $1 + ')'
|
471
|
-
# "\0"
|
472
|
-
#end
|
473
|
-
#str = Regexp.escape(str)
|
474
|
-
#rexps.each do |r|
|
475
|
-
# str = str.sub("\0", r)
|
476
|
-
#end
|
477
|
-
#str = str.gsub(/(\\\ )+/, '\s+')
|
478
|
-
#Regexp.new(str, Regexp::IGNORECASE)
|
479
|
-
end
|
480
|
-
|
481
|
-
#
|
482
|
-
# check only local and maybe start paths
|
483
|
-
#def __locate_file(file)
|
484
|
-
# Dir.ascend(Dir.pwd) do |path|
|
485
|
-
# f1 = File.join(path, file)
|
486
|
-
# f2 = File.join(path, 'fixtures', file)
|
487
|
-
# fr = File.file?(f1) ? f1 : File.exist?(f2) ? f2 : nil
|
488
|
-
# (file = fr; break) if fr
|
489
|
-
# end
|
490
|
-
#end
|
491
|
-
|
492
|
-
end
|
493
|
-
|
494
|
-
end
|
495
|
-
|