qed 1.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/Syckfile
DELETED
@@ -1,70 +0,0 @@
|
|
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
DELETED
@@ -1,175 +0,0 @@
|
|
1
|
-
= Standard Sections
|
2
|
-
|
3
|
-
QED demos are light-weight specification documents, highly suitable
|
4
|
-
to interface-driven design. The documents are divided up into
|
5
|
-
clauses separated by blank lines. Clauses that are flush to the
|
6
|
-
left margin are always explanation or comment clauses. Indented
|
7
|
-
clauses are always executable code.
|
8
|
-
|
9
|
-
Each code section is executed in order of appearance, within a
|
10
|
-
rescue wrapper that captures any failures or errors. If neither
|
11
|
-
a failure or error occur then the code gets a "pass".
|
12
|
-
|
13
|
-
For example, the following passes:
|
14
|
-
|
15
|
-
(2 + 2).assert == 4
|
16
|
-
|
17
|
-
While the following would "fail", as indicated by the raising of
|
18
|
-
an Assertion error:
|
19
|
-
|
20
|
-
expect Assertion do
|
21
|
-
(2 + 2).assert == 5
|
22
|
-
end
|
23
|
-
|
24
|
-
And this would have raised a NameError:
|
25
|
-
|
26
|
-
expect NameError do
|
27
|
-
nobody_knows_method
|
28
|
-
end
|
29
|
-
|
30
|
-
= Neutral Code
|
31
|
-
|
32
|
-
There is no means of specifying that a code clause is neutral code,
|
33
|
-
i.e. that it should be executed but not tested. Thus far, such a
|
34
|
-
feature has proven to be a YAGNI.
|
35
|
-
|
36
|
-
= Defining Custom Assertions
|
37
|
-
|
38
|
-
The context in which the QED code is run is a self-extended module, thus
|
39
|
-
reusable macros can be created simply by defining a method.
|
40
|
-
|
41
|
-
def assert_integer(x)
|
42
|
-
x.assert.is_a? Integer
|
43
|
-
end
|
44
|
-
|
45
|
-
Now lets try out our new macro definition.
|
46
|
-
|
47
|
-
assert_integer(4)
|
48
|
-
|
49
|
-
Let's prove that it can also fail:
|
50
|
-
|
51
|
-
expect Assertion do
|
52
|
-
assert_integer("IV")
|
53
|
-
end
|
54
|
-
|
55
|
-
= Helper File
|
56
|
-
|
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.
|
62
|
-
|
63
|
-
= Before and After Clauses
|
64
|
-
|
65
|
-
QED supports *before* and *after* clauses in a specification
|
66
|
-
through the use of before and after code blocks. Before and after
|
67
|
-
clauses are executed at the beginning and at the end of each
|
68
|
-
subsequent step.
|
69
|
-
|
70
|
-
We use a *before* clause if we want to setup some code at the
|
71
|
-
start of each step.
|
72
|
-
|
73
|
-
a, z = nil, nil
|
74
|
-
|
75
|
-
Before do
|
76
|
-
a = "BEFORE"
|
77
|
-
end
|
78
|
-
|
79
|
-
And an *after* clause to teardown objects after a step.
|
80
|
-
|
81
|
-
After do
|
82
|
-
z = "AFTER"
|
83
|
-
end
|
84
|
-
|
85
|
-
Notice we assigned +a+ and +z+ before the block. This was to ensure
|
86
|
-
their visibility in the scope later. Now, lets verify that the *before*
|
87
|
-
and *after* clauses work.
|
88
|
-
|
89
|
-
a.assert == "BEFORE"
|
90
|
-
|
91
|
-
a = "A"
|
92
|
-
z = "Z"
|
93
|
-
|
94
|
-
And now.
|
95
|
-
|
96
|
-
z.assert == "AFTER"
|
97
|
-
|
98
|
-
There can only be one before or after clause at a time. So if we
|
99
|
-
define a new *before* or *after* clause later in the document,
|
100
|
-
it will replace the current clause(s) in use.
|
101
|
-
|
102
|
-
As a demonstration of this:
|
103
|
-
|
104
|
-
Before do
|
105
|
-
a = "BEFORE AGAIN"
|
106
|
-
end
|
107
|
-
|
108
|
-
We will see it is the case.
|
109
|
-
|
110
|
-
a.assert == "BEFORE AGAIN"
|
111
|
-
|
112
|
-
Only use *before* and *after* clauses when necessary --specifications
|
113
|
-
are generally more readable without them. Indeed, some developers
|
114
|
-
make a policy of avoiding them altogether. YMMV.
|
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 found relative to the location of current document.
|
125
|
-
|
126
|
-
= Tabular Steps
|
127
|
-
|
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.
|
131
|
-
|
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
|
-
|
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
|
142
|
-
|
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.
|
169
|
-
|
170
|
-
This concludes the basic overview of QED's specification system, which
|
171
|
-
is itself a QED document. Yes, we eat our own dog food.
|
172
|
-
|
173
|
-
---
|
174
|
-
1[helper.rb] Helper
|
175
|
-
|
data/demo/02_err.qed
DELETED
@@ -1,18 +0,0 @@
|
|
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/data.txt
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
data/demo/helpers/sample.rb
DELETED
data/demo/table.yml
DELETED
data/lib/qed/extract.rb
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
|
-
raise "not ready yet"
|
4
|
-
|
5
|
-
module QED
|
6
|
-
|
7
|
-
# Extractor is a tool for extracting code from embedded
|
8
|
-
# comment blocks.
|
9
|
-
#
|
10
|
-
# TODO:
|
11
|
-
# - Should extract_block handle more than the first matching block?
|
12
|
-
# - How can we handle embedded code in standard comments? Eg. #
|
13
|
-
#
|
14
|
-
module Extract
|
15
|
-
|
16
|
-
extend self
|
17
|
-
|
18
|
-
# Extract unit tests. This task scans every package script
|
19
|
-
# looking for sections of the form:
|
20
|
-
#
|
21
|
-
# =begin test
|
22
|
-
# ...
|
23
|
-
# =end
|
24
|
-
#
|
25
|
-
# With appropriate headers, it copies these sections to files
|
26
|
-
# in your project's test/ dir, which then can be run using the
|
27
|
-
# Ratchet test task. The exact directory layout of the files to
|
28
|
-
# be tested is reflected in the test directory. You can then
|
29
|
-
# use project.rb's test task to run the tests.
|
30
|
-
#
|
31
|
-
# files Files to extract ['lib/**/*.rb']
|
32
|
-
# output Test directory ['test/']
|
33
|
-
#
|
34
|
-
|
35
|
-
def test_extract(files=nil)
|
36
|
-
output = 'test/embedded' # Don't think output should be setable.
|
37
|
-
|
38
|
-
files = files || 'lib/**/*.rb'
|
39
|
-
files = 'lib/**/*.rb' if TrueClass == files
|
40
|
-
files = [files].flatten.compact
|
41
|
-
|
42
|
-
filelist = files.collect{ |f| Dir.glob(f) }
|
43
|
-
filelist.flatten!
|
44
|
-
if filelist.empty?
|
45
|
-
puts "No scripts found from which to extract tests."
|
46
|
-
return
|
47
|
-
end
|
48
|
-
|
49
|
-
FileUtils.mkdir_p(output) unless File.directory?(output)
|
50
|
-
|
51
|
-
#vrunner = VerbosityRunner.new("Extracting", verbosity?)
|
52
|
-
#vrunner.setup(filelist.size)
|
53
|
-
|
54
|
-
filelist.each do |file|
|
55
|
-
#vrunner.prepare(file)
|
56
|
-
|
57
|
-
testing = extract_test_from_file( file )
|
58
|
-
if testing.strip.empty?
|
59
|
-
status = "[NONE]"
|
60
|
-
else
|
61
|
-
complete_test = create_test(testing, file)
|
62
|
-
libpath = File.dirname(file)
|
63
|
-
testfile = "test_" + File.basename(file)
|
64
|
-
fp = File.join(output, libpath, testfile)
|
65
|
-
unless File.directory?( File.dirname(fp))
|
66
|
-
FileUtils.mkdir_p(File.dirname(fp))
|
67
|
-
end
|
68
|
-
File.open(fp, "w"){ |fw| fw << complete_test }
|
69
|
-
status = "[TEST]"
|
70
|
-
end
|
71
|
-
|
72
|
-
#vrunner.complete(file, status)
|
73
|
-
end
|
74
|
-
|
75
|
-
#vrunner.finish(
|
76
|
-
# :normal => "#{filelist.size} files had tests extracted.",
|
77
|
-
# :check => false
|
78
|
-
#)
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
# Extract test from a file's testing comments.
|
84
|
-
|
85
|
-
def extract_test_from_file(file)
|
86
|
-
return nil if ! File.file?(file)
|
87
|
-
tests = ""; inside = false
|
88
|
-
fstr = File.read(file)
|
89
|
-
fstr.split(/\n/).each do |l|
|
90
|
-
if l =~ /^=begin[ ]*test/i
|
91
|
-
tests << "\n"
|
92
|
-
inside = true
|
93
|
-
next
|
94
|
-
elsif inside and l =~ /^=[ ]*end/
|
95
|
-
inside = false
|
96
|
-
next
|
97
|
-
end
|
98
|
-
if inside
|
99
|
-
tests << l << "\n"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
tests
|
103
|
-
end
|
104
|
-
|
105
|
-
# Generate the test.
|
106
|
-
|
107
|
-
def create_test(testing, file)
|
108
|
-
fp = file.split(/[\/]/)
|
109
|
-
if fp[0] == 'lib'
|
110
|
-
reqf = "require '#{fp[1..-1].join('/')}'"
|
111
|
-
else
|
112
|
-
reqf = ''
|
113
|
-
end
|
114
|
-
teststr = []
|
115
|
-
teststr << "# _____ _"
|
116
|
-
teststr << "# |_ _|__ ___| |_"
|
117
|
-
teststr << "# | |/ _ \\/ __| __|"
|
118
|
-
teststr << "# | | __/\\__ \\ |_"
|
119
|
-
teststr << "# |_|\\___||___/\\__|"
|
120
|
-
teststr << "#"
|
121
|
-
teststr << "# for #{file}"
|
122
|
-
teststr << "#"
|
123
|
-
teststr << "# Extracted #{Time.now}"
|
124
|
-
teststr << "# Project.rb Test Extraction"
|
125
|
-
teststr << "#"
|
126
|
-
teststr << ""
|
127
|
-
teststr << "#{reqf}"
|
128
|
-
teststr << ""
|
129
|
-
teststr << testing
|
130
|
-
teststr << ""
|
131
|
-
teststr.join("\n")
|
132
|
-
end
|
133
|
-
|
134
|
-
end #module Extract
|
135
|
-
|
136
|
-
end #module Quarry
|
137
|
-
|
data/lib/qed/reporter/ditto.rb
DELETED
@@ -1,72 +0,0 @@
|
|
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
|
-
|