qed 1.0.0

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/bin/qed ADDED
@@ -0,0 +1,150 @@
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
+
149
+ QED::Command.execute
150
+
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'qed/document'
5
+
6
+ options = {}
7
+
8
+ usage = OptionParser.new do |usage|
9
+
10
+ usage.banner = "Usage: qedoc [OPTIONS] <QEDFile1> [ <QEDFile2> ... ]"
11
+
12
+ usage.on("-o", "--output [DIR]", "Output directory") do |dir|
13
+ options[:output]= dir
14
+ end
15
+
16
+ usage.on("-t", "--title [TITLE]", "Title of Document") do |title|
17
+ options[:title]= title
18
+ end
19
+
20
+ usage.on("--css [URI]", "Specify a URI for a CSS file add to HTML header.") do |uri|
21
+ options[:css] = uri
22
+ end
23
+
24
+ usage.on("--dryrun", "") do
25
+ options[:dryrun] = true
26
+ end
27
+
28
+ usage.on("-q", "--quiet", "") do
29
+ options[:quiet] = true
30
+ end
31
+
32
+ usage.on_tail("-h", "--help", "display this help message") do
33
+ puts usage
34
+ exit
35
+ end
36
+
37
+ end
38
+
39
+ usage.parse!
40
+
41
+ options[:paths] = ARGV.dup
42
+
43
+ #opts[:output] = cli.options[:file]
44
+ #opts[:dryrun] = cli.options[:dryrun]
45
+ #opts[:quiet] = cli.options[:quiet]
46
+ #opts[:css] = cli.options[:css]
47
+ #opts[:title] = cli.options[:title]
48
+
49
+ doc = QED::Document.new(options)
50
+
51
+ doc.generate
52
+
@@ -0,0 +1,143 @@
1
+ = Standard Sections
2
+
3
+ QED demos are light-weight specification documents, suitable
4
+ for Interface-driven Development. 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
+
31
+ = Neutral Code
32
+
33
+ There is no means of specifying that a code clause is neutral code,
34
+ i.e. that it should be executed but not tested. So far this
35
+ such a feature has proven to be a YAGNI. Yet we may add such a
36
+ feature in the future if it is ultimately deemed necessary.
37
+
38
+
39
+ = Defining Custom Assertions
40
+
41
+ The context in which the QED code is run is a self-extended module, thus
42
+ reusable macros can be created simply by defining a method.
43
+
44
+ def assert_integer(x)
45
+ x.assert.is_a? Integer
46
+ end
47
+
48
+ Now lets try out our new macro definition.
49
+
50
+ assert_integer(4)
51
+
52
+ Let's prove that it can also fail:
53
+
54
+ expect Assertion do
55
+ assert_integer("IV")
56
+ end
57
+
58
+
59
+ = Helper File
60
+
61
+ If you create a file called `qed_helper.rb` located in the directory with the
62
+ QED documents you are running via the `qed` command, it will be loaded first.
63
+ You can use that to load optional AE features, or define your own specialized
64
+ assertion methods.
65
+
66
+
67
+ = Before and After Clauses
68
+
69
+ QED supports *before* and *after* clauses in a specification
70
+ through the use of before and after code blocks. Before and after
71
+ clauses are executed at the beginning and at the end of each
72
+ subsequent step.
73
+
74
+ We use a *before* clause if we want to setup some code at the
75
+ start of each step.
76
+
77
+ a, z = nil, nil
78
+
79
+ before do
80
+ a = "BEFORE"
81
+ end
82
+
83
+ And an *after* clause to tear down objects after a step.
84
+
85
+ after do
86
+ z = "AFTER"
87
+ end
88
+
89
+ Notice we assigned +a+ and +z+ before the block. This was to ensure
90
+ their visibility in the scope later. Now, lets verify this the *before*
91
+ and *after* clause work.
92
+
93
+ a.assert == "BEFORE"
94
+
95
+ a = "A"
96
+ z = "Z"
97
+
98
+ And now.
99
+
100
+ z.assert == "AFTER"
101
+
102
+ There can only be one before or after clause at a time. So if we
103
+ define a new *before* or *after* clause later in the document,
104
+ it will replace the current clause(s) in use.
105
+
106
+ As a demonstration of this:
107
+
108
+ before do
109
+ a = "BEFORE AGAIN"
110
+ end
111
+
112
+ We will see it is the case.
113
+
114
+ a.assert == "BEFORE AGAIN"
115
+
116
+ Only use *before* and *after* clauses when necessary --specifications
117
+ are generally more readable without them. Indeed, some developers
118
+ make a policy of avoiding them altogether. YMMV.
119
+
120
+
121
+ = Tabular Steps
122
+
123
+ Finally we will demonstrate a tabular step. +table+ method is used
124
+ for this. We supply a file name to the method telling QED where to
125
+ find the table data to be used in the test. All table files are looked
126
+ for relative to the location of the document. If no name is given the
127
+ '<doc-name>.yaml' is assumed.
128
+
129
+ The arity of the table block determines the number of columns each row
130
+ in the table should have. Each row is assigned in turn and run
131
+ through the coded step. Consider the following example:
132
+
133
+ Every row in 'table.yaml' will be assigned to the block parameters
134
+ and run through the following assertion.
135
+
136
+ table do |x,y|
137
+ x.upcase.assert == y
138
+ end
139
+
140
+ This concludes the basic overview of QED's specification system, which
141
+ is itself a QED document. Yes, we eat our own dog food.
142
+
143
+ Q.E.D.
@@ -0,0 +1,4 @@
1
+ ---
2
+ - [ try , TRY ]
3
+ - [ me , ME ]
4
+
@@ -0,0 +1 @@
1
+ require 'ae/expect'
@@ -0,0 +1,355 @@
1
+ <html>
2
+ <head>
3
+ <title>QED Overview</title>
4
+
5
+ <style>
6
+ #container{ margin: 0 auto; width: 800px; }
7
+
8
+ /* Debug borders */
9
+ /* p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 { border: 1px solid red; } */
10
+
11
+ body { font-size: 14px; line-height: 20px; margin: 1em 5% 1em 5%; font-family: Verdana, Arial, Helvetica, sans-serif; }
12
+ a { color: #336; text-decoration: underline; }
13
+ a:visited { color: #334; }
14
+ em { font-style: italic; }
15
+ strong { font-weight: bold; }
16
+ tt { color: navy; }
17
+
18
+ h1, h2, h3, h4, h5, h6 { color: #223; margin-top: 1.2em; margin-bottom: 0.5em; line-height: 1.3; }
19
+ h1 { border-bottom: 2px solid silver; }
20
+ h2 { border-bottom: 2px solid silver; padding-top: 0.5em; }
21
+
22
+ hr { border: 1px solid silver; }
23
+
24
+ p { color: #222; text-align: justify; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.4em; }
25
+
26
+ pre { padding: 10; margin: 0; font-family: monospace; font-size: 0.9em; }
27
+ pre.pass { color: green; }
28
+ pre.fail { color: red; }
29
+ pre.error { color: red; font-weight: bold; }
30
+
31
+ span#author { color: #527bbd; font-weight: bold; font-size: 1.1em; }
32
+ span#email { }
33
+ span#revision { }
34
+
35
+ div#footer { font-size: small; border-top: 2px solid silver; padding-top: 0.5em; margin-top: 4.0em; }
36
+ div#footer-text { float: left; padding-bottom: 0.5em; }
37
+ div#footer-badges { float: right; padding-bottom: 0.5em; }
38
+
39
+ /* Block element content. */
40
+ div.content { padding: 0; }
41
+
42
+ /* Block element titles. */
43
+ h1.title { font-weight: bold; text-align: left; font-size: 3em; margin-top: 1.0em; margin-bottom: 0.5em; }
44
+
45
+ /* Block element titles. */
46
+ div.title, caption.title { font-weight: bold; text-align: left; margin-top: 1.0em; margin-bottom: 0.5em; }
47
+ div.title + * { margin-top: 0; }
48
+ td div.title:first-child { margin-top: 0.0em; }
49
+ div.content div.title:first-child { margin-top: 0.0em; }
50
+ div.content + div.title { margin-top: 0.0em; }
51
+ div.sidebarblock > div.content { background: #ffffee; border: 1px solid silver; padding: 0.5em; }
52
+
53
+ img { border-style: none; }
54
+
55
+ dl { margin-top: 0.8em; margin-bottom: 0.8em; }
56
+ dt { margin-top: 0.5em; margin-bottom: 0; font-style: italic; }
57
+ dd > *:first-child { margin-top: 0; }
58
+ ul, ol { list-style-position: outside; }
59
+
60
+ thead { font-weight: bold; }
61
+ tfoot { font-weight: bold; }
62
+ </style>
63
+
64
+ <!-- TODO: only include if these files exists -->
65
+ <link href="../assets/styles/spec.css" type="text/css" rel="stylesheet">
66
+ <!-- spec.css might be a problem with clobber -->
67
+ <link href="spec.css" type="text/css" rel="stylesheet">
68
+
69
+
70
+
71
+ <!-- JQuery is needed -->
72
+ <script src="jquery.js" type="text/javascript" language="javascript"></script>
73
+
74
+ </head>
75
+
76
+ <body>
77
+
78
+ <!-- Side Table of Contents -->
79
+ <div id="sidebar" style="position: fixed; top: 10; right: 10; background: white;">
80
+ <a href="javascript: toc_toggle();">
81
+ <img src="img/icon/book.jpg" height="30px;" style="border: none;" alt="TOC" align="right"/>
82
+ </a>
83
+
84
+ <div id="toc_side" class="toc">
85
+ </div>
86
+ </div>
87
+
88
+ <div id="container">
89
+ <div id="header">
90
+ <img src="img/icon/book.jpg" align="left" style="padding-right: 10px;" alt=""/>
91
+
92
+ <h1 class="title">QED Overview</h1>
93
+
94
+ <h1>Table of Contents</h1>
95
+
96
+ <div class="toc">
97
+ </div>
98
+ </div>
99
+
100
+ <div id="content">
101
+ <h1>Standard Sections</h1>
102
+ <p>
103
+ QED demos are light-weight specification documents, suitable for
104
+ Interface-driven Development. The documents are divided up into clauses
105
+ separated by blank lines. Clauses that are flush to the left margin are
106
+ always explanation or comment clauses. Indented clauses are always
107
+ executable code.
108
+ </p>
109
+ <p>
110
+ Each code section is executed in order of appearance, within a rescue
111
+ wrapper that captures any failures or errors. If neither a failure or error
112
+ occur then the code gets a &quot;pass&quot;.
113
+ </p>
114
+ <p>
115
+ For example, the following passes:
116
+ </p>
117
+ <pre>
118
+ (2 + 2).assert == 4
119
+ </pre>
120
+ <p>
121
+ While the following would &quot;fail&quot;, as indicated by the raising of
122
+ an Assertion error:
123
+ </p>
124
+ <pre>
125
+ Assertion.assert.raised? do
126
+ (2 + 2).assert == 5
127
+ end
128
+
129
+ #expect Assertion do
130
+ # (2 + 2).assert == 5
131
+ #end
132
+ </pre>
133
+ <p>
134
+ And this would have raised a NameError:
135
+ </p>
136
+ <pre>
137
+ expect NameError do
138
+ nobody_knows_method
139
+ end
140
+ </pre>
141
+ <h1>Neutral Code</h1>
142
+ <p>
143
+ There is no means of specifying that a code clause is neutral code, i.e.
144
+ that it should be executed but not tested. So far this such a feature has
145
+ proven to be a YAGNI. Yet we may add such a feature in the future if it is
146
+ ultimately deemed necessary.
147
+ </p>
148
+ <h1>Defining Macros</h1>
149
+ <p>
150
+ The context in which the QED code is run is a self-extended module, thus
151
+ reusable macros can be created simply by defining a method.
152
+ </p>
153
+ <pre>
154
+ def assert_integer(x)
155
+ x.assert.is_a? Integer
156
+ end
157
+ </pre>
158
+ <p>
159
+ Now lets try out our new macro definition.
160
+ </p>
161
+ <pre>
162
+ assert_integer(4)
163
+ </pre>
164
+ <p>
165
+ Let&#8217;s prove that it can also fail:
166
+ </p>
167
+ <pre>
168
+ expect Assertion do
169
+ assert_integer(&quot;IV&quot;)
170
+ end
171
+ </pre>
172
+ <h1>Before and After Clauses</h1>
173
+ <p>
174
+ QED supports <b>before</b> and <b>after</b> clauses in a specification
175
+ through the use of before and after code blocks. Before and after clauses
176
+ are executed at the beginning and at the end of each subsequent step.
177
+ </p>
178
+ <p>
179
+ We use a <b>before</b> clause if we want to setup some code at the start of
180
+ each step.
181
+ </p>
182
+ <pre>
183
+ a, z = nil, nil
184
+
185
+ before do
186
+ a = &quot;BEFORE&quot;
187
+ end
188
+ </pre>
189
+ <p>
190
+ And an <b>after</b> clause to tear down objects after a step.
191
+ </p>
192
+ <pre>
193
+ after do
194
+ z = &quot;AFTER&quot;
195
+ end
196
+ </pre>
197
+ <p>
198
+ Notice we assigned <tt>a</tt> and <tt>z</tt> before the block. This was to
199
+ ensure their visibility in the scope later. Now, lets verify this the
200
+ <b>before</b> and <b>after</b> clause work.
201
+ </p>
202
+ <pre>
203
+ a.assert == &quot;BEFORE&quot;
204
+
205
+ a = &quot;A&quot;
206
+ z = &quot;Z&quot;
207
+ </pre>
208
+ <p>
209
+ And now.
210
+ </p>
211
+ <pre>
212
+ z.assert == &quot;AFTER&quot;
213
+ </pre>
214
+ <p>
215
+ There can only be one before or after clause at a time. So if we define a
216
+ new <b>before</b> or <b>after</b> clause later in the document, it will
217
+ replace the current clause(s) in use.
218
+ </p>
219
+ <p>
220
+ As a demonstration of this:
221
+ </p>
222
+ <pre>
223
+ before do
224
+ a = &quot;BEFORE AGAIN&quot;
225
+ end
226
+ </pre>
227
+ <p>
228
+ We will see it is the case.
229
+ </p>
230
+ <pre>
231
+ a.assert == &quot;BEFORE AGAIN&quot;
232
+ </pre>
233
+ <p>
234
+ Only use <b>before</b> and <b>after</b> clauses when necessary
235
+ &#8212;specifications are generally more readable without them. Indeed,
236
+ some developers make a policy of avoiding them altogether. YMMV.
237
+ </p>
238
+ <h1>Tabular Steps</h1>
239
+ <p>
240
+ Finally we will demonstrate a tabular step. <tt>table</tt> method is used
241
+ for this. We supply a file name to the method telling QED where to find the
242
+ table data to be used in the test. All table files are looked for relative
243
+ to the location of the document. If no name is given the
244
+ &#8217;&lt;doc-name&gt;.yaml&#8217; is assumed.
245
+ </p>
246
+ <p>
247
+ The arity of the table block determines the number of columns each row in
248
+ the table should have. Each row is assigned in turn and run through the
249
+ coded step. Consider the following example:
250
+ </p>
251
+ <p>
252
+ Every row in &#8216;table.yaml&#8217; will be assigned to the block
253
+ parameters and run through the following assertion.
254
+ </p>
255
+ <pre>
256
+ table do |x,y|
257
+ x.upcase.assert == y
258
+ end
259
+ </pre>
260
+ <p>
261
+ This concludes the basic overview of QED&#8217;s specification system,
262
+ which is itself a QED document. Yes, we eat our own dog food.
263
+ </p>
264
+ <p>
265
+ Q.E.D.
266
+ </p>
267
+
268
+
269
+ </div>
270
+ </div>
271
+
272
+ </body>
273
+
274
+ </html>
275
+
276
+ <script src="../assets/scripts/spec.js" type="text/javascript" language="javascript"></script>
277
+
278
+ <script type="text/javascript" language="javascript">
279
+ /*****************************************************************
280
+ * $.toc()
281
+ * by rebecca murphey
282
+ * rmurphey gmail com
283
+ *
284
+ * This function is called on its own and takes as an argument
285
+ * a list of selectors with which it will build a table of
286
+ * contents.
287
+ *
288
+ * The first selector will make up the top level of the TOC;
289
+ * the second selector will make up the second level of the TOC;
290
+ * etc.
291
+ *
292
+ * This function returns a div containing nested unordered lists;
293
+ * each list item is linked to an anchor tag added before the item
294
+ * on the page.
295
+ *
296
+ * usage: $.toc('h1,h2,h3').prependTo('body');
297
+ ************************************************************************/
298
+ (function($) {
299
+ $.toc = function(tocList) {
300
+ $(tocList).addClass('jquery-toc');
301
+ var tocListArray = tocList.split(',');
302
+ $.each(tocListArray, function(i,v) { tocListArray[i] = $.trim(v); });
303
+ var $elements = $('.jquery-toc');
304
+ $('body').append('<div></div>');
305
+ var $toc = $('body div:last');
306
+ var lastLevel = 1;
307
+ $toc.append('<ul class="jquery-toc-1"></ul>');
308
+ $elements.each(function() {
309
+ var $e = $(this);
310
+ var text = $e.text();
311
+ var anchor = text.replace(/ /g,'-');
312
+ $e.before('<a name="' + anchor + '"></a>');
313
+ var level;
314
+ $.each(tocListArray, function(i,v) {
315
+ if (v.match(' ')) {
316
+ var vArray = v.split(' ');
317
+ var e = vArray[vArray.length - 1];
318
+ } else { e = v; }
319
+ if ($e.is(e)) { level = i+1; }
320
+ });
321
+ var className = 'jquery-toc-' + level;
322
+ var li = '<li><a href="#' + anchor + '">' + text + '</a></li>';
323
+ if (level == lastLevel) {
324
+ $('ul.' + className + ':last',$toc).append(li);
325
+ } else if (level > lastLevel) {
326
+ var parentLevel = level - 1;
327
+ var parentClassName = 'jquery-toc-' + parentLevel;
328
+ $('ul.' + parentClassName + ':last',$toc).
329
+ append('<ul class="' + className + '"></ul>');
330
+ $('ul.' + className + ':last',$toc).append(li);
331
+ } else if (level < lastLevel) {
332
+ $('ul.' + className + ':last',$toc).append(li);
333
+ }
334
+ lastLevel = level;
335
+ });
336
+ var $toc_ul = $('ul.jquery-toc-1',$toc);
337
+ $toc.remove();
338
+ return($toc_ul);
339
+ }
340
+ })(jQuery);
341
+ </script>
342
+
343
+ <script>
344
+ function toc_toggle() {
345
+ $('#toc_side').toggle();
346
+ $("pre").addClass("pass");
347
+ $("pre:contains('FAIL:')").addClass("fail");
348
+ $("pre:contains('ERROR:')").addClass("error");
349
+ };
350
+
351
+ $.toc('#content h1,h2,h3,h4').appendTo('.toc');
352
+
353
+ toc_toggle();
354
+ </script>
355
+