qed 1.1.0 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
data/demo/data.txt ADDED
@@ -0,0 +1 @@
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.
@@ -1 +1,2 @@
1
1
  require 'ae/expect'
2
+
data/demo/table.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ - [ try , TRY ]
3
+ - [ me , ME ]
4
+ - [ mc , MC ]
5
+
data/doc/qedoc/index.html CHANGED
@@ -1,6 +1,6 @@
1
1
  <html>
2
2
  <head>
3
- <title>QED Overview</title>
3
+ <title>Demonstration</title>
4
4
 
5
5
  <style>
6
6
  #container{ margin: 0 auto; width: 800px; }
@@ -89,7 +89,7 @@
89
89
  <div id="header">
90
90
  <img src="img/icon/book.jpg" align="left" style="padding-right: 10px;" alt=""/>
91
91
 
92
- <h1 class="title">QED Overview</h1>
92
+ <h1 class="title">Demonstration</h1>
93
93
 
94
94
  <h1>Table of Contents</h1>
95
95
 
@@ -115,31 +115,30 @@ occur then the code gets a &#8220;pass&#8221;.
115
115
  For example, the following passes:
116
116
  </p>
117
117
  <pre>
118
- (2 + 2).assert == 4
118
+ (2 + 2).assert == 4
119
119
  </pre>
120
120
  <p>
121
121
  While the following would &#8220;fail&#8221;, as indicated by the raising
122
122
  of an Assertion error:
123
123
  </p>
124
124
  <pre>
125
- expect Assertion do
126
- (2 + 2).assert == 5
127
- end
125
+ expect Assertion do
126
+ (2 + 2).assert == 5
127
+ end
128
128
  </pre>
129
129
  <p>
130
130
  And this would have raised a NameError:
131
131
  </p>
132
132
  <pre>
133
- expect NameError do
134
- nobody_knows_method
135
- end
133
+ expect NameError do
134
+ nobody_knows_method
135
+ end
136
136
  </pre>
137
137
  <h1>Neutral Code</h1>
138
138
  <p>
139
139
  There is no means of specifying that a code clause is neutral code, i.e.
140
- that it should be executed but not tested. So far this such a feature has
141
- proven to be a YAGNI. Yet we may add such a feature in the future if it is
142
- ultimately deemed necessary.
140
+ that it should be executed but not tested. Thus far, such a feature has
141
+ proven to be a YAGNI.
143
142
  </p>
144
143
  <h1>Defining Custom Assertions</h1>
145
144
  <p>
@@ -147,30 +146,32 @@ The context in which the QED code is run is a self-extended module, thus
147
146
  reusable macros can be created simply by defining a method.
148
147
  </p>
149
148
  <pre>
150
- def assert_integer(x)
151
- x.assert.is_a? Integer
152
- end
149
+ def assert_integer(x)
150
+ x.assert.is_a? Integer
151
+ end
153
152
  </pre>
154
153
  <p>
155
154
  Now lets try out our new macro definition.
156
155
  </p>
157
156
  <pre>
158
- assert_integer(4)
157
+ assert_integer(4)
159
158
  </pre>
160
159
  <p>
161
160
  Let&#8217;s prove that it can also fail:
162
161
  </p>
163
162
  <pre>
164
- expect Assertion do
165
- assert_integer(&quot;IV&quot;)
166
- end
163
+ expect Assertion do
164
+ assert_integer(&quot;IV&quot;)
165
+ end
167
166
  </pre>
168
167
  <h1>Helper File</h1>
169
168
  <p>
