qed 2.9.0 → 2.9.1
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/.index +69 -0
- data/.yardopts +3 -2
- data/{HISTORY.rdoc → HISTORY.md} +44 -32
- data/LICENSE.txt +25 -0
- data/{README.rdoc → README.md} +60 -51
- data/{qed/01_demos.rdoc → demo/01_demos.md} +3 -3
- data/{qed/02_advice.rdoc → demo/02_advice.md} +17 -17
- data/{qed/03_helpers.rdoc → demo/03_helpers.md} +10 -10
- data/{qed/04_samples.rdoc → demo/04_samples.md} +5 -5
- data/{qed/05_quote.rdoc → demo/05_quote.md} +7 -7
- data/{qed/07_toplevel.rdoc → demo/07_toplevel.md} +11 -11
- data/{qed/08_cross_script.rdoc → demo/08_cross_script.md} +9 -9
- data/{qed/09_cross_script.rdoc → demo/09_cross_script.md} +13 -14
- data/demo/10_constant_lookup.md +16 -0
- data/{qed/11_embedded_rules.rdoc → demo/11_embedded_rules.md} +13 -13
- data/{qed/99_issues/02_topcode.rdoc → demo/99_issues/02_topcode.md} +0 -0
- data/{qed → demo}/applique/ae.rb +0 -0
- data/{qed → demo}/applique/constant.rb +0 -0
- data/{qed → demo}/applique/env.rb +0 -0
- data/{qed → demo}/applique/fileutils.rb +0 -0
- data/{qed → demo}/applique/markup.rb +0 -0
- data/demo/applique/quote.md +8 -0
- data/{qed → demo}/applique/toplevel.rb +0 -0
- data/{qed → demo}/helpers/advice.rb +0 -0
- data/{qed → demo}/helpers/toplevel.rb +0 -0
- data/{qed → demo}/samples/data.txt +0 -0
- data/{qed → demo}/samples/table.yml +0 -0
- data/lib/qed.yml +41 -42
- data/lib/qed/cli.rb +2 -4
- data/lib/qed/cli/qed.rb +30 -3
- data/lib/qed/evaluator.rb +4 -1
- data/lib/qed/reporter/abstract.rb +1 -1
- data/lib/qed/session.rb +9 -2
- data/lib/qed/settings.rb +6 -122
- data/lib/qed/utils.rb +125 -0
- metadata +80 -56
- data/.config.rb +0 -24
- data/.ruby +0 -70
- data/COPYING.rdoc +0 -31
- data/lib/qed/rc.rb +0 -12
- data/qed/10_constant_lookup.rdoc +0 -16
- data/qed/applique/quote.rdoc +0 -8
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
# QED Demonstrandum
|
2
2
|
|
3
|
-
|
3
|
+
## Steps
|
4
4
|
|
5
5
|
QED demos are light-weight specification documents, highly suitable
|
6
6
|
to interface-driven design. The documents are divided up into
|
@@ -29,7 +29,7 @@ And this would have raised a NameError.
|
|
29
29
|
nobody_knows_method
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
## Defining Custom Assertions
|
33
33
|
|
34
34
|
The context in which the QED code is run is a self-extended module, thus
|
35
35
|
reusable macros can be created simply by defining a method.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# Advice
|
2
2
|
|
3
3
|
Advice are event-based procedures that augment demonstrations.
|
4
4
|
They are used to keep demonstrations clean of extraneous,
|
@@ -9,7 +9,7 @@ Typically you will want to put advice definitions in applique
|
|
9
9
|
files, rather then place them directly in the demonstration
|
10
10
|
document, but you can do so, as you will see in this document.
|
11
11
|
|
12
|
-
|
12
|
+
## Before and After
|
13
13
|
|
14
14
|
QED supports *before* and *after* clauses in a specification
|
15
15
|
through the use of Before and After code blocks. These blocks
|
@@ -64,26 +64,26 @@ Only use *before* and *after* clauses when necessary --specifications
|
|
64
64
|
are generally more readable without them. Indeed, some developers
|
65
65
|
make a policy of avoiding them altogether. YMMV.
|
66
66
|
|
67
|
-
|
67
|
+
## Caveats of Before and After
|
68
68
|
|
69
69
|
Instead of using Before and After clauses, it is wiser to
|
70
70
|
define a reusable setup method. For example, in the helper
|
71
71
|
if we define a method such as #prepare_example.
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
def prepare_example
|
74
|
+
"Hello, World!"
|
75
|
+
end
|
76
76
|
|
77
77
|
Then we can reuse it in later code blocks.
|
78
78
|
|
79
|
-
|
80
|
-
|
79
|
+
example = prepare_example
|
80
|
+
example.assert == "Hello, World!"
|
81
81
|
|
82
82
|
The advantage to this is that it gives the reader an indication
|
83
83
|
of what is going on behind the scenes, rather the having
|
84
84
|
an object just magically appear.
|
85
85
|
|
86
|
-
|
86
|
+
## Event Targets
|
87
87
|
|
88
88
|
There is a small set of advice targets that do not come before or after,
|
89
89
|
rather they occur *upon* a particular event. These include +:pass+, +:fail+
|
@@ -95,13 +95,13 @@ These event targets can be advised by calling the +When+ method
|
|
95
95
|
with the target type as an argument along with the code block
|
96
96
|
to be run when the event is triggered.
|
97
97
|
|
98
|
-
|
98
|
+
x = []
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
When(:step) do |section|
|
101
|
+
section.text.scan(/^\*(.*?)$/) do |m|
|
102
|
+
x << $1.strip
|
103
|
+
end
|
103
104
|
end
|
104
|
-
end
|
105
105
|
|
106
106
|
Now let's see if it worked.
|
107
107
|
|
@@ -111,9 +111,9 @@ Now let's see if it worked.
|
|
111
111
|
|
112
112
|
So +x+ should now contain these three list samples.
|
113
113
|
|
114
|
-
|
114
|
+
x.assert == [ 'SampleA', 'SampleB', 'SampleC' ]
|
115
115
|
|
116
|
-
|
116
|
+
## Pattern Matchers
|
117
117
|
|
118
118
|
QED also supports comment match triggers. With the +When+ method one can
|
119
119
|
define procedures to run when a given pattern matches comment text.
|
@@ -159,7 +159,7 @@ that if 'then match #2' is found, will it be considered a complete match.
|
|
159
159
|
All regular expression slots are collected from all matches and passed to
|
160
160
|
the block. We can see that the rule matched this very paragraph.
|
161
161
|
|
162
|
-
|
162
|
+
@a.assert == [1,2]
|
163
163
|
|
164
164
|
This concludes the basic overview of QED's specification system, which
|
165
165
|
is itself a QED document. Yes, we eat our own dog food.
|
@@ -1,31 +1,31 @@
|
|
1
|
-
|
1
|
+
# Helpers
|
2
2
|
|
3
3
|
There are two ways to load advice scripts. Manually loaded
|
4
|
-
helpers act
|
4
|
+
helpers act pe-demonstrandum and so apply only to the currently
|
5
5
|
executing demo. Automaticly loaded helpers apply to all
|
6
6
|
demonstrandum within their preview.
|
7
7
|
|
8
8
|
Helper scripts can be written just like demonstration scripts,
|
9
9
|
or they can be defined as pure Ruby scripts.
|
10
10
|
|
11
|
-
|
11
|
+
## Automatic Helpers
|
12
12
|
|
13
13
|
Automatic helpers, known as the "applique" are loaded at the
|
14
14
|
start of a session and apply equally to all demonstrandum within
|
15
|
-
the same or lower directory as
|
15
|
+
the same or lower directory as the demo. These helpers are placed
|
16
16
|
in an +applique+ subdirectory. For instance this document uses,
|
17
|
-
|
17
|
+
[applique/env.rb](applique/env.rb).
|
18
18
|
|
19
|
-
|
19
|
+
## Manual Helpers
|
20
20
|
|
21
21
|
Manual helpers are loaded per-demonstration by using specially
|
22
22
|
marked links.
|
23
23
|
|
24
|
-
For example, because this link, Advice
|
25
|
-
begins with
|
24
|
+
For example, because this link, [Advice](qed://helpers/advice.rb),
|
25
|
+
begins with `qed:`, it will be used to load a helper. We can
|
26
26
|
see this with the following assertion.
|
27
27
|
|
28
|
-
|
28
|
+
pudding.assert.include?('loaded advice.rb')
|
29
29
|
|
30
30
|
No where in the demonstration have we defined +pudding+, but
|
31
31
|
it has been defined for us in the advice.rb helper script.
|
@@ -35,7 +35,7 @@ helper is keeping count of decriptive paragraphs. Since the
|
|
35
35
|
helper script was loaded two paragraphs back, the next count
|
36
36
|
will be 3.
|
37
37
|
|
38
|
-
|
38
|
+
count.assert == 3
|
39
39
|
|
40
40
|
Helpers are vital to building test-demonstration suites for
|
41
41
|
applications. But here again, only use them as necessary.
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
1
|
+
# Test Samples
|
2
2
|
|
3
|
-
|
3
|
+
## Flat-file Data
|
4
4
|
|
5
5
|
When creating testable demonstrations, there are times when sizable
|
6
6
|
chunks of data are needed. It is convenient to store such data in
|
@@ -19,7 +19,7 @@ Files are looked-up relative to the location of the current document.
|
|
19
19
|
If not found then they will be looked-up relative to the current
|
20
20
|
working directory.
|
21
21
|
|
22
|
-
|
22
|
+
## Tabular Data
|
23
23
|
|
24
24
|
The +Table+ method is similar to the +Data+ method except that it
|
25
25
|
expects a YAML file, and it can take a block to iterate the data over.
|
@@ -29,7 +29,7 @@ The arity of the table block corresponds to the number of columns in
|
|
29
29
|
each row of the table. Each row is assigned in turn and run through
|
30
30
|
the coded step. Consider the following example.
|
31
31
|
|
32
|
-
Every row in the
|
32
|
+
Every row in the [table.yml table](table.yml) will be assigned to
|
33
33
|
the block parameters and run through the subsequent assertion.
|
34
34
|
|
35
35
|
Table File.dirname(__FILE__) + '/samples/table.yml' do |x, y|
|
@@ -38,7 +38,7 @@ the block parameters and run through the subsequent assertion.
|
|
38
38
|
|
39
39
|
Without the block, the +Table+ methods simply returns the sample data.
|
40
40
|
|
41
|
-
|
41
|
+
## Considerations
|
42
42
|
|
43
43
|
Both Data and Table are some what "old fashion" approches to sample
|
44
44
|
data. New techinques using plain text blocks are more convenient
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# Quotes
|
2
2
|
|
3
3
|
We do not always want verbatim clauses to be interpreted as code.
|
4
4
|
Sometimes it would more useful to treat them a plain text to
|
@@ -7,9 +7,9 @@ which the preceeding paragraph can make use in a processing rule.
|
|
7
7
|
For example let say we want to make an example out of the following
|
8
8
|
text:
|
9
9
|
|
10
|
-
|
10
|
+
The file will contain
|
11
11
|
|
12
|
-
|
12
|
+
this text
|
13
13
|
|
14
14
|
The use of the colon (`:`) tells the processor that the next
|
15
15
|
segment is a plain text continuation of the current segment, rather
|
@@ -19,7 +19,7 @@ the end of the arguments list of any applicable processing rule.
|
|
19
19
|
Behind the scenes we created a rule to set the text to an instance
|
20
20
|
variable called @quote_text, and we can verify it is so.
|
21
21
|
|
22
|
-
|
22
|
+
@quote_text.assert == "The file will contain\n\nthis text"
|
23
23
|
|
24
24
|
Alternately we can use a colon (':') instead of ellipsis. We can repeat
|
25
25
|
the same statment as above.
|
@@ -27,11 +27,11 @@ the same statment as above.
|
|
27
27
|
For example let say we want to make an example out of the following
|
28
28
|
text:
|
29
29
|
|
30
|
-
|
30
|
+
The file will contain
|
31
31
|
|
32
|
-
|
32
|
+
different text
|
33
33
|
|
34
34
|
And again we can verify that it did in fact set the @quote_text variable.
|
35
35
|
|
36
|
-
|
36
|
+
@quote_text.assert == "The file will contain\n\ndifferent text"
|
37
37
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# Toplevel Simulation
|
2
2
|
|
3
3
|
QED simulates Ruby's TOPLEVEL environment in both the Demonstrandum
|
4
4
|
and the Applique contexts. This serves two important purposes.
|
@@ -10,31 +10,31 @@ the code it is intended to test.
|
|
10
10
|
Let's look at some examples. For starters, we have access to a class
|
11
11
|
defined at the "toplevel" in the applique.
|
12
12
|
|
13
|
-
|
13
|
+
ToplevelClass
|
14
14
|
|
15
15
|
We can also call a method defined in the toplevel.
|
16
16
|
|
17
|
-
|
17
|
+
toplevel_method.assert == true
|
18
18
|
|
19
19
|
At the demonstrandum level we can define reusable methods.
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
def demo_method
|
22
|
+
true
|
23
|
+
end
|
24
24
|
|
25
|
-
|
25
|
+
demo_method.assert == true
|
26
26
|
|
27
27
|
And at the demonstrandum level even singleton methods are accessible.
|
28
28
|
|
29
|
-
|
29
|
+
def self.singleton_method; true; end
|
30
30
|
|
31
|
-
|
31
|
+
singleton_method.assert == true
|
32
32
|
|
33
33
|
QED uses a self-extend modules to achieve this simulation, so the
|
34
34
|
contexts are in fact a bit more capable then even Ruby's TOPLEVEL.
|
35
35
|
For instance, #define_method can be used.
|
36
36
|
|
37
|
-
|
37
|
+
define_method(:named_method){ true }
|
38
38
|
|
39
|
-
|
39
|
+
named_method.assert == true
|
40
40
|
|
@@ -1,25 +1,25 @@
|
|
1
|
-
|
1
|
+
# Cross-Scripting Setup
|
2
2
|
|
3
3
|
We define some variables here to make sure it is
|
4
4
|
not visible in the next script.
|
5
5
|
|
6
6
|
Let's set two local variables.
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
a = 100
|
9
|
+
b = 200
|
10
10
|
|
11
11
|
And two instance varaibles.
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
@a = 1000
|
14
|
+
@b = 2000
|
15
15
|
|
16
16
|
Also let check how it effect constants.
|
17
17
|
|
18
|
-
|
18
|
+
CROSS_SCRIPT_CONSTANT = "cross?"
|
19
19
|
|
20
20
|
And a method.
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
def cross_script_method
|
23
|
+
"common"
|
24
|
+
end
|
25
25
|
|
@@ -1,29 +1,28 @@
|
|
1
|
-
|
1
|
+
# Cross-Scripting Check
|
2
2
|
|
3
3
|
Make sure local and instance variables from previous
|
4
4
|
QED scripts are not visible in this document.
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
expect NameError do
|
7
|
+
a.assert = 100
|
8
|
+
b.assert = 200
|
9
|
+
end
|
10
10
|
|
11
11
|
And two instance_varaibles
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
@a.assert! == 1000
|
14
|
+
@b.assert! == 2000
|
16
15
|
|
17
16
|
Method definitions also do not cross QED scripts.
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
expect NameError do
|
19
|
+
cross_script_method
|
20
|
+
end
|
22
21
|
|
23
22
|
Since each demo is encapsulated in a separated class scope, constants also
|
24
23
|
do not make their way across.
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
expect NameError do
|
26
|
+
CROSS_SCRIPT_CONSTANT
|
27
|
+
end
|
29
28
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Missing Constant
|
2
|
+
|
3
|
+
If a constant is missing it is because it was not found
|
4
|
+
in either the demos scope, the applique or at the toplevel.
|
5
|
+
|
6
|
+
begin
|
7
|
+
UnknownConstant
|
8
|
+
rescue => err
|
9
|
+
# no colon means toplevel
|
10
|
+
err.name.to_s.refute.include?('::')
|
11
|
+
end
|
12
|
+
|
13
|
+
A constant defined in the applique is visible.
|
14
|
+
|
15
|
+
APPLIQUE_CONSTANT.assert = true
|
16
|
+
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# Meta Code
|
2
2
|
|
3
3
|
All code steps are evaluated in a rescue clause. If an error occurs, it
|
4
4
|
is captured and reported through the test report, and execution continues.
|
@@ -6,20 +6,20 @@ However, sometimes this is not desired. To evaluate a step without the
|
|
6
6
|
rescue clause, and effective *fail fast*, append `^` mark to the end of
|
7
7
|
the desription text, like so. ^
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
When 'this is cool' do |text|
|
10
|
+
@text = text
|
11
|
+
end
|
12
12
|
|
13
13
|
Now, let's try it by saying, "this is cool":
|
14
14
|
|
15
|
-
|
15
|
+
And this is the text.
|
16
16
|
|
17
17
|
Did it work?
|
18
18
|
|
19
|
-
|
19
|
+
@text.assert == "And this is the text."
|
20
20
|
|
21
21
|
|
22
|
-
|
22
|
+
## Match Separator
|
23
23
|
|
24
24
|
The `When` method can take a list of String or Regexp as arguments.
|
25
25
|
If any of the strings contain `...`, the string will be split into
|
@@ -27,20 +27,20 @@ two at this point, which effective means that any text can occur
|
|
27
27
|
within this space. It behaves much like adding `((*.?))`, but parses
|
28
28
|
more quickly by dividing the string into multiple matches.
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
When 'Let /(\w+)/ be ... scared of /(\w+)/' do |name, monster|
|
31
|
+
@name = name
|
32
|
+
@monster = monster
|
33
|
+
end
|
34
34
|
|
35
35
|
Okay let's try it: Let John be very scared of Zombies.
|
36
36
|
|
37
37
|
So now what is the name?
|
38
38
|
|
39
|
-
|
39
|
+
@name.assert == "John"
|
40
40
|
|
41
41
|
What is the monster?
|
42
42
|
|
43
|
-
|
43
|
+
@monster.assert == "Zombies"
|
44
44
|
|
45
45
|
Did it work?
|
46
46
|
|
File without changes
|
data/{qed → demo}/applique/ae.rb
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|