qed 1.1.0 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +40 -2
- data/MANIFEST +7 -12
- data/README.rdoc +30 -23
- data/bin/qed +1 -147
- data/demo/01_spec.qed +82 -53
- data/demo/data.txt +1 -0
- data/demo/{qed_helper.rb → helper.rb} +1 -0
- data/demo/table.yml +5 -0
- data/doc/qedoc/index.html +98 -53
- data/lib/qed.rb +1 -1
- data/lib/qed/command.rb +166 -0
- data/lib/qed/document.rb +43 -13
- data/lib/qed/reporter/base.rb +12 -5
- data/lib/qed/reporter/dotprogress.rb +1 -1
- data/lib/qed/reporter/summary.rb +2 -1
- data/lib/qed/reporter/verbatim.rb +11 -12
- data/lib/qed/script.rb +140 -33
- data/meta/description +2 -2
- data/meta/homepage +1 -1
- data/meta/{package → name} +0 -0
- data/meta/repository +1 -0
- data/meta/{project → suite} +0 -0
- data/meta/version +1 -1
- metadata +15 -13
- data/demo/01_spec.yaml +0 -4
data/HISTORY
CHANGED
@@ -1,6 +1,43 @@
|
|
1
1
|
= RELEASE HISTORY
|
2
2
|
|
3
|
-
== 1.
|
3
|
+
== 1.2 / 2009-12-07
|
4
|
+
|
5
|
+
This release adds a significant new feature, Comment Matchers.
|
6
|
+
These work like Cucumber allowing for background code to
|
7
|
+
be run when matching comments occur --a much better solution
|
8
|
+
for setup and teardown.
|
9
|
+
|
10
|
+
Changes:
|
11
|
+
|
12
|
+
* 2 Major Enhancements
|
13
|
+
|
14
|
+
* Added command matchers via #When method.
|
15
|
+
* All QED methods are now capitalized.
|
16
|
+
|
17
|
+
* 2 Minor Enhancements
|
18
|
+
|
19
|
+
* Use OptionParser for qed exectuable.
|
20
|
+
* Verbatim reporter is literally verbatim.
|
21
|
+
|
22
|
+
|
23
|
+
== 1.1 / 2009-09-05
|
24
|
+
|
25
|
+
This release
|
26
|
+
|
27
|
+
Changes:
|
28
|
+
|
29
|
+
* 2 Major Enhancements
|
30
|
+
|
31
|
+
* Helpers are provided by bottom code.
|
32
|
+
* Added Markdown header support.
|
33
|
+
|
34
|
+
* 2 Minor Enhancements
|
35
|
+
|
36
|
+
* Use Ansi project for color output.
|
37
|
+
* Use latest RDoc version.
|
38
|
+
|
39
|
+
|
40
|
+
== 1.0 / 2009-06-30
|
4
41
|
|
5
42
|
QED has found itself. It took some time to really figure out
|
6
43
|
what this project "was" and how it should best be utilized.
|
@@ -9,7 +46,8 @@ perpective.
|
|
9
46
|
|
10
47
|
Changes:
|
11
48
|
|
12
|
-
*
|
49
|
+
* 2 Major Enhancement
|
13
50
|
|
14
51
|
* Partial rewrite of a project that was once called "Quarry".
|
52
|
+
* Now uese AE for assertions.
|
15
53
|
|
data/MANIFEST
CHANGED
@@ -1,23 +1,18 @@
|
|
1
1
|
#!mast bin demo doc/qedoc lib meta [A-Z]*
|
2
|
-
bin
|
3
2
|
bin/qed
|
4
3
|
bin/qedoc
|
5
|
-
demo
|
6
4
|
demo/01_spec.qed
|
7
|
-
demo/
|
8
|
-
demo/
|
9
|
-
|
5
|
+
demo/data.txt
|
6
|
+
demo/helper.rb
|
7
|
+
demo/table.yml
|
10
8
|
doc/qedoc/index.html
|
11
9
|
doc/qedoc/jquery.js
|
12
|
-
lib
|
13
|
-
lib/qed
|
14
|
-
lib/qed/document
|
10
|
+
lib/qed/command.rb
|
15
11
|
lib/qed/document/jquery.js
|
16
12
|
lib/qed/document/markup.rb
|
17
13
|
lib/qed/document/template.rhtml
|
18
14
|
lib/qed/document.rb
|
19
15
|
lib/qed/extract.rb
|
20
|
-
lib/qed/reporter
|
21
16
|
lib/qed/reporter/base.rb
|
22
17
|
lib/qed/reporter/dotprogress.rb
|
23
18
|
lib/qed/reporter/summary.rb
|
@@ -25,15 +20,15 @@ lib/qed/reporter/verbatim.rb
|
|
25
20
|
lib/qed/runner.rb
|
26
21
|
lib/qed/script.rb
|
27
22
|
lib/qed.rb
|
28
|
-
meta
|
29
23
|
meta/authors
|
30
24
|
meta/created
|
31
25
|
meta/description
|
32
26
|
meta/homepage
|
33
|
-
meta/
|
34
|
-
meta/
|
27
|
+
meta/name
|
28
|
+
meta/repository
|
35
29
|
meta/requires
|
36
30
|
meta/ruby
|
31
|
+
meta/suite
|
37
32
|
meta/summary
|
38
33
|
meta/title
|
39
34
|
meta/version
|
data/README.rdoc
CHANGED
@@ -7,18 +7,25 @@
|
|
7
7
|
|
8
8
|
== Introduction
|
9
9
|
|
10
|
-
Q.E.D.
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
Q.E.D. is an abbreviation for the well known Latin phrase "Quod Erat Demonstrandum",
|
11
|
+
literally "which was to be demonstrated", which is oft written in its abbreviated
|
12
|
+
form at the end of a mathematical proof or philosophical argument to signify the
|
13
|
+
successful completion of a proof.
|
14
|
+
|
15
|
+
And so it for Ruby Q.E.D., which might also be taken to stand for
|
16
|
+
Quality Ensured Documentation.
|
17
|
+
|
18
|
+
Q.E.D. is in fact both a test framwork and a documentation system for Ruby
|
19
|
+
developers. QED sits somehwere between lower-level testing tools like Test::Unit
|
20
|
+
and grand requirement specifications tools like Cucumber. In pratice it works
|
21
|
+
best addressing <i>API-Driven Development</i>, which is especially useful when
|
22
|
+
designing reusable libraries.
|
16
23
|
|
17
24
|
|
18
25
|
== Features
|
19
26
|
|
20
27
|
* Demos can be RDoc, Markdown or any other conforming text format.
|
21
|
-
* Uses excellent Assertive Expressive library for assertion system.
|
28
|
+
* Uses the excellent Assertive Expressive library for assertion system.
|
22
29
|
* Helpers are easily loaded relative to running document.
|
23
30
|
* Table macro allows large sets of data to be run by the same code.
|
24
31
|
* Documentation tool provides nice output with jQuery-based TOC.
|
@@ -28,8 +35,8 @@ is especailly useful when designing reusble libraries.
|
|
28
35
|
|
29
36
|
=== Assertion Syntax
|
30
37
|
|
31
|
-
QED uses AE (Assertive
|
32
|
-
express behaviors. To give a
|
38
|
+
QED uses AE (Assertive Expressive) library to provide an elegant means to
|
39
|
+
express behaviors. To give a quick overview, you can use code such as:
|
33
40
|
|
34
41
|
4.assert == 5
|
35
42
|
|
@@ -55,22 +62,22 @@ For example:
|
|
55
62
|
5.assert == 5
|
56
63
|
|
57
64
|
As you can see, we used RDoc for this document. Almost any text format
|
58
|
-
can be used. The only
|
65
|
+
can be used. The only necessary distinction is that description text
|
59
66
|
align to the left margin and all code be indented. However QED recognizes
|
60
|
-
RDoc and Markdown style headers, so any format that supports
|
61
|
-
(which covers many markup formats in use today) will work a bit
|
62
|
-
While strictly speaking QED does not need to recognize headers,
|
63
|
-
improve console output.
|
67
|
+
RDoc and Markdown single-line style headers, so any format that supports
|
68
|
+
this style (which covers many markup formats in use today) will work a bit
|
69
|
+
better. While strictly speaking QED does not need to recognize headers,
|
70
|
+
it does improve console output.
|
64
71
|
|
65
72
|
Give this design some thought. It should become clear that this approach is
|
66
73
|
especially fruitful in that it allows *documentation* and *specification*
|
67
|
-
to
|
74
|
+
to seamlessly merge into a unified *demonstration*.
|
68
75
|
|
69
76
|
=== Running Demonstrations
|
70
77
|
|
71
78
|
If we were to run the above document through QED in verbatim mode the output
|
72
79
|
would be identical (assuming we did not make a typo and the assertions passed).
|
73
|
-
If there were errors or failures, we would see information
|
80
|
+
If there were errors or failures, we would see information detailing each.
|
74
81
|
|
75
82
|
To run a document through QED, simply use the +qed+ command.
|
76
83
|
|
@@ -79,21 +86,21 @@ To run a document through QED, simply use the +qed+ command.
|
|
79
86
|
The <tt>-v</tt> option specifies verbatim mode, which outputs the entire
|
80
87
|
document.
|
81
88
|
|
82
|
-
Notice we placed the QED document in the demo directory, this is
|
83
|
-
|
84
|
-
|
85
|
-
of the name. While this is not necessary, it helps order
|
86
|
-
properly with generating QED documentation (QEDocs).
|
89
|
+
Notice we placed the QED document in the <tt>demo</tt> directory, this is
|
90
|
+
one of two conical place that has been designated for them (the other is test/demos),
|
91
|
+
though you can put them elsewhere in your project if you prefer. Also notice the
|
92
|
+
<tt>01_</tt> in front of the name. While this is not necessary, it helps order
|
93
|
+
the documents properly with generating QED documentation (QEDocs).
|
87
94
|
|
88
95
|
To generate documentation from QED documents, use the +qedoc+ command.
|
89
96
|
|
90
|
-
$
|
97
|
+
$ qedoc --output doc/qedoc --title "Example" demo/*.rdoc
|
91
98
|
|
92
99
|
When documenting QED recognizes the format by the file extension and
|
93
100
|
treats it accordingly. An extension of <tt>.qed</tt> is treated the same
|
94
101
|
as <tt>.rdoc</tt>.
|
95
102
|
|
96
|
-
Use the <tt>--help</tt> options on each command to get more
|
103
|
+
Use the <tt>--help</tt> options on each command to get more information on
|
97
104
|
the use of these commands.
|
98
105
|
|
99
106
|
|
data/bin/qed
CHANGED
@@ -1,150 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'qed'
|
4
|
-
require 'getoptlong'
|
5
|
-
|
6
|
-
module QED
|
7
|
-
|
8
|
-
# = QED Commandline Tool
|
9
|
-
#
|
10
|
-
class Command
|
11
|
-
def self.execute
|
12
|
-
new.execute
|
13
|
-
end
|
14
|
-
|
15
|
-
attr :reporter
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
@reporter = nil
|
19
|
-
end
|
20
|
-
|
21
|
-
def opts
|
22
|
-
@opts ||= GetoptLong.new(
|
23
|
-
[ '--version', GetoptLong::NO_ARGUMENT ],
|
24
|
-
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
25
|
-
[ '--debug', '-D', GetoptLong::NO_ARGUMENT ],
|
26
|
-
[ '--verbose', '-V', GetoptLong::NO_ARGUMENT ],
|
27
|
-
[ '--verbatim', '-v', GetoptLong::NO_ARGUMENT ],
|
28
|
-
[ '--summary', '-s', GetoptLong::NO_ARGUMENT ],
|
29
|
-
[ '--script', GetoptLong::NO_ARGUMENT ],
|
30
|
-
[ '--loadpath', '-I', GetoptLong::REQUIRED_ARGUMENT ]
|
31
|
-
)
|
32
|
-
end
|
33
|
-
|
34
|
-
#
|
35
|
-
def parse_options
|
36
|
-
opts.each do |opt, arg|
|
37
|
-
case opt
|
38
|
-
when '--help'
|
39
|
-
puts HELP
|
40
|
-
exit
|
41
|
-
when '--debug'
|
42
|
-
$RESPECT_DEBUG = true
|
43
|
-
when '--verbose'
|
44
|
-
$VERBOSE = true
|
45
|
-
when '--verbatim'
|
46
|
-
@reporter = :verbatim
|
47
|
-
when '--summary'
|
48
|
-
@reporter = :summary
|
49
|
-
when '--script'
|
50
|
-
@reporter = :script # psuedo-reporter
|
51
|
-
when '--loadpath'
|
52
|
-
libs = arg.split(/[:;]/).map{ |dir| File.expand_path(dir) }
|
53
|
-
libs.each{|dir| $LOAD_PATH.unshift(dir)}
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
#
|
59
|
-
#def load_rc
|
60
|
-
# if rcfile = Dir['.config/qed{,rc}{,.rb}'].first
|
61
|
-
# load(rcfile)
|
62
|
-
# end
|
63
|
-
#end
|
64
|
-
|
65
|
-
# TODO: Better way to load helpers?
|
66
|
-
#
|
67
|
-
#def load_helpers
|
68
|
-
# dirs = spec_files.map{ |file| File.join(Dir.pwd, File.dirname(file)) }
|
69
|
-
# dirs = dirs.select{ |dir| File.directory?(dir) }
|
70
|
-
# dirs.each do |dir|
|
71
|
-
# while dir != '/' do
|
72
|
-
# helper = File.join(dir, 'qed_helper.rb')
|
73
|
-
# load(helper) if File.exist?(helper)
|
74
|
-
# break if Dir.pwd == dir
|
75
|
-
# dir = File.dirname(dir)
|
76
|
-
# end
|
77
|
-
# end
|
78
|
-
#end
|
79
|
-
|
80
|
-
#
|
81
|
-
def specs
|
82
|
-
spec_files
|
83
|
-
end
|
84
|
-
|
85
|
-
#
|
86
|
-
def spec_files
|
87
|
-
files = ARGV.map do |pattern|
|
88
|
-
Dir[pattern]
|
89
|
-
end.flatten.uniq
|
90
|
-
|
91
|
-
files = files.map do |file|
|
92
|
-
File.directory?(file) ? Dir[File.join(file,'**','*')] : file
|
93
|
-
end.flatten.uniq
|
94
|
-
|
95
|
-
files = files.reject do |file|
|
96
|
-
%w{.yml .yaml .rb}.include?(File.extname(file))
|
97
|
-
end
|
98
|
-
|
99
|
-
files
|
100
|
-
end
|
101
|
-
|
102
|
-
#
|
103
|
-
def output
|
104
|
-
case reporter
|
105
|
-
when :verbatim
|
106
|
-
Reporter::Verbatim.new
|
107
|
-
when :summary
|
108
|
-
Reporter::Summary.new
|
109
|
-
else
|
110
|
-
nil
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
#
|
115
|
-
def runner
|
116
|
-
Runner.new(specs, output)
|
117
|
-
end
|
118
|
-
|
119
|
-
#
|
120
|
-
def execute
|
121
|
-
parse_options
|
122
|
-
#load_rc
|
123
|
-
#load_helpers
|
124
|
-
case reporter
|
125
|
-
when :script
|
126
|
-
specs.each do |spec|
|
127
|
-
puts spec.to_script
|
128
|
-
end
|
129
|
-
else
|
130
|
-
runner.check
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
HELP = <<-END
|
135
|
-
qed [--options] [spec/tests...]
|
136
|
-
|
137
|
-
Options:
|
138
|
-
-v --verbatim use verbatim reporter
|
139
|
-
-s --summary use summary reporter
|
140
|
-
-V --verbose extra verbose output
|
141
|
-
-D --debug spec/tests will exit on error
|
142
|
-
-h --help show this help information
|
143
|
-
--version show quarry version
|
144
|
-
END
|
145
|
-
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
2
|
+
require 'qed/command'
|
149
3
|
QED::Command.execute
|
150
4
|
|
data/demo/01_spec.qed
CHANGED
@@ -12,21 +12,20 @@ a failure or error occur then the code gets a "pass".
|
|
12
12
|
|
13
13
|
For example, the following passes:
|
14
14
|
|
15
|
-
|
15
|
+
(2 + 2).assert == 4
|
16
16
|
|
17
17
|
While the following would "fail", as indicated by the raising of
|
18
18
|
an Assertion error:
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
expect Assertion do
|
21
|
+
(2 + 2).assert == 5
|
22
|
+
end
|
23
23
|
|
24
24
|
And this would have raised a NameError:
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
expect NameError do
|
27
|
+
nobody_knows_method
|
28
|
+
end
|
30
29
|
|
31
30
|
= Neutral Code
|
32
31
|
|
@@ -34,34 +33,32 @@ There is no means of specifying that a code clause is neutral code,
|
|
34
33
|
i.e. that it should be executed but not tested. Thus far, such a
|
35
34
|
feature has proven to be a YAGNI.
|
36
35
|
|
37
|
-
|
38
36
|
= Defining Custom Assertions
|
39
37
|
|
40
38
|
The context in which the QED code is run is a self-extended module, thus
|
41
39
|
reusable macros can be created simply by defining a method.
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
def assert_integer(x)
|
42
|
+
x.assert.is_a? Integer
|
43
|
+
end
|
46
44
|
|
47
45
|
Now lets try out our new macro definition.
|
48
46
|
|
49
|
-
|
47
|
+
assert_integer(4)
|
50
48
|
|
51
49
|
Let's prove that it can also fail:
|
52
50
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
expect Assertion do
|
52
|
+
assert_integer("IV")
|
53
|
+
end
|
57
54
|
|
58
55
|
= Helper File
|
59
56
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
Helpers can be defined at the bottom of any QED document by placing the code
|
58
|
+
after a triple-dash divider (ie. "---"). You can use that to load optional
|
59
|
+
AE features, or define your own specialized assertion methods. Helpers
|
60
|
+
can be defined in a separate files using +require+ or +load+ in the bottom
|
61
|
+
section to import them. The bottom section is run first, before any the steps.
|
65
62
|
|
66
63
|
= Before and After Clauses
|
67
64
|
|
@@ -73,30 +70,30 @@ subsequent step.
|
|
73
70
|
We use a *before* clause if we want to setup some code at the
|
74
71
|
start of each step.
|
75
72
|
|
76
|
-
|
73
|
+
a, z = nil, nil
|
77
74
|
|
78
|
-
|
79
|
-
|
80
|
-
|
75
|
+
Before do
|
76
|
+
a = "BEFORE"
|
77
|
+
end
|
81
78
|
|
82
|
-
And an *after* clause to
|
79
|
+
And an *after* clause to teardown objects after a step.
|
83
80
|
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
After do
|
82
|
+
z = "AFTER"
|
83
|
+
end
|
87
84
|
|
88
85
|
Notice we assigned +a+ and +z+ before the block. This was to ensure
|
89
|
-
their visibility in the scope later. Now, lets verify
|
90
|
-
and *after*
|
86
|
+
their visibility in the scope later. Now, lets verify that the *before*
|
87
|
+
and *after* clauses work.
|
91
88
|
|
92
|
-
|
89
|
+
a.assert == "BEFORE"
|
93
90
|
|
94
|
-
|
95
|
-
|
91
|
+
a = "A"
|
92
|
+
z = "Z"
|
96
93
|
|
97
94
|
And now.
|
98
95
|
|
99
|
-
|
96
|
+
z.assert == "AFTER"
|
100
97
|
|
101
98
|
There can only be one before or after clause at a time. So if we
|
102
99
|
define a new *before* or *after* clause later in the document,
|
@@ -104,43 +101,75 @@ it will replace the current clause(s) in use.
|
|
104
101
|
|
105
102
|
As a demonstration of this:
|
106
103
|
|
107
|
-
|
108
|
-
|
109
|
-
|
104
|
+
Before do
|
105
|
+
a = "BEFORE AGAIN"
|
106
|
+
end
|
110
107
|
|
111
108
|
We will see it is the case.
|
112
109
|
|
113
|
-
|
110
|
+
a.assert == "BEFORE AGAIN"
|
114
111
|
|
115
112
|
Only use *before* and *after* clauses when necessary --specifications
|
116
113
|
are generally more readable without them. Indeed, some developers
|
117
114
|
make a policy of avoiding them altogether. YMMV.
|
118
115
|
|
116
|
+
= External Data
|
117
|
+
|
118
|
+
When creating testable demonstrations, there are times when sizable
|
119
|
+
chunks of data are needed. It is convenient to store such data in
|
120
|
+
a separate file. The +Data+ method makes is easy to load such files.
|
121
|
+
|
122
|
+
Data('data.txt').assert =~ /dolor/
|
123
|
+
|
124
|
+
All files are looked for relative to the location of current document.
|
119
125
|
|
120
126
|
= Tabular Steps
|
121
127
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
for relative to the location of the document. If no name is given the
|
126
|
-
'<doc-name>.yaml' is assumed.
|
128
|
+
The +Table+ method is similar to the +Data+ method except that it
|
129
|
+
expects a YAML file, and it can take a block to iterate the data over.
|
130
|
+
This makes it easy to test tables of examples.
|
127
131
|
|
128
132
|
The arity of the table block determines the number of columns each row
|
129
133
|
in the table should have. Each row is assigned in turn and run
|
130
134
|
through the coded step. Consider the following example:
|
131
135
|
|
132
|
-
Every row in
|
133
|
-
and run through the
|
136
|
+
Every row in the {table.yml table}[table.yml] will be assigned to
|
137
|
+
the block parameters and run through the subsequent assertion.
|
138
|
+
|
139
|
+
Table 'table.yml' do |x, y|
|
140
|
+
x.upcase.assert == y
|
141
|
+
end
|
134
142
|
|
135
|
-
|
136
|
-
|
137
|
-
|
143
|
+
= Comment Triggers
|
144
|
+
|
145
|
+
QED also supports comment match triggers. With the +When+ method one can
|
146
|
+
define setup and teardown procedures by matching against comment text.
|
147
|
+
For example:
|
148
|
+
|
149
|
+
When 'given a setting @a equal to (((\d+)))' do |n|
|
150
|
+
@a = n.to_i
|
151
|
+
end
|
152
|
+
|
153
|
+
Now, @a will be set to 1 whenever a comment like this one contains,
|
154
|
+
"given a setting @a equal to 1".
|
155
|
+
|
156
|
+
@a.assert == 1
|
157
|
+
|
158
|
+
A string pattern is translated into a regular expression. In fact, you can
|
159
|
+
use a regular expression if you need more control over the match. When
|
160
|
+
using a string all spaces are converted to <tt>\s+</tt> and anything within
|
161
|
+
double-parenthesis is treated as raw regular expression. Since the above
|
162
|
+
example has (((\d+))), the actual regular expression contains <tt>(\d+)</tt>,
|
163
|
+
so any number can be used. For example, "given a setting @a equal to 2".
|
164
|
+
|
165
|
+
@a.assert == 2
|
166
|
+
|
167
|
+
Typically you will want to put triggers is helper files, rather then
|
168
|
+
place them directly in the demonstration document.
|
138
169
|
|
139
170
|
This concludes the basic overview of QED's specification system, which
|
140
171
|
is itself a QED document. Yes, we eat our own dog food.
|
141
172
|
|
142
|
-
Q.E.D.
|
143
|
-
|
144
173
|
---
|
145
|
-
require '
|
174
|
+
require 'helper'
|
146
175
|
|