170
- If you create a file called `qed_helper.rb` located in the directory with
171
- the QED documents you are running via the `qed` command, it will be loaded
172
- first. You can use that to load optional AE features, or define your own
173
- specialized assertion methods.
169
+ Helpers can be defined at the bottom of any QED document by placing the
170
+ code after a triple-dash divider (ie. &#8220;&#8212;&#8221;). You can use
171
+ that to load optional AE features, or define your own specialized assertion
172
+ methods. Helpers can be defined in a separate files using <tt>require</tt>
173
+ or <tt>load</tt> in the bottom section to import them. The bottom section
174
+ is run first, before any the steps.
174
175
  </p>
175
176
  <h1>Before and After Clauses</h1>
176
177
  <p>
@@ -183,36 +184,36 @@ We use a <b>before</b> clause if we want to setup some code at the start of
183
184
  each step.
184
185
  </p>
185
186
  <pre>
186
- a, z = nil, nil
187
+ a, z = nil, nil
187
188
 
188
- before do
189
- a = &quot;BEFORE&quot;
190
- end
189
+ Before do
190
+ a = &quot;BEFORE&quot;
191
+ end
191
192
  </pre>
192
193
  <p>
193
- And an <b>after</b> clause to tear down objects after a step.
194
+ And an <b>after</b> clause to teardown objects after a step.
194
195
  </p>
195
196
  <pre>
196
- after do
197
- z = &quot;AFTER&quot;
198
- end
197
+ After do
198
+ z = &quot;AFTER&quot;
199
+ end
199
200
  </pre>
200
201
  <p>
201
202
  Notice we assigned <tt>a</tt> and <tt>z</tt> before the block. This was to
202
- ensure their visibility in the scope later. Now, lets verify this the
203
- <b>before</b> and <b>after</b> clause work.
203
+ ensure their visibility in the scope later. Now, lets verify that the
204
+ <b>before</b> and <b>after</b> clauses work.
204
205
  </p>
205
206
  <pre>
206
- a.assert == &quot;BEFORE&quot;
207
+ a.assert == &quot;BEFORE&quot;
207
208
 
208
- a = &quot;A&quot;
209
- z = &quot;Z&quot;
209
+ a = &quot;A&quot;
210
+ z = &quot;Z&quot;
210
211
  </pre>
211
212
  <p>
212
213
  And now.
213
214
  </p>
214
215
  <pre>
215
- z.assert == &quot;AFTER&quot;
216
+ z.assert == &quot;AFTER&quot;
216
217
  </pre>
217
218
  <p>
218
219
  There can only be one before or after clause at a time. So if we define a
@@ -223,28 +224,38 @@ replace the current clause(s) in use.
223
224
  As a demonstration of this:
224
225
  </p>
225
226
  <pre>
226
- before do
227
- a = &quot;BEFORE AGAIN&quot;
228
- end
227
+ Before do
228
+ a = &quot;BEFORE AGAIN&quot;
229
+ end
229
230
  </pre>
230
231
  <p>
231
232
  We will see it is the case.
232
233
  </p>
233
234
  <pre>
234
- a.assert == &quot;BEFORE AGAIN&quot;
235
+ a.assert == &quot;BEFORE AGAIN&quot;
235
236
  </pre>
236
237
  <p>
237
238
  Only use <b>before</b> and <b>after</b> clauses when necessary
238
239
  &#8212;specifications are generally more readable without them. Indeed,
239
240
  some developers make a policy of avoiding them altogether. YMMV.
240
241
  </p>
242
+ <h1>External Data</h1>
243
+ <p>
244
+ When creating testable demonstrations, there are times when sizable chunks
245
+ of data are needed. It is convenient to store such data in a separate file.
246
+ The <tt>Data</tt> method makes is easy to load such files.
247
+ </p>
248
+ <pre>
249
+ Data('data.txt').assert =~ /dolor/
250
+ </pre>
251
+ <p>
252
+ All files are looked for relative to the location of current document.
253
+ </p>
241
254
  <h1>Tabular Steps</h1>
242
255
  <p>
243
- Finally we will demonstrate a tabular step. <tt>table</tt> method is used
244
- for this. We supply a file name to the method telling QED where to find the
245
- table data to be used in the test. All table files are looked for relative
246
- to the location of the document. If no name is given the
247
- &#8217;<doc-name>.yaml&#8217; is assumed.
256
+ The <tt>Table</tt> method is similar to the <tt>Data</tt> method except
257
+ that it expects a YAML file, and it can take a block to iterate the data
258
+ over. This makes it easy to test tables of examples.
248
259
  </p>
249
260
  <p>
250
261
  The arity of the table block determines the number of columns each row in
@@ -252,20 +263,54 @@ the table should have. Each row is assigned in turn and run through the
252
263
  coded step. Consider the following example:
253
264
  </p>
254
265
  <p>
255
- Every row in &#8216;table.yaml&#8217; will be assigned to the block
256
- parameters and run through the following assertion.
266
+ Every row in the <a href="http://table.yml">table.yml table</a> will be
267
+ assigned to the block parameters and run through the subsequent assertion.
257
268
  </p>
258
269
  <pre>
259
- table do |x,y|
260
- x.upcase.assert == y
261
- end
270
+ Table 'table.yml' do |x, y|
271
+ x.upcase.assert == y
272
+ end
262
273
  </pre>
274
+ <h1>Comment Triggers</h1>
275
+ <p>
276
+ QED also supports comment match triggers. With the <tt>When</tt> method one
277
+ can define setup and teardown procedures by matching against comment text.
278
+ For example:
279
+ </p>
280
+ <pre>
281
+ When 'given a setting @a equal to (((\d+)))' do |n|
282
+ @a = n.to_i
283
+ end
284
+ </pre>
285
+ <p>
286
+ Now, @a will be set to 1 whenever a comment like this one contains,
287
+ &#8220;given a setting @a equal to 1&#8221;.
288
+ </p>
289
+ <pre>
290
+ @a.assert == 1
291
+ </pre>
292
+ <p>
293
+ A string pattern is translated into a regular expression. In fact, you can
294
+ use a regular expression if you need more control over the match. When
295
+ using a string all spaces are converted to <tt>\s+</tt> and anything within
296
+ double-parenthesis is treated as raw regular expression. Since the above
297
+ example has (((\d+))), the actual regular expression contains
298
+ <tt>(\d+)</tt>, so any number can be used. For example, &#8220;given a
299
+ setting @a equal to 2&#8221;.
300
+ </p>
301
+ <pre>
302
+ @a.assert == 2
303
+ </pre>
304
+ <p>
305
+ Typically you will want to put triggers is helper files, rather then place
306
+ them directly in the demonstration document.
307
+ </p>
263
308
  <p>
264
309
  This concludes the basic overview of QED&#8217;s specification system,
265
310
  which is itself a QED document. Yes, we eat our own dog food.
266
311
  </p>
267
- <p>
268
- Q.E.D.
312
+ <hr size="1"></hr><p>
313
+ require &#8216;helper&#8217;
269
314
  </p>
270
315
 
271
316
 
data/lib/qed.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module QED
2
- VERSION="1.0.0" #:till: VERSION="<%= version %>"
2
+ VERSION="1.2" #:till: VERSION="<%= version %>"
3
3
  end
4
4
 
5
5
  require 'qed/runner'
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'qed'
4
+ require 'optparse'
5
+
6
+ module QED
7
+
8
+ # = QED Commandline Tool
9
+ #
10
+ class Command
11
+ def self.execute
12
+ new.execute
13
+ end
14
+
15
+ #
16
+ attr :format
17
+
18
+ #
19
+ def initialize
20
+ @format = nil
21
+ end
22
+
23
+ # Instance of OptionParser
24
+ def opts
25
+ @opts ||= OptionParser.new do |opt|
26
+
27
+ opt.on('--dotprogress', '-d', "use dot-progress reporter [default]") do
28
+ @format = :summary
29
+ end
30
+
31
+ opt.on('--verbatim', '-v', "use verbatim reporter") do
32
+ @format = :verbatim
33
+ end
34
+
35
+ opt.on('--summary', '-s', "use summary reporter") do
36
+ @format = :summary
37
+ end
38
+
39
+ opt.on('--script', "psuedo-reporter") do
40
+ @format = :script # psuedo-reporter
41
+ end
42
+
43
+ opt.on('--loadpath', "-I", "add paths to $LOAD_PATH") do |arg|
44
+ libs = arg.split(/[:;]/).map{ |dir| File.expand_path(dir) }
45
+ libs.each{|dir| $LOAD_PATH.unshift(dir)}
46
+ end
47
+
48
+ opt.on('--verbose', '-V', "extra verbose output") do
49
+ @verbose = true
50
+ $VERBOSE = true
51
+ end
52
+
53
+ opt.on('--debug', "demos will exit on error") do
54
+ $DEBUG = true
55
+ end
56
+
57
+ opt.on_tail('--version', "display version") do
58
+ puts "QED #{VERSION}"
59
+ exit
60
+ end
61
+
62
+ opt.on_tail('--copyright', "display copyrights") do
63
+ puts "Copyright (c) 2008, 2009 Thomas Sawyer, GPL License"
64
+ exit
65
+ end
66
+
67
+ opt.on_tail('--help', '-h', "display this help message") do
68
+ puts opt
69
+ exit
70
+ end
71
+
72
+ end
73
+ end
74
+
75
+ #
76
+ #def load_rc
77
+ # if rcfile = Dir['.config/qed{,rc}{,.rb}'].first
78
+ # load(rcfile)
79
+ # end
80
+ #end
81
+
82
+ # TODO: Better way to load helpers?
83
+ #
84
+ #def load_helpers
85
+ # dirs = spec_files.map{ |file| File.join(Dir.pwd, File.dirname(file)) }
86
+ # dirs = dirs.select{ |dir| File.directory?(dir) }
87
+ # dirs.each do |dir|
88
+ # while dir != '/' do
89
+ # helper = File.join(dir, 'qed_helper.rb')
90
+ # load(helper) if File.exist?(helper)
91
+ # break if Dir.pwd == dir
92
+ # dir = File.dirname(dir)
93
+ # end
94
+ # end
95
+ #end
96
+
97
+ #
98
+ def demos
99
+ demo_files
100
+ end
101
+
102
+ #
103
+ def demo_files
104
+ files = ARGV.map do |pattern|
105
+ Dir[pattern]
106
+ end.flatten.uniq
107
+
108
+ files = files.map do |file|
109
+ if File.directory?(file)
110
+ Dir[File.join(file,'**','*{.qed,.rd,.rdoc,.md,.markdown}')]
111
+ else
112
+ file
113
+ end
114
+ end
115
+
116
+ file = files.flatten.uniq
117
+
118
+ #files = files.select do |file|
119
+ # %w{.yml .yaml .rb}.include?(File.extname(file))
120
+ #end
121
+
122
+ files
123
+ end
124
+
125
+ #
126
+ def reporter
127
+ case format
128
+ when :dotprogress
129
+ Reporter::DotProgress.new(reporter_options)
130
+ when :verbatim
131
+ Reporter::Verbatim.new(reporter_options)
132
+ when :summary
133
+ Reporter::Summary.new(reporter_options)
134
+ else
135
+ nil
136
+ end
137
+ end
138
+
139
+ #
140
+ def reporter_options
141
+ { :verbose => @verbose }
142
+ end
143
+
144
+ #
145
+ def runner
146
+ Runner.new(demos, reporter)
147
+ end
148
+
149
+ #
150
+ def execute
151
+ opts.parse!
152
+ #load_rc
153
+ #load_helpers
154
+ case reporter
155
+ when :script
156
+ specs.each do |spec|
157
+ puts spec.to_script
158
+ end
159
+ else
160
+ runner.check
161
+ end
162
+ end
163
+
164
+ end
165
+ end
166
+
data/lib/qed/document.rb CHANGED
@@ -12,8 +12,8 @@ module QED
12
12
 
13
13
  DEFAULT_TITLE = "Demonstration"
14
14
  DEFAULT_CSS = nil #"../assets/styles/spec.css"
15
- DEFAULT_OUTPUT = "doc/spec"
16
- DEFAULT_PATH = ["spec/**/*"]
15
+ DEFAULT_OUTPUT = "doc/qedoc"
16
+ DEFAULT_PATH = "test/demos"
17
17
 
18
18
  attr_accessor :title
19
19
  attr_accessor :css
@@ -35,12 +35,15 @@ module QED
35
35
  @output ||= DEFAULT_OUTPUT
36
36
  @paths ||= []
37
37
 
38
- @paths = DEFAULT_PATH if @paths.empty?
38
+ if @paths.empty?
39
+ dir = Dir['{test/demos,demo,demos}'].first || DEFAULT_PATH
40
+ @paths = File.join(dir, '**', '*')
41
+ end
39
42
  end
40
43
 
41
- # Specification files.
42
- def spec_files
43
- @spec_files ||= (
44
+ # Demo files.
45
+ def demo_files
46
+ @demo_files ||= (
44
47
  glob = paths.map{ |f| File.directory?(f) ? Dir["#{f}/**/*"] : Dir[f] }.flatten
45
48
  glob = glob.select do |f|
46
49
  File.file?(f) && f !~ /fixtures\/|helpers\// && f !~ /\.rb$/
@@ -66,7 +69,7 @@ module QED
66
69
 
67
70
  #TODO: load .config/qedrc.rb
68
71
 
69
- spec_files.each do |file|
72
+ demo_files.each do |file|
70
73
  puts file unless quiet?
71
74
 
72
75
  #strio = StringIO.new('')
@@ -76,19 +79,26 @@ module QED
76
79
  #iotext = strio.string
77
80
  #strio.close
78
81
 
79
- case ext = File.extname(file)
82
+ ext = File.extname(file)
83
+ txt = File.read(file)
84
+
85
+ if ext == '.qed'
86
+ ext = file_type(txt)
87
+ end
88
+
89
+ case ext
80
90
  #when '.qed'
81
91
  # require_qedoc
82
92
  # markup = Markup.new(File.read(file))
83
93
  # text << markup.to_html
84
- when '.rd', '.rdoc', '.qed'
94
+ when '.rd', '.rdoc'
85
95
  require_rdoc
86
96
  markup = RDoc::Markup::ToHtml.new
87
- text << markup.convert(File.read(file))
97
+ text << markup.convert(txt)
88
98
  #text << markup.convert(iotext, formatter)
89
99
  when '.md', '.markdown'
90
100
  require_rdiscount
91
- markdown = RDiscount.new(File.read(file))
101
+ markdown = RDiscount.new(txt)
92
102
  text << markdown.to_html
93
103
  end
94
104
  text << "\n"
@@ -135,6 +145,21 @@ module QED
135
145
 
136
146
  private
137
147
 
148
+ #
149
+ def file_type(text)
150
+ rdoc = text.index(/^\=/)
151
+ markdown = text.index(/^\#/)
152
+ if markdown && rdoc
153
+ rdoc < markdown ? '.rdoc' : '.markdown'
154
+ elsif rdoc
155
+ '.rdoc'
156
+ elsif markdown
157
+ '.markdown'
158
+ else # fallback to rdoc
159
+ '.rdoc'
160
+ end
161
+ end
162
+
138
163
  #
139
164
  def require_qedoc
140
165
  @require_rdoc ||= (
@@ -146,8 +171,13 @@ module QED
146
171
  #
147
172
  def require_rdoc
148
173
  @require_rdoc ||= (
149
- require 'rdoc/markup/to_html'
150
- #require 'rdoc/markup/simple_markup'
174
+ begin
175
+ require 'rdoc/markup/to_html'
176
+ rescue LoadError
177
+ require 'rubygems'
178
+ gem 'rdoc'
179
+ retry
180
+ end
151
181
  true
152
182
  )
153
183
  end