qed 1.2 → 1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +2 -2
- data/Syckfile +70 -0
- data/demo/01_spec.qed +7 -7
- data/demo/02_err.qed +18 -0
- data/demo/03_site.qed +12 -0
- data/demo/helpers/sample.rb +4 -0
- data/doc/qedoc/index.html +31 -10
- data/lib/qed/command.rb +167 -61
- data/lib/qed/config.rb +25 -0
- data/lib/qed/document.rb +1 -1
- data/lib/qed/document/template.rhtml +1 -1
- data/lib/qed/reporter/ditto.rb +72 -0
- data/lib/qed/reporter/dotprogress.rb +11 -2
- data/lib/qed/runner.rb +69 -19
- data/lib/qed/script.rb +171 -13
- data/lib/qed/script1.rb +495 -0
- data/meta/description +2 -2
- data/meta/summary +1 -1
- data/meta/version +1 -1
- metadata +15 -13
- data/MANIFEST +0 -37
- data/demo/helper.rb +0 -2
data/README.rdoc
CHANGED
@@ -44,11 +44,11 @@ In this example, because 4 != 5, this expression will raise an Assertion
|
|
44
44
|
exception. QED's Runner class is thus just a means of running and capturing
|
45
45
|
code block containing these assertions.
|
46
46
|
|
47
|
-
You can learn more about AE at http://proutils.
|
47
|
+
You can learn more about AE at http://proutils.github.com/ae.
|
48
48
|
|
49
49
|
=== Document Structure
|
50
50
|
|
51
|
-
QED documents are simply text files --thus a practice of
|
51
|
+
QED documents are simply text files --thus a practice of literate programming.
|
52
52
|
For example:
|
53
53
|
|
54
54
|
= Example
|
data/Syckfile
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
---
|
2
|
+
stats:
|
3
|
+
service : Stats
|
4
|
+
title : ~
|
5
|
+
loadpath : ~
|
6
|
+
exclude : ~
|
7
|
+
output : ~
|
8
|
+
active : true
|
9
|
+
|
10
|
+
box:
|
11
|
+
service: Box
|
12
|
+
active : true
|
13
|
+
types : [ gem, tar ]
|
14
|
+
spec : true
|
15
|
+
include: [ bin, demo, doc, lib, meta, test, "[A-Z]*" ]
|
16
|
+
exclude: [ doc/rdoc, doc/ri ]
|
17
|
+
|
18
|
+
dnote:
|
19
|
+
service : DNote
|
20
|
+
loadpath : ~
|
21
|
+
labels : ~
|
22
|
+
output : ~
|
23
|
+
format : ~
|
24
|
+
active : true
|
25
|
+
|
26
|
+
email:
|
27
|
+
service : Email
|
28
|
+
file : ~
|
29
|
+
subject : ~
|
30
|
+
mailto :
|
31
|
+
- ruby-talk@ruby-lang.org
|
32
|
+
- proutils@googlegroups.com
|
33
|
+
from : <%= ENV['EMAIL_ACCOUNT'] %>
|
34
|
+
server : <%= ENV['EMAIL_SERVER'] %>
|
35
|
+
port : <%= ENV['EMAIL_PORT'] %>
|
36
|
+
account : <%= ENV['EMAIL_ACCOUNT'] %>
|
37
|
+
domain : <%= ENV['EMAIL_DOMAIN'] %>
|
38
|
+
login : <%= ENV['EMAIL_LOGIN'] %>
|
39
|
+
secure : <%= ENV['EMAIL_SECURE'] %>
|
40
|
+
active : true
|
41
|
+
|
42
|
+
ridoc:
|
43
|
+
service: RIDoc
|
44
|
+
include: ~
|
45
|
+
exclude: ~
|
46
|
+
active : true
|
47
|
+
|
48
|
+
syntax:
|
49
|
+
service : Syntax
|
50
|
+
loadpath : ~
|
51
|
+
exclude : ~
|
52
|
+
active : false
|
53
|
+
|
54
|
+
testrb:
|
55
|
+
service : TestUnit
|
56
|
+
tests : ~
|
57
|
+
exclude : ~
|
58
|
+
loadpath : ~
|
59
|
+
requires : ~
|
60
|
+
live : false
|
61
|
+
active : false
|
62
|
+
|
63
|
+
vclog:
|
64
|
+
service : VClog
|
65
|
+
format : html # xml, txt
|
66
|
+
layout : rel # gnu
|
67
|
+
typed : false
|
68
|
+
output : ~
|
69
|
+
active : false
|
70
|
+
|
data/demo/01_spec.qed
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
= Standard Sections
|
2
2
|
|
3
|
-
QED demos are light-weight specification documents, suitable
|
4
|
-
|
3
|
+
QED demos are light-weight specification documents, highly suitable
|
4
|
+
to interface-driven design. The documents are divided up into
|
5
5
|
clauses separated by blank lines. Clauses that are flush to the
|
6
6
|
left margin are always explanation or comment clauses. Indented
|
7
7
|
clauses are always executable code.
|
@@ -121,7 +121,7 @@ a separate file. The +Data+ method makes is easy to load such files.
|
|
121
121
|
|
122
122
|
Data('data.txt').assert =~ /dolor/
|
123
123
|
|
124
|
-
All files are
|
124
|
+
All files are found relative to the location of current document.
|
125
125
|
|
126
126
|
= Tabular Steps
|
127
127
|
|
@@ -129,9 +129,9 @@ The +Table+ method is similar to the +Data+ method except that it
|
|
129
129
|
expects a YAML file, and it can take a block to iterate the data over.
|
130
130
|
This makes it easy to test tables of examples.
|
131
131
|
|
132
|
-
The arity of the table block
|
133
|
-
|
134
|
-
|
132
|
+
The arity of the table block corresponds to the number of columns in
|
133
|
+
each row of the table. Each row is assigned in turn and run through
|
134
|
+
the coded step. Consider the following example:
|
135
135
|
|
136
136
|
Every row in the {table.yml table}[table.yml] will be assigned to
|
137
137
|
the block parameters and run through the subsequent assertion.
|
@@ -171,5 +171,5 @@ This concludes the basic overview of QED's specification system, which
|
|
171
171
|
is itself a QED document. Yes, we eat our own dog food.
|
172
172
|
|
173
173
|
---
|
174
|
-
|
174
|
+
1[helper.rb] Helper
|
175
175
|
|
data/demo/02_err.qed
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= Examples of Failure
|
2
|
+
|
3
|
+
This document is here simply to demonstrate what
|
4
|
+
a failed step looks like.
|
5
|
+
|
6
|
+
1.assert == 2
|
7
|
+
|
8
|
+
And this step demonstrates an error.
|
9
|
+
|
10
|
+
raise "just because"
|
11
|
+
|
12
|
+
When run with the -v (verbatim) option, +qed+ will
|
13
|
+
highlight these in red and give a brief error
|
14
|
+
message.
|
15
|
+
|
16
|
+
---
|
17
|
+
1[sample.rb] Sample Helper
|
18
|
+
|
data/demo/03_site.qed
ADDED
data/doc/qedoc/index.html
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<html>
|
2
2
|
<head>
|
3
|
-
<title>
|
3
|
+
<title>QED Demonstrandum</title>
|
4
4
|
|
5
5
|
<style>
|
6
6
|
#container{ margin: 0 auto; width: 800px; }
|
@@ -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 {
|
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
|
|
@@ -89,7 +89,7 @@
|
|
89
89
|
<div id="header">
|
90
90
|
<img src="img/icon/book.jpg" align="left" style="padding-right: 10px;" alt=""/>
|
91
91
|
|
92
|
-
<h1 class="title">
|
92
|
+
<h1 class="title">QED Demonstrandum</h1>
|
93
93
|
|
94
94
|
<h1>Table of Contents</h1>
|
95
95
|
|
@@ -100,8 +100,8 @@
|
|
100
100
|
<div id="content">
|
101
101
|
<h1>Standard Sections</h1>
|
102
102
|
<p>
|
103
|
-
QED demos are light-weight specification documents, suitable
|
104
|
-
|
103
|
+
QED demos are light-weight specification documents, highly suitable to
|
104
|
+
interface-driven design. The documents are divided up into clauses
|
105
105
|
separated by blank lines. Clauses that are flush to the left margin are
|
106
106
|
always explanation or comment clauses. Indented clauses are always
|
107
107
|
executable code.
|
@@ -249,7 +249,7 @@ The <tt>Data</tt> method makes is easy to load such files.
|
|
249
249
|
Data('data.txt').assert =~ /dolor/
|
250
250
|
</pre>
|
251
251
|
<p>
|
252
|
-
All files are
|
252
|
+
All files are found relative to the location of current document.
|
253
253
|
</p>
|
254
254
|
<h1>Tabular Steps</h1>
|
255
255
|
<p>
|
@@ -258,9 +258,9 @@ that it expects a YAML file, and it can take a block to iterate the data
|
|
258
258
|
over. This makes it easy to test tables of examples.
|
259
259
|
</p>
|
260
260
|
<p>
|
261
|
-
The arity of the table block
|
262
|
-
the table
|
263
|
-
|
261
|
+
The arity of the table block corresponds to the number of columns in each
|
262
|
+
row of the table. Each row is assigned in turn and run through the coded
|
263
|
+
step. Consider the following example:
|
264
264
|
</p>
|
265
265
|
<p>
|
266
266
|
Every row in the <a href="http://table.yml">table.yml table</a> will be
|
@@ -310,7 +310,28 @@ This concludes the basic overview of QED’s specification system,
|
|
310
310
|
which is itself a QED document. Yes, we eat our own dog food.
|
311
311
|
</p>
|
312
312
|
<hr size="1"></hr><p>
|
313
|
-
|
313
|
+
<a href="http://helper.rb">1</a> Helper
|
314
|
+
</p>
|
315
|
+
|
316
|
+
<h1>Examples of Failure</h1>
|
317
|
+
<p>
|
318
|
+
This document is here simply to demonstrate what a failed step looks like.
|
319
|
+
</p>
|
320
|
+
<pre>
|
321
|
+
1.assert == 2
|
322
|
+
</pre>
|
323
|
+
<p>
|
324
|
+
And this step demonstrates an error.
|
325
|
+
</p>
|
326
|
+
<pre>
|
327
|
+
raise "just because"
|
328
|
+
</pre>
|
329
|
+
<p>
|
330
|
+
When run with the -v (verbatim) option, <tt>qed</tt> will highlight these
|
331
|
+
in red and give a brief error message.
|
332
|
+
</p>
|
333
|
+
<hr size="1"></hr><p>
|
334
|
+
<a href="http://helper.rb">1</a> Helper
|
314
335
|
</p>
|
315
336
|
|
316
337
|
|
data/lib/qed/command.rb
CHANGED
@@ -2,58 +2,127 @@
|
|
2
2
|
|
3
3
|
require 'qed'
|
4
4
|
require 'optparse'
|
5
|
+
require 'shellwords'
|
5
6
|
|
6
7
|
module QED
|
7
8
|
|
8
9
|
# = QED Commandline Tool
|
9
10
|
#
|
10
11
|
class Command
|
12
|
+
|
13
|
+
# Configuration directory.
|
14
|
+
CONFDIR = "{.,}config/qed"
|
15
|
+
|
16
|
+
# Initialize and execute.
|
11
17
|
def self.execute
|
12
18
|
new.execute
|
13
19
|
end
|
14
20
|
|
15
|
-
#
|
21
|
+
# Ouput format.
|
16
22
|
attr :format
|
17
23
|
|
24
|
+
# Make sure format is a symbol.
|
25
|
+
def format=(type)
|
26
|
+
@format = type.to_sym
|
27
|
+
end
|
28
|
+
|
29
|
+
# Trace execution?
|
30
|
+
attr :trace
|
31
|
+
|
32
|
+
# Options defined by selected profile.
|
33
|
+
attr :profile
|
34
|
+
|
35
|
+
# Command-line options.
|
36
|
+
attr :options
|
37
|
+
|
38
|
+
# Files to be run.
|
39
|
+
attr :files
|
40
|
+
|
18
41
|
#
|
42
|
+
def files=(globs)
|
43
|
+
@files = [globs].flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
attr_accessor :loadpath
|
48
|
+
|
49
|
+
#
|
50
|
+
attr_accessor :requires
|
51
|
+
|
52
|
+
#
|
53
|
+
attr_accessor :env
|
54
|
+
|
55
|
+
#
|
56
|
+
|
19
57
|
def initialize
|
20
|
-
@format
|
58
|
+
@format = nil
|
59
|
+
@env = nil
|
60
|
+
@profile = nil
|
61
|
+
@requires = []
|
62
|
+
@loadpath = []
|
63
|
+
@files = []
|
64
|
+
@options = {}
|
21
65
|
end
|
22
66
|
|
23
67
|
# Instance of OptionParser
|
68
|
+
|
24
69
|
def opts
|
25
70
|
@opts ||= OptionParser.new do |opt|
|
26
71
|
|
72
|
+
opt.separator("Custom Profiles:") unless profiles.empty?
|
73
|
+
|
74
|
+
profiles.each do |name, value|
|
75
|
+
o = "--#{name}"
|
76
|
+
opt.on(o, "#{name} custom profile") do
|
77
|
+
@profile = name
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
opt.separator("Report Options (pick one):")
|
82
|
+
|
27
83
|
opt.on('--dotprogress', '-d', "use dot-progress reporter [default]") do
|
28
|
-
@format = :summary
|
84
|
+
@options[:format] = :summary
|
29
85
|
end
|
30
86
|
|
31
87
|
opt.on('--verbatim', '-v', "use verbatim reporter") do
|
32
|
-
@format = :verbatim
|
88
|
+
@options[:format] = :verbatim
|
33
89
|
end
|
34
90
|
|
35
91
|
opt.on('--summary', '-s', "use summary reporter") do
|
36
|
-
@format = :summary
|
92
|
+
@options[:format] = :summary
|
37
93
|
end
|
38
94
|
|
39
95
|
opt.on('--script', "psuedo-reporter") do
|
40
|
-
@
|
96
|
+
@options[:script] # psuedo-reporter
|
97
|
+
end
|
98
|
+
|
99
|
+
opt.separator("Control Options:")
|
100
|
+
|
101
|
+
opt.on('--env', '-e [NAME]', "runtime environment [default]") do |name|
|
102
|
+
@options[:env] = name
|
103
|
+
end
|
104
|
+
|
105
|
+
opt.on('--loadpath', "-I PATH", "add paths to $LOAD_PATH") do |arg|
|
106
|
+
@options[:loadpath] ||= []
|
107
|
+
@options[:loadpath].concat(arg.split(/[:;]/).map{ |dir| File.expand_path(dir) })
|
41
108
|
end
|
42
109
|
|
43
|
-
opt.on('--
|
44
|
-
|
45
|
-
|
110
|
+
opt.on('--require', "-r", "require library") do |arg|
|
111
|
+
@options[:requires] ||= []
|
112
|
+
@options[:requires].concat(arg.split(/[:;]/)) #.map{ |dir| File.expand_path(dir) })
|
46
113
|
end
|
47
114
|
|
48
|
-
opt.on('--
|
49
|
-
@
|
50
|
-
$VERBOSE = true
|
115
|
+
opt.on('--trace', '-t', "show full backtraces for exceptions") do
|
116
|
+
@options[:trace] = true
|
51
117
|
end
|
52
118
|
|
53
|
-
opt.on('--debug', "
|
119
|
+
opt.on('--debug', "exit immediately upon raised exception") do
|
120
|
+
$VERBOSE = true # wish this were called $WARN
|
54
121
|
$DEBUG = true
|
55
122
|
end
|
56
123
|
|
124
|
+
opt.separator("Optional Commands:")
|
125
|
+
|
57
126
|
opt.on_tail('--version', "display version") do
|
58
127
|
puts "QED #{VERSION}"
|
59
128
|
exit
|
@@ -73,35 +142,24 @@ module QED
|
|
73
142
|
end
|
74
143
|
|
75
144
|
#
|
76
|
-
#def load_rc
|
77
|
-
# if rcfile = Dir['.config/qed{,rc}{,.rb}'].first
|
78
|
-
# load(rcfile)
|
79
|
-
# end
|
80
|
-
#end
|
81
|
-
|
82
|
-
# TODO: Better way to load helpers?
|
83
|
-
#
|
84
|
-
#def load_helpers
|
85
|
-
# dirs = spec_files.map{ |file| File.join(Dir.pwd, File.dirname(file)) }
|
86
|
-
# dirs = dirs.select{ |dir| File.directory?(dir) }
|
87
|
-
# dirs.each do |dir|
|
88
|
-
# while dir != '/' do
|
89
|
-
# helper = File.join(dir, 'qed_helper.rb')
|
90
|
-
# load(helper) if File.exist?(helper)
|
91
|
-
# break if Dir.pwd == dir
|
92
|
-
# dir = File.dirname(dir)
|
93
|
-
# end
|
94
|
-
# end
|
95
|
-
#end
|
96
145
|
|
97
|
-
#
|
98
146
|
def demos
|
99
147
|
demo_files
|
100
148
|
end
|
101
149
|
|
102
150
|
#
|
151
|
+
|
103
152
|
def demo_files
|
104
|
-
files =
|
153
|
+
files = self.files
|
154
|
+
|
155
|
+
#if files.empty?
|
156
|
+
# if File.directory?('test')
|
157
|
+
# files << 'test/doc{,s}'
|
158
|
+
# files << 'test/demo{,s}'
|
159
|
+
# end
|
160
|
+
#end
|
161
|
+
|
162
|
+
files = files.map do |pattern|
|
105
163
|
Dir[pattern]
|
106
164
|
end.flatten.uniq
|
107
165
|
|
@@ -113,7 +171,7 @@ module QED
|
|
113
171
|
end
|
114
172
|
end
|
115
173
|
|
116
|
-
|
174
|
+
files = files.flatten.uniq
|
117
175
|
|
118
176
|
#files = files.select do |file|
|
119
177
|
# %w{.yml .yaml .rb}.include?(File.extname(file))
|
@@ -122,38 +180,48 @@ module QED
|
|
122
180
|
files
|
123
181
|
end
|
124
182
|
|
125
|
-
#
|
126
|
-
def reporter
|
127
|
-
case format
|
128
|
-
when :dotprogress
|
129
|
-
Reporter::DotProgress.new(reporter_options)
|
130
|
-
when :verbatim
|
131
|
-
Reporter::Verbatim.new(reporter_options)
|
132
|
-
when :summary
|
133
|
-
Reporter::Summary.new(reporter_options)
|
134
|
-
else
|
135
|
-
nil
|
136
|
-
end
|
137
|
-
end
|
183
|
+
# Instance of Runner class.
|
138
184
|
|
139
|
-
|
140
|
-
|
141
|
-
{ :verbose => @verbose }
|
185
|
+
def runner
|
186
|
+
Runner.new(demos, :format=>format, :trace=>trace)
|
142
187
|
end
|
143
188
|
|
144
|
-
#
|
145
|
-
|
146
|
-
|
189
|
+
# Parse command-line options along with profile options.
|
190
|
+
|
191
|
+
def parse
|
192
|
+
@files = []
|
193
|
+
argv = ARGV.dup
|
194
|
+
opts.parse!(argv)
|
195
|
+
@files.concat(argv)
|
196
|
+
|
197
|
+
if profile
|
198
|
+
args = profiles[profile]
|
199
|
+
argv = Shellwords.shellwords(args)
|
200
|
+
opts.parse!(argv)
|
201
|
+
@files.concat(argv)
|
202
|
+
end
|
203
|
+
|
204
|
+
options.each do |k,v|
|
205
|
+
__send__("#{k}=", v)
|
206
|
+
end
|
147
207
|
end
|
148
208
|
|
149
|
-
#
|
209
|
+
# Run demonstrations.
|
210
|
+
|
150
211
|
def execute
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
212
|
+
parse
|
213
|
+
|
214
|
+
abort "No documents." if demos.empty?
|
215
|
+
|
216
|
+
prepare_loadpath
|
217
|
+
|
218
|
+
require_libraries
|
219
|
+
require_environment
|
220
|
+
|
221
|
+
# TODO: Remove case, can :script be done with Reporter or do we ne need selectable Runner?
|
222
|
+
case format
|
155
223
|
when :script
|
156
|
-
|
224
|
+
demos.each do |spec|
|
157
225
|
puts spec.to_script
|
158
226
|
end
|
159
227
|
else
|
@@ -161,6 +229,44 @@ module QED
|
|
161
229
|
end
|
162
230
|
end
|
163
231
|
|
232
|
+
# Profile configurations.
|
233
|
+
|
234
|
+
def profiles
|
235
|
+
@profiles ||= (
|
236
|
+
file = Dir["#{CONFDIR}/profile{,s}.{yml,yaml}"].first
|
237
|
+
file ? YAML.load(File.new(file)) : {}
|
238
|
+
)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Add to load path (from -I option).
|
242
|
+
|
243
|
+
def prepare_loadpath
|
244
|
+
loadpath.each{ |dir| $LOAD_PATH.unshift(dir) }
|
245
|
+
end
|
246
|
+
|
247
|
+
# Require libraries (from -r option).
|
248
|
+
|
249
|
+
def require_libraries
|
250
|
+
requires.each{ |file| require(file) }
|
251
|
+
end
|
252
|
+
|
253
|
+
# Require requirement file (from -e option.
|
254
|
+
|
255
|
+
def require_environment
|
256
|
+
if env
|
257
|
+
if file = Dir["#{CONFDIR}/{env,environments}/#{env}.rb"].first
|
258
|
+
require(file)
|
259
|
+
end
|
260
|
+
else
|
261
|
+
if file = Dir["#{CONFDIR}/env.rb"].first
|
262
|
+
require(file)
|
263
|
+
elsif file = Dir["#{CONFDIR}/{env,environments}/default.rb"].first
|
264
|
+
require(file)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
164
269
|
end
|
270
|
+
|
165
271
|
end
|
166
272
|
|