qed 2.1.1 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +622 -344
- data/DIARY.rdoc +117 -0
- data/HISTORY +36 -0
- data/PROFILE +16 -0
- data/README.rdoc +69 -36
- data/REQUIRE +9 -0
- data/ROADMAP +12 -0
- data/VERSION +5 -0
- data/demo/01_demos.rdoc +56 -0
- data/demo/02_advice.rdoc +158 -0
- data/demo/03_helpers.rdoc +42 -0
- data/demo/04_fixtures.rdoc +29 -0
- data/demo/05_quote.rdoc +24 -0
- data/demo/07_toplevel.rdoc +42 -0
- data/demo/08_cross_script.rdoc +27 -0
- data/demo/09_cross_script.rdoc +27 -0
- data/demo/10_constant_lookup.rdoc +16 -0
- data/demo/applique/constant.rb +2 -0
- data/demo/applique/env.rb +5 -0
- data/demo/applique/fileutils.rb +1 -0
- data/demo/applique/markup.rb +10 -0
- data/demo/applique/quote.rb +4 -0
- data/demo/applique/toplevel.rb +15 -0
- data/demo/fixtures/data.txt +1 -0
- data/demo/fixtures/table.yml +5 -0
- data/demo/helpers/advice.rb +40 -0
- data/demo/helpers/sample.rb +4 -0
- data/demo/helpers/toplevel.rb +6 -0
- data/eg/hello_world.rdoc +15 -0
- data/{demo/error.rdoc → eg/view_error.rdoc} +0 -0
- data/{demo → eg}/website.rdoc +0 -0
- data/lib/qed.rb +20 -1
- data/lib/qed/advice.rb +4 -30
- data/lib/qed/advice/events.rb +6 -3
- data/lib/qed/advice/patterns.rb +37 -19
- data/lib/qed/applique.rb +85 -0
- data/lib/qed/command.rb +3 -5
- data/lib/qed/evaluator.rb +52 -56
- data/lib/qed/package.yml +5 -0
- data/lib/qed/parser.rb +149 -0
- data/lib/qed/profile.yml +16 -0
- data/lib/qed/reporter/{base.rb → abstract.rb} +17 -19
- data/lib/qed/reporter/bullet.rb +14 -16
- data/lib/qed/reporter/dotprogress.rb +7 -6
- data/lib/qed/reporter/html.rb +21 -3
- data/lib/qed/reporter/verbatim.rb +28 -26
- data/lib/qed/scope.rb +98 -82
- data/lib/qed/script.rb +21 -69
- data/lib/qed/session.rb +44 -3
- data/script/qedoc +2 -0
- data/script/test +2 -0
- metadata +74 -28
- data/doc/qedoc/index.html +0 -515
- data/doc/qedoc/jquery.js +0 -19
- data/meta/authors +0 -1
- data/meta/created +0 -1
- data/meta/description +0 -2
- data/meta/homepage +0 -1
- data/meta/name +0 -1
- data/meta/released +0 -1
- data/meta/repository +0 -1
- data/meta/requires +0 -5
- data/meta/ruby +0 -2
- data/meta/suite +0 -1
- data/meta/summary +0 -1
- data/meta/title +0 -1
- data/meta/version +0 -1
data/DIARY.rdoc
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
= Diary
|
2
|
+
|
3
|
+
== 2010-06-06 / HTML Won't Do
|
4
|
+
|
5
|
+
There have proven to be significant issues associated with translating markup to HTML and having QED evalute the HTML, rather than plain text. To begin with different markup engines translate special characeters in differnt ways. RDoc for instance will translate astrisks around a word into 'b' tags, whereas Textile translates them to 'em' tags. Still other characters are translated into HTML escape codes, eg. <code>\&#8216;</code>. There are a variety of these and each markup language will translate them according to it's own rules (or not at all). This means pattern matches in advice have to take these translations into account. Instead of matching on an asterisk we might need to match on +<b>+. A minor naggle perhaps, but it means being exceptionally aware of all translaterions that occur, and moreover, that applique may not be portable across markup languages.
|
6
|
+
|
7
|
+
There are other discrepencies as well such as the translation of code blocks to \<pre> vs. \<pre>\<code> tags, but all this aside, while perhaps annoying, it can be managed. A normalization procedure can help mitage the issues. However, the ultimate problem is your classic YAGNI, the fact that little, if anything, is gained by using HTML as the defacto document format. And this is simply because everyone will write there documents in a text-based markup, none of which fully support the HTML that QED could utilize. For instance RDoc and Markdown do not have a notation for tables (although extended Markdown might). Textile does not have a clean notation for \<pre> blocks --you have to use \<pre>! And ASCIIDoc, while a very capable documentation system has a verbose syntax that is not particullary suited to reading in plain text. Perhaps if all the available markdown languages were equally as capable, it would be worth the additional effort. But lacking this I beleive more advantage can ultimately be gained by allowing QED to have it's own markup syntax one suited best to it's purpose.
|
8
|
+
|
9
|
+
|
10
|
+
== 2010-02-03 / Some Determinations
|
11
|
+
|
12
|
+
In the end I have decided on loading helpers on the fly via
|
13
|
+
special AHREF links. We still need a plan for loading global
|
14
|
+
helpers though.
|
15
|
+
|
16
|
+
Also, per last entry, Before and After stays b/c When doesn't
|
17
|
+
quite cover the usecase. However, I definately encourge the use
|
18
|
+
of helper methods in place of Before and After clauses.
|
19
|
+
|
20
|
+
|
21
|
+
== 2010-01-28 / Before and After
|
22
|
+
|
23
|
+
Wouldn't it better to allow helpers to define methods, which
|
24
|
+
can be called in the steps for setting things up, rather than
|
25
|
+
using "magic" Before and After clauses which give no indication
|
26
|
+
that something has happened?
|
27
|
+
|
28
|
+
= Examples
|
29
|
+
|
30
|
+
== Example #1
|
31
|
+
|
32
|
+
For example #1 we will use example1[helper/example1] support file.
|
33
|
+
First we need to prepare the example. It is a complex process, so we
|
34
|
+
have made a special method for it. See the helper[helper/example1]
|
35
|
+
file for details.
|
36
|
+
|
37
|
+
ex = prepare_example1
|
38
|
+
|
39
|
+
Now we can show that the example is hip.
|
40
|
+
|
41
|
+
ex.assert.hip == true
|
42
|
+
|
43
|
+
So we could get rid of Before(:step) and After(:step) definitions this
|
44
|
+
way, and it's not such a big loss, b/c we still have #When, and
|
45
|
+
After(:Step) is of very rare utility which can be worked around.
|
46
|
+
|
47
|
+
|
48
|
+
== 2010-01-30 / The Best Way to Handle Helpers
|
49
|
+
|
50
|
+
1) Should helpers be stored in a special location relative
|
51
|
+
to the demo file, from which all helpers in that location
|
52
|
+
are loaded automatically. This simplifies loading, but it
|
53
|
+
makes support for per-demo helpers more awkward.
|
54
|
+
This option also means taking special consideration for
|
55
|
+
helpers when documenting --any reference to them will have
|
56
|
+
to be tacked-on rather then be an integral part of the document
|
57
|
+
itself.
|
58
|
+
|
59
|
+
We might do something like this:
|
60
|
+
|
61
|
+
demos/
|
62
|
+
demo1.rdoc
|
63
|
+
demo1/
|
64
|
+
helper.rb
|
65
|
+
demo2.rdoc
|
66
|
+
demo2/
|
67
|
+
helper.rb
|
68
|
+
share/
|
69
|
+
helper.rb
|
70
|
+
|
71
|
+
Such that demo1/helper.rb only applies to demo1.rdoc, and
|
72
|
+
likewise for demo2, but both use share/helper.rb.
|
73
|
+
|
74
|
+
2) Or, should the demo be able to specify which helpers to
|
75
|
+
load via href links. This allows full flexability it selecting
|
76
|
+
behavior for the demo. It also means the documentation will
|
77
|
+
have references to helpers built-in (although they will have
|
78
|
+
to be augmented when documenting to ensure the hrefs link
|
79
|
+
correctly). But session-oriented advice doesn't make much
|
80
|
+
sense in a per-demo context. We could ignore that, or place
|
81
|
+
session advice in a separate location. While this option
|
82
|
+
is more flexible, it also means demos may be more difficult
|
83
|
+
to follow, because one must scan the links in the document
|
84
|
+
to determine which helpers are being used.
|
85
|
+
|
86
|
+
An example demo might look like:
|
87
|
+
|
88
|
+
== Examples
|
89
|
+
|
90
|
+
== Example 1
|
91
|
+
|
92
|
+
For example #1 we will use example1[helper/example1] support file.
|
93
|
+
|
94
|
+
... and so on ...
|
95
|
+
|
96
|
+
== Example 2
|
97
|
+
|
98
|
+
For example #2 we will use example2[helper/example2] support file.
|
99
|
+
|
100
|
+
... and so on ...
|
101
|
+
|
102
|
+
In which case it seems prudent to load these helpers as they are
|
103
|
+
evaluated, rather than all at once at the start. However this insinuates
|
104
|
+
that there is only one before and after advice at a time, and when
|
105
|
+
would before advice for the entire demo run, upon loading the helper?
|
106
|
+
|
107
|
+
I think it would be better to use When clauses. Then the helpers could
|
108
|
+
be loaded all at once at the start and it would not matter. And instead of
|
109
|
+
<code>Before do</code> use <code>When /*/ do</code> for general before
|
110
|
+
clauses.
|
111
|
+
|
112
|
+
However, if referenced helpers are to be loaded all at once at the start,
|
113
|
+
it seems almost silly to even allow helpers to be referenced in the
|
114
|
+
document. With the exception of using them as footnotes, it conveys too
|
115
|
+
much positional indication. So either load them when they are encountered,
|
116
|
+
or use option #1.
|
117
|
+
|
data/HISTORY
CHANGED
@@ -1,5 +1,41 @@
|
|
1
1
|
= RELEASE HISTORY
|
2
2
|
|
3
|
+
== 2.2.0 / 2010-06-20
|
4
|
+
|
5
|
+
This release returns to a text-based evaluator, rather
|
6
|
+
then use HTML. Processing HTML proved to have too many
|
7
|
+
edge cases to be effective --both in implementation
|
8
|
+
and in end-usage. So to remedy the situation QED has
|
9
|
+
return to supportting simple markup formats such as
|
10
|
+
RDoc and Markup.
|
11
|
+
|
12
|
+
This release also adds multi-pattern advice. Instead of
|
13
|
+
a single pattern, multiple patterns can be matched
|
14
|
+
sequentially. This make it a easier to match large text
|
15
|
+
descriptions without restoring to regular expressions.
|
16
|
+
|
17
|
+
In addition QED now supports raw text blocks. By ending
|
18
|
+
a description section in ellipsis (...), the subsequent
|
19
|
+
code setion becomes a plain text section and is passed
|
20
|
+
into the argument list of any matching When advice. This
|
21
|
+
makes it easy to scaffold fixture files, for example.
|
22
|
+
|
23
|
+
Finally, this release also refines the evaluation scopes.
|
24
|
+
Where before, a new binding was being created, each was
|
25
|
+
attached to the TOPLEVEL, and therefore not truly isolated
|
26
|
+
on a per-dcoument basis. To correct, QED now mocks the
|
27
|
+
TOPLEVEL providing a new instance of this mock object for
|
28
|
+
each document.
|
29
|
+
|
30
|
+
Changes:
|
31
|
+
|
32
|
+
* No longer uses HTML for document processing.
|
33
|
+
* Support for plain text blocks using ellipsis.
|
34
|
+
* New sequential multi-pattern matches.
|
35
|
+
* Mock TOPLEVEL at both the demo and applique levels.
|
36
|
+
* Adjust color support for latest ANSI release.
|
37
|
+
|
38
|
+
|
3
39
|
== 2.1.1 / 2010-04-08
|
4
40
|
|
5
41
|
Fixed bug introduced in the last version that executed all
|
data/PROFILE
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
title: QED
|
3
|
+
suite: proutils
|
4
|
+
summary: Quod Erat Demonstrandum
|
5
|
+
authors: Thomas Sawyer <transfire@gmail.com>
|
6
|
+
created: 2006-12-16
|
7
|
+
|
8
|
+
description:
|
9
|
+
QED (Quality Ensured Demonstrations) is a TDD/BDD framework
|
10
|
+
utilizing Literate Programming techniques.
|
11
|
+
|
12
|
+
resources:
|
13
|
+
home: http://proutils.github.com/qed
|
14
|
+
work: http://github.com/protuils/qed
|
15
|
+
repo: git://github.com/proutils/qed.git
|
16
|
+
|
data/README.rdoc
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
= Ruby Q.E.D.
|
2
2
|
|
3
3
|
homepage: http://proutils.rubyforge.org/qed
|
4
|
-
mailing list: http://groups.google.com/group/
|
5
|
-
development: http://github.com/proutils/qed
|
4
|
+
mailing list: http://groups.google.com/group/proutils
|
5
|
+
development: http://github.com/proutils/qed
|
6
6
|
|
7
7
|
|
8
8
|
== Introduction
|
@@ -10,23 +10,22 @@
|
|
10
10
|
Q.E.D. is an abbreviation for the well known Latin phrase "Quod Erat Demonstrandum",
|
11
11
|
literally "which was to be demonstrated", which is oft written in its abbreviated
|
12
12
|
form at the end of a mathematical proof or philosophical argument to signify the
|
13
|
-
successful
|
13
|
+
a successful conclusion. And so it is too for Ruby Q.E.D., though it might as easily
|
14
|
+
be taken to stand for "Quality Ensured Documentation".
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
best addressing <i>API-Driven Development</i>, which is especially useful when
|
22
|
-
designing reusable libraries.
|
16
|
+
QED is in fact both a test framework and a documentation system for Ruby
|
17
|
+
developers. QED sits somewhere between lower-level testing tools like Test::Unit
|
18
|
+
and grand requirement specifications tools like Cucumber. In practice it works
|
19
|
+
exceptionally well for <i>API-Driven Design</i>, which is especially useful when
|
20
|
+
designing reusable libraries, but it can be used to test code at any level
|
21
|
+
of abstract, from unit test to systems tests.
|
23
22
|
|
24
23
|
|
25
24
|
== Features
|
26
25
|
|
27
|
-
*
|
28
|
-
*
|
29
|
-
*
|
26
|
+
* Write tests and documentation in the same breath!
|
27
|
+
* Demos can be RDoc, Markdown or any other conforming text format.
|
28
|
+
* Uses the excellent Assertive Expressive library for assertions.
|
30
29
|
* Table macro allows large sets of data to be run by the same code.
|
31
30
|
* Documentation tool provides nice output with jQuery-based TOC.
|
32
31
|
|
@@ -35,21 +34,22 @@ designing reusable libraries.
|
|
35
34
|
|
36
35
|
=== Assertion Syntax
|
37
36
|
|
38
|
-
QED uses AE (Assertive Expressive) library to provide an elegant means to
|
39
|
-
|
37
|
+
QED uses the AE (Assertive Expressive) library to provide an elegant means to
|
38
|
+
make assertions. To give a quick overview, assertion can be written as:
|
40
39
|
|
41
40
|
4.assert == 5
|
42
41
|
|
43
42
|
In this example, because 4 != 5, this expression will raise an Assertion
|
44
43
|
exception. QED's Runner class is thus just a means of running and capturing
|
45
|
-
code
|
44
|
+
code blocks containing these assertions.
|
46
45
|
|
47
46
|
You can learn more about AE at http://proutils.github.com/ae.
|
48
47
|
|
49
48
|
=== Document Structure
|
50
49
|
|
51
|
-
QED documents are simply text files
|
52
|
-
|
50
|
+
QED documents are simply text files called *demonstrandum*. Because they
|
51
|
+
largely consist of free-form descriptive text, they are a practice pure
|
52
|
+
Literate Programming. For example:
|
53
53
|
|
54
54
|
= Example
|
55
55
|
|
@@ -61,13 +61,14 @@ For example:
|
|
61
61
|
|
62
62
|
5.assert == 5
|
63
63
|
|
64
|
-
|
65
|
-
can be used. The only necessary distinction is that description text
|
66
|
-
align to the left margin and all code be indented
|
64
|
+
In this example RDoc was chosen for the document format. However, almost any
|
65
|
+
text format can be used. The only necessary distinction is that description text
|
66
|
+
align to the left margin and all code be indented, although QED does recognize
|
67
67
|
RDoc and Markdown single-line style headers, so any format that supports
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
those (which covers many markup formats in use today) will have mildly
|
69
|
+
improved console output. In any case, the essential take away here is that
|
70
|
+
QED *demonstrandum* are simply descriptive documents with interspersed
|
71
|
+
blocks of example code.
|
71
72
|
|
72
73
|
Give this design some thought. It should become clear that this approach is
|
73
74
|
especially fruitful in that it allows *documentation* and *specification*
|
@@ -83,25 +84,57 @@ To run a document through QED, simply use the +qed+ command.
|
|
83
84
|
|
84
85
|
$ qed -v demo/01_example.rdoc
|
85
86
|
|
86
|
-
The <
|
87
|
+
The <code>-v</code> option specifies verbatim mode, which outputs the entire
|
87
88
|
document.
|
88
89
|
|
89
|
-
Notice we placed the QED document in the <
|
90
|
-
|
91
|
-
|
92
|
-
<
|
93
|
-
the documents properly
|
90
|
+
Notice we placed the QED document in the <code>demo/</code> or <code>demos/</code>
|
91
|
+
directory, this is the conical place that has been designated for them, though you
|
92
|
+
can of course put them elsewhere in your project if you prefer. Also notice the
|
93
|
+
<code>01_</code> prefix in front of the name. While this is not strictly necessary,
|
94
|
+
it helps order the documents properly when generating QED documentation (QEDocs).
|
95
|
+
|
96
|
+
=== Utilizeing Applique
|
97
|
+
|
98
|
+
QED demonstrandum descriptive text is not stricty passive explination. Using
|
99
|
+
pattern matching techniques, document phrases can trigger underlying actions.
|
100
|
+
These actions provide a support structure for running tests called the *applique*.
|
101
|
+
|
102
|
+
Creating an applique is easy. Along with your QED scripts, to which the
|
103
|
+
applique will apply, create an <code>applique/</code> directory. In this
|
104
|
+
directory add Ruby scripts. When you run your demos every Ruby script in
|
105
|
+
the directory will be automatically loaded.
|
106
|
+
|
107
|
+
Within these applique scripts *advice* can be defined. Advice can be
|
108
|
+
either *event advice*, which is simply triggered by some fixed cycle
|
109
|
+
of running, such as <code>Before :document</code> or <code>After :all</code>,
|
110
|
+
and *pattern advice* which are used to match against descriptive
|
111
|
+
phrases in the QED demos. An example would be:
|
112
|
+
|
113
|
+
When "a new round is started" do
|
114
|
+
@round = []
|
115
|
+
end
|
116
|
+
|
117
|
+
So that whenever the phrase "a new round is started" appears in a demo,
|
118
|
+
the @round instance variable with be reset to an empty array.
|
119
|
+
|
120
|
+
It is rather amazing what can be accomplished with such a system,
|
121
|
+
be sure to look at QED's own demonstandum to get a better notion of
|
122
|
+
how you can put the the system to use.
|
123
|
+
|
124
|
+
=== Generating Documentation
|
94
125
|
|
95
126
|
To generate documentation from QED documents, use the +qedoc+ command.
|
96
127
|
|
97
128
|
$ qedoc --output doc/qedoc --title "Example" demo/*.rdoc
|
98
129
|
|
99
|
-
When documenting QED recognizes the format by the file extension and
|
100
|
-
treats it accordingly. An extension of <
|
101
|
-
as <
|
130
|
+
When documenting, QED recognizes the format by the file extension and
|
131
|
+
treats it accordingly. An extension of <code>.qed</code> is treated the same
|
132
|
+
as <code>.rdoc</code>.
|
133
|
+
|
134
|
+
Use the <code>--help</code> options on each command to get more information
|
135
|
+
on the use of these commands.
|
136
|
+
|
102
137
|
|
103
|
-
Use the <tt>--help</tt> options on each command to get more information on
|
104
|
-
the use of these commands.
|
105
138
|
|
106
139
|
|
107
140
|
== Requirements
|
data/REQUIRE
ADDED
data/ROADMAP
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
= ROADMAP
|
2
|
+
|
3
|
+
== 2.2.0
|
4
|
+
|
5
|
+
* Simplify code. I do not think we need both an Evaluator and Scope classes.
|
6
|
+
|
7
|
+
== 2.3.0
|
8
|
+
|
9
|
+
* Add a distributed evaluator, probably using Drb. This will allow the code
|
10
|
+
portion of documents to run in an isolated process. It will also make it possible
|
11
|
+
(in the long run) to run tests in parallel acrosss a cluster.
|
12
|
+
|
data/VERSION
ADDED
data/demo/01_demos.rdoc
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
= Demonstrations
|
2
|
+
|
3
|
+
== Standard Sections
|
4
|
+
|
5
|
+
QED demos are light-weight specification documents, highly suitable
|
6
|
+
to interface-driven design. The documents are divided up into
|
7
|
+
clauses separated by blank lines. Clauses that are flush to the
|
8
|
+
left margin are always explanation or comment clauses. Indented
|
9
|
+
clauses are always executable code.
|
10
|
+
|
11
|
+
Each code section is executed in order of appearance, within a
|
12
|
+
rescue wrapper that captures any failures or errors. If neither
|
13
|
+
a failure or error occur then the code gets a "pass".
|
14
|
+
|
15
|
+
For example, the following passes:
|
16
|
+
|
17
|
+
(2 + 2).assert == 4
|
18
|
+
|
19
|
+
While the following would "fail", as indicated by the raising of
|
20
|
+
an Assertion error:
|
21
|
+
|
22
|
+
expect Assertion do
|
23
|
+
(2 + 2).assert == 5
|
24
|
+
end
|
25
|
+
|
26
|
+
And this would have raised a NameError:
|
27
|
+
|
28
|
+
expect NameError do
|
29
|
+
nobody_knows_method
|
30
|
+
end
|
31
|
+
|
32
|
+
== Neutral Code Blocks
|
33
|
+
|
34
|
+
There is no means of specifying that a code clause is neutral code,
|
35
|
+
i.e. that it should be executed but not tested. Thus far, such a
|
36
|
+
feature has proven to be a YAGNI.
|
37
|
+
|
38
|
+
== Defining Custom Assertions
|
39
|
+
|
40
|
+
The context in which the QED code is run is a self-extended module, thus
|
41
|
+
reusable macros can be created simply by defining a method.
|
42
|
+
|
43
|
+
def assert_integer(x)
|
44
|
+
x.assert.is_a? Integer
|
45
|
+
end
|
46
|
+
|
47
|
+
Now lets try out our new macro definition.
|
48
|
+
|
49
|
+
assert_integer(4)
|
50
|
+
|
51
|
+
Let's prove that it can also fail:
|
52
|
+
|
53
|
+
expect Assertion do
|
54
|
+
assert_integer("IV")
|
55
|
+
end
|
56
|
+
|
data/demo/02_advice.rdoc
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
= Advice
|
2
|
+
|
3
|
+
Advice are event-based procedures that augment demonstrations.
|
4
|
+
They are used to keep demonstrations clean of extraneous,
|
5
|
+
repetitive and merely adminstrative code that the reader does
|
6
|
+
not need to see over and over.
|
7
|
+
|
8
|
+
Typically you will want to put advice definitions is applique
|
9
|
+
files, rather then place them directly in the demonstration
|
10
|
+
document, but you can do so, as you will see in this document.
|
11
|
+
|
12
|
+
== Before and After
|
13
|
+
|
14
|
+
QED supports *before* and *after* clauses in a specification
|
15
|
+
through the use of Before and After code blocks. These blocks
|
16
|
+
are executed at the beginning and at the end of each indicated
|
17
|
+
step.
|
18
|
+
|
19
|
+
We use a *before* clause if we want to setup some code at the
|
20
|
+
start of each code step.
|
21
|
+
|
22
|
+
a, z = nil, nil
|
23
|
+
|
24
|
+
Before do
|
25
|
+
a = "BEFORE"
|
26
|
+
end
|
27
|
+
|
28
|
+
And an *after* clause to teardown objects after a code step.
|
29
|
+
|
30
|
+
After do
|
31
|
+
z = "AFTER"
|
32
|
+
end
|
33
|
+
|
34
|
+
Notice we assigned +a+ and +z+ before the block. This was to ensure
|
35
|
+
their visibility in the scope later. Now, lets verify that the *before*
|
36
|
+
and *after* clauses work.
|
37
|
+
|
38
|
+
a.assert == "BEFORE"
|
39
|
+
|
40
|
+
a = "A"
|
41
|
+
z = "Z"
|
42
|
+
|
43
|
+
And now.
|
44
|
+
|
45
|
+
z.assert == "AFTER"
|
46
|
+
|
47
|
+
There can be more than one before and after clause at a time. If we
|
48
|
+
define a new *before* or *after* clause later in the document,
|
49
|
+
it will be appended to the current list of clauses in use.
|
50
|
+
|
51
|
+
As a demonstration of this:
|
52
|
+
|
53
|
+
b = nil
|
54
|
+
|
55
|
+
Before do
|
56
|
+
b = "BEFORE AGAIN"
|
57
|
+
end
|
58
|
+
|
59
|
+
We will see it is the case.
|
60
|
+
|
61
|
+
b.assert == "BEFORE AGAIN"
|
62
|
+
|
63
|
+
Only use *before* and *after* clauses when necessary --specifications
|
64
|
+
are generally more readable without them. Indeed, some developers
|
65
|
+
make a policy of avoiding them altogether. YMMV.
|
66
|
+
|
67
|
+
== Caveats of Before and After
|
68
|
+
|
69
|
+
Instead of using Before and After clauses, it is wiser to
|
70
|
+
define a reusable setup method. For example, in the helper
|
71
|
+
if we define a method such as #prepare_example.
|
72
|
+
|
73
|
+
def prepare_example
|
74
|
+
"Hello, World!"
|
75
|
+
end
|
76
|
+
|
77
|
+
Then we can reuse it in later code blocks.
|
78
|
+
|
79
|
+
example = prepare_example
|
80
|
+
example.assert == "Hello, World!"
|
81
|
+
|
82
|
+
The advantage to this is that it gives the reader an indication
|
83
|
+
of what is going on behind the scenes, rather the having
|
84
|
+
an object just magically appear.
|
85
|
+
|
86
|
+
== Event Targets
|
87
|
+
|
88
|
+
There is a small set of advice targets that do not come before
|
89
|
+
or after an event, rather they occur *upon* a particular event.
|
90
|
+
These include +:load+ and +:unload+ for when a new helper is loaded;
|
91
|
+
+:pass+, +:fail+ and +:error+ for when a code block passes, fails or
|
92
|
+
raises an error; and +:text+ and +:code+ which target the immediate
|
93
|
+
processing of a text block and code excecution.
|
94
|
+
|
95
|
+
These event targets can be advised by calling the +When+ method
|
96
|
+
with the target type as an argument along with the code block
|
97
|
+
to be run when the event is triggered.
|
98
|
+
|
99
|
+
x = []
|
100
|
+
|
101
|
+
When(:text) do |section|
|
102
|
+
section.text.scan(/^\*(.*?)$/) do |m|
|
103
|
+
x << $1.strip
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
Not let see if it worked:
|
108
|
+
|
109
|
+
* SampleA
|
110
|
+
* SampleB
|
111
|
+
* SampleC
|
112
|
+
|
113
|
+
So +x+ should now contain these three list samples.
|
114
|
+
|
115
|
+
x.assert == [ 'SampleA', 'SampleB', 'SampleC' ]
|
116
|
+
|
117
|
+
|
118
|
+
== Pattern Matchers
|
119
|
+
|
120
|
+
QED also supports comment match triggers. With the +When+ method one can
|
121
|
+
define procedures to run when a given pattern matches comment text.
|
122
|
+
For example:
|
123
|
+
|
124
|
+
When 'given a setting @a equal to (((\d+)))' do |n|
|
125
|
+
@a = n.to_i
|
126
|
+
end
|
127
|
+
|
128
|
+
Now, @a will be set to 1 whenever a comment like this one contains,
|
129
|
+
"given a setting @a equal to 1".
|
130
|
+
|
131
|
+
@a.assert == 1
|
132
|
+
|
133
|
+
A string pattern is translated into a regular expression. In fact, you can
|
134
|
+
use a regular expression if you need more control over the match. When
|
135
|
+
using a string all spaces are converted to <tt>\s+</tt> and anything within
|
136
|
+
double-parenthesis is treated as raw regular expression. Since the above
|
137
|
+
example has (((\d+))), the actual regular expression contains <tt>(\d+)</tt>,
|
138
|
+
so any number can be used. For example, "given a setting @a equal to 2".
|
139
|
+
|
140
|
+
@a.assert == 2
|
141
|
+
|
142
|
+
When clauses can also use consecutive pattern matching. For instance
|
143
|
+
we could write:
|
144
|
+
|
145
|
+
When 'first match #(((\d+)))', 'then match #(((\d+)))' do |i1, i2|
|
146
|
+
@a = [i1.to_i, i2.to_i]
|
147
|
+
end
|
148
|
+
|
149
|
+
So that 'first match #1' will be looked for first, and only after
|
150
|
+
that if 'then match #2' is found, will it be condiered a complete match.
|
151
|
+
All regular expression slots are collected from all matches and passed to
|
152
|
+
the block. We can see that the rule matched this very paragraph:
|
153
|
+
|
154
|
+
@a.assert == [1,2]
|
155
|
+
|
156
|
+
This concludes the basic overview of QED's specification system, which
|
157
|
+
is itself a QED document. Yes, we eat our own dog food.
|
158
|
+
|