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