qed 2.6.3 → 2.7.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.
Files changed (55) hide show
  1. data/.ruby +4 -3
  2. data/.yardopts +3 -0
  3. data/HISTORY.rdoc +71 -35
  4. data/README.rdoc +9 -10
  5. data/bin/qed +1 -1
  6. data/bin/qedoc +2 -1
  7. data/lib/qed.rb +2 -5
  8. data/lib/qed.yml +4 -3
  9. data/lib/qed/applique.rb +57 -24
  10. data/lib/qed/cli.rb +8 -0
  11. data/lib/qed/cli/qed.rb +124 -0
  12. data/lib/qed/demo.rb +35 -39
  13. data/lib/qed/document.rb +5 -3
  14. data/lib/qed/document/template.rhtml +1 -0
  15. data/lib/qed/evaluator.rb +227 -199
  16. data/lib/qed/parser.rb +60 -282
  17. data/lib/qed/reporter/abstract.rb +54 -58
  18. data/lib/qed/reporter/dotprogress.rb +6 -4
  19. data/lib/qed/reporter/html.rb +112 -31
  20. data/lib/qed/reporter/tapy.rb +95 -125
  21. data/lib/qed/reporter/verbatim.rb +80 -38
  22. data/lib/qed/scope.rb +35 -48
  23. data/lib/qed/session.rb +35 -140
  24. data/lib/qed/settings.rb +104 -67
  25. data/lib/qed/step.rb +237 -0
  26. data/{spec → qed}/01_demos.rdoc +0 -0
  27. data/{spec → qed}/02_advice.rdoc +18 -7
  28. data/qed/03_helpers.rdoc +44 -0
  29. data/{spec → qed}/04_samples.rdoc +4 -4
  30. data/{spec → qed}/05_quote.rdoc +3 -3
  31. data/{spec → qed}/07_toplevel.rdoc +0 -0
  32. data/{spec → qed}/08_cross_script.rdoc +0 -0
  33. data/{spec → qed}/09_cross_script.rdoc +0 -0
  34. data/{spec → qed}/10_constant_lookup.rdoc +2 -2
  35. data/qed/11_embedded_rules.rdoc +46 -0
  36. data/{test/integration/topcode.rdoc → qed/99_issues/02_topcode.rdoc} +0 -0
  37. data/{spec → qed}/applique/constant.rb +0 -0
  38. data/{spec → qed}/applique/env.rb +0 -0
  39. data/{spec → qed}/applique/fileutils.rb +0 -0
  40. data/{spec → qed}/applique/markup.rb +0 -0
  41. data/{spec → qed}/applique/toplevel.rb +0 -0
  42. data/{spec → qed}/helpers/advice.rb +6 -7
  43. data/{spec → qed}/helpers/toplevel.rb +0 -0
  44. data/{spec → qed}/samples/data.txt +0 -0
  45. data/{spec → qed}/samples/table.yml +0 -0
  46. metadata +44 -39
  47. data/LICENSE.rdoc +0 -31
  48. data/SPECSHEET.rdoc +0 -456
  49. data/lib/qed/advice.rb +0 -158
  50. data/lib/qed/reporter/bullet.rb +0 -91
  51. data/lib/qed/reporter/dtrace.rb +0 -67
  52. data/lib/yard-qed.rb +0 -1
  53. data/spec/03_helpers.rdoc +0 -43
  54. data/spec/applique/quote.rb +0 -4
  55. data/spec/helpers/sample.rb +0 -4
@@ -3,9 +3,11 @@ module Reporter #:nodoc:
3
3
 
4
4
  require 'qed/reporter/abstract'
5
5
 
6
- # = DotProgress Reporter
6
+ # The dot reporter is the traditional test reporter where
7
+ # dot is printed for every successful step, an 'E' for
8
+ # errors and an 'F' for failures.
7
9
  #
8
- class DotProgress < Abstract
10
+ class Dot < Abstract
9
11
 
10
12
  #
11
13
  def before_session(session)
@@ -27,13 +29,13 @@ module Reporter #:nodoc:
27
29
  end
28
30
 
29
31
  def fail(step, assertion)
30
- io.print "F"
32
+ io.print "F".ansi(:red)
31
33
  io.flush
32
34
  super(step, assertion)
33
35
  end
34
36
 
35
37
  def error(step, exception)
36
- io.print "E"
38
+ io.print "E".ansi(:red)
37
39
  io.flush
38
40
  super(step, exception)
39
41
  end
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module QED
2
4
  module Reporter
3
5
 
@@ -5,7 +7,7 @@ module Reporter
5
7
 
6
8
  # = Html Reporter
7
9
  #
8
- # FIXME: This must be completely redesigned since we moved back
10
+ # NOTE: This must be completely redesigned since we moved back
9
11
  # to text based evaluation --which makes generting HTML with
10
12
  # modifications from the evaluation tricky. But I've come up
11
13
  # with a farily clever way to handle this. Take the original
@@ -22,56 +24,135 @@ module Reporter
22
24
 
23
25
  #
24
26
  def initialize(*args)
25
- raise "HTML format is not currently working"
27
+ require 'erb'
28
+
29
+ begin
30
+ require 'rubygems'
31
+ gem 'rdoc'
32
+ require 'rdoc'
33
+ rescue
34
+ end
35
+
36
+ super(*args)
26
37
  end
27
38
 
28
39
  #
29
- def pass(step)
30
- step['class'] = 'pass' # TODO add class not replace
31
- step['style'] = 'color: green;' # TODO add style not replace
40
+ def before_session(session)
41
+ io.puts <<-END
42
+ <html>
43
+ <head>
44
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
45
+ <title>QED Report</title>
46
+ <style>
47
+ body{width:800px; margin:0 auto;}
48
+ pre{font-family: courier,monospace;}
49
+ .pass{color: #020;}
50
+ .pass pre{color: green;}
51
+ .fail{color: #200; background: pink;}
52
+ .fail pre{color: green;}
53
+ .error{color: #200; background: pink;}
54
+ .error pre{color: red;}
55
+ </style>
56
+ </head>
57
+ <body>
58
+ END
32
59
  end
33
60
 
34
61
  #
35
- def fail(step, assertion)
36
- step['class'] = 'fail' # TODO add class not replace
37
- step['style'] = 'color: red;' # TODO add style not replace
62
+ def before_demo(demo)
63
+ io.puts <<-END
64
+ <h2>#{localize_file(demo.file)}</h2>
65
+ END
66
+ end
38
67
 
39
- msg = "\n"
40
- msg << " ##### FAIL #####\n"
41
- msg << " # " + assertion.to_s
42
- msg << "\n"
68
+ def step(step)
69
+ @_explain = step.explain.dup
70
+ end
43
71
 
44
- step.add_child(Nokogiri::HTML.fragment(msg))
72
+ #
73
+ def match(step, md)
74
+ #@match = md
75
+ unless md[0].empty?
76
+ @_explain.sub!(md[0], "<b>#{md[0]}</b>")
77
+ end
45
78
  end
46
79
 
47
80
  #
48
- def error(step, exception)
49
- raise exception if $DEBUG
81
+ def pass(step)
82
+ io.puts <<-END
83
+ <div class="test pass">
84
+ #{render(@_explain)}
50
85
 
51
- step['class'] = 'error' # TODO add class not replace
52
- step['style'] = 'color: red;' # TODO add style not replace
86
+ <pre>#{step.example}</pre>
87
+ </div>
88
+ END
89
+ end
53
90
 
54
- msg = "\n"
55
- msg << " ##### ERROR #####\n"
56
- msg << " # " + exception.to_s + "\n"
57
- msg << " # " + exception.backtrace[0]
58
- msg << "\n"
91
+ #
92
+ def fail(step, assertion)
93
+ io.puts ERB.new(<<-END).result(binding)
94
+ <div class="test fail">
95
+ #{render(@_explain)}
96
+
97
+ <pre>#{step.example}</pre>
98
+
99
+ <div class="assertion">
100
+ <p>#{assertion.class} - #{assertion.message}</p>
101
+ <ol>
102
+ <% assertion.backtrace.each do |bt| %>
103
+ <li><%= bt %></li>
104
+ <% end %>
105
+ </ol>
106
+ </div>
107
+ </div>
108
+ END
109
+ end
59
110
 
60
- step.add_child(Nokogiri::HTML.fragment(msg))
111
+ #
112
+ def error(step, exception)
113
+ io.puts ERB.new(<<-END).result(binding)
114
+ <div class="test error">
115
+ #{render(@_explain)}
116
+
117
+ <pre>#{step.example}</pre>
118
+
119
+ <div class="exception">
120
+ <p>#{exception.class} - #{exception.message}</p>
121
+ <ol>
122
+ <% exception.backtrace.each do |bt| %>
123
+ <li><%= bt %></li>
124
+ <% end %>
125
+ </ol>
126
+ </div>
127
+ </div>
128
+ END
61
129
  end
62
130
 
63
131
  #
64
- def after_document(demo)
65
- io.puts demo.document.to_s
132
+ def after_demo(demo)
66
133
  end
67
134
 
68
- #def report(str)
69
- # count[-1] += 1 unless count.empty?
70
- # str = str.chomp('.') + '.'
71
- # str = count.join('.') + ' ' + str
72
- # io.puts str.strip
73
- #end
135
+ #
136
+ def after_session(session)
137
+ io.puts <<-END
138
+ </body>
139
+ </html>
140
+ END
141
+ end
74
142
 
143
+ private
144
+
145
+ def render(str)
146
+ rdoc.convert(str.strip)
147
+ end
148
+
149
+ def rdoc
150
+ @rdoc ||= RDoc::Markup::ToHtml.new
151
+ end
152
+
153
+ #def h(str)
154
+ # ERB::Util.html_escape(str)
155
+ #end
75
156
  end
76
157
 
77
158
  end#module Reporter
@@ -13,22 +13,27 @@ module Reporter #:nodoc:
13
13
  class TapY < Abstract
14
14
 
15
15
  #
16
- def head(step)
16
+ def before_session(session)
17
+ @start_time = Time.now
18
+
17
19
  data = {
18
- 'type' => 'header',
20
+ 'type' => 'suite',
19
21
  'start' => Time.now.strftime('%Y-%m-%d %H:%M:%S'),
20
- 'count' => session.total_step_count
22
+ 'count' => session.total_step_count,
23
+ 'rev' => 2
21
24
  }
22
25
  io.puts data.to_yaml
23
26
  end
24
27
 
25
- #
26
- def desc(step)
27
- #data = {
28
- # 'type' => 'note',
29
- # 'description' => step.to_s.strip
30
- #}
31
- #io.puts data.to_yaml
28
+ # TODO: Handle cases by file or by headers?
29
+ def demo(demo)
30
+ data = {
31
+ 'type' => 'case',
32
+ 'subtype' => 'demo',
33
+ 'label' => localize_file(demo.file),
34
+ 'level' => 0
35
+ }
36
+ io.puts data.to_yaml
32
37
  end
33
38
 
34
39
  #
@@ -36,44 +41,51 @@ module Reporter #:nodoc:
36
41
  def pass(step)
37
42
  super(step)
38
43
 
39
- lines = step.text.split("\n")
44
+ source_line = lines = step.text.split("\n")
45
+
40
46
  #snip, l = [], step.line
41
47
  #lines.map do |line|
42
48
  # snip << { (l += 1) => line }
43
49
  #end
44
50
 
45
- if step.header?
46
- data = {
47
- 'type' => 'note',
48
- 'description' => step.text, #.strip,
49
- }
50
- elsif step.code?
51
- data = {
52
- 'type' => 'test',
53
- 'status' => 'pass',
54
- 'description' => step.text.strip,
55
- #'file' => step.file,
56
- #'line' => step.line,
57
- #'returned' => nil,
58
- #'expected' => nil,
59
- 'source' => lines.first,
60
- 'snippet' => step.text.strip,
61
- 'time' => time_since_start
62
- }
51
+ #if step.header?
52
+ # data = {
53
+ # 'type' => 'note',
54
+ # 'description' => step.text, #.strip,
55
+ # }
56
+
57
+ data = {
58
+ 'type' => 'test',
59
+ 'subtype' => 'step',
60
+ 'status' => 'pass',
61
+ 'label' => step.text.strip,
62
+ 'file' => localize_file(step.file),
63
+ 'line' => step.lineno,
64
+ 'time' => time_since_start
65
+ }
66
+
67
+ #'returned' => nil,
68
+ #'expected' => nil,
69
+
70
+ if step.example?
71
+ if step.code?
72
+ data.merge!(
73
+ 'source' => step.example_lines.first.last.strip,
74
+ 'snippet' => step.example_lines.map{ |n, l| {n => l.rstrip} }
75
+ )
76
+ else
77
+ data.merge!(
78
+ 'source' => step.example_lines.first.last.strip,
79
+ 'snippet' => step.example_lines.map{ |n, l| {n => l.rstrip} }
80
+ )
81
+ end
63
82
  else
64
- data = {
65
- 'type' => 'test',
66
- 'status' => 'pass',
67
- 'description' => step.text.strip,
68
- #'file' => step.file,
69
- #'line' => step.line,
70
- #'returned' => nil,
71
- #'expected' => nil,
72
- 'source' => lines.first,
73
- 'snippet' => step.text.strip,
74
- 'time' => time_since_start
75
- }
83
+ #data.merge!(
84
+ # 'source' => step.explain_lines.first.first,
85
+ # 'snippet' => step.sample_text
86
+ #)
76
87
  end
88
+
77
89
  io.puts data.to_yaml
78
90
  end
79
91
 
@@ -84,22 +96,30 @@ module Reporter #:nodoc:
84
96
  backtrace = sane_backtrace(assertion)
85
97
 
86
98
  file, line = file_line(backtrace)
99
+ file = localize_file(file)
87
100
 
88
101
  snippet = structured_code_snippet(assertion, bredth=3)
89
102
  source = snippet.map{ |h| h.values.first }[snippet.size / 2].strip
90
103
 
91
104
  data = {
92
105
  'type' => 'test',
106
+ 'subtype' => 'step',
93
107
  'status' => 'fail',
94
- 'description' => step.text.strip,
95
- 'file' => file,
96
- 'line' => line,
97
- 'message' => assertion.to_s.unansi,
108
+ 'label' => step.explain.strip,
109
+ 'file' => localize_file(step.file),
110
+ 'line' => step.explain_lineno,
98
111
  #'returned' => nil,
99
112
  #'expected' => nil,
100
- 'source' => source,
101
- 'snippet' => snippet,
102
- 'time' => time_since_start
113
+ 'time' => time_since_start,
114
+ 'exception' => {
115
+ 'message' => assertion.message, #unansi
116
+ 'class' => assertion.class.name,
117
+ 'file' => file,
118
+ 'line' => line,
119
+ 'source' => source,
120
+ 'snippet' => snippet,
121
+ 'backtrace' => backtrace
122
+ }
103
123
  }
104
124
 
105
125
  io.puts data.to_yaml
@@ -112,106 +132,56 @@ module Reporter #:nodoc:
112
132
  backtrace = sane_backtrace(exception)
113
133
 
114
134
  file, line = file_line(backtrace)
135
+ file = localize_file(file)
115
136
 
116
137
  snippet = structured_code_snippet(exception, bredth=3)
117
138
  source = snippet.map{ |h| h.values.first }[snippet.size / 2].strip
118
139
 
119
140
  data = {
120
141
  'type' => 'test',
142
+ 'subtype' => 'step',
121
143
  'status' => 'error',
122
- 'description' => step.text.strip,
123
- 'file' => file,
124
- 'line' => line,
125
- 'message' => exception.to_s.unansi,
144
+ 'label' => step.explain.strip,
145
+ 'file' => localize_file(step.file),
146
+ 'line' => step.explain_lineno,
126
147
  #'returned' => nil,
127
148
  #'expected' => nil,
128
- 'backtrace' => backtrace,
129
- 'source' => source,
130
- 'snippet' => snippet,
131
- 'time' => time_since_start
149
+ 'time' => time_since_start,
150
+ 'exception' => {
151
+ 'message' => assertion.message, #unansi
152
+ 'class' => assertion.class.name,
153
+ 'file' => file,
154
+ 'line' => line,
155
+ 'source' => source,
156
+ 'snippet' => snippet,
157
+ 'backtrace' => backtrace
158
+ }
132
159
  }
133
160
 
134
161
  io.puts data.to_yaml
135
162
  end
136
163
 
137
-
138
- =begin
139
- def fail(step, assertion)
140
- backtrace = sane_backtrace(assertion)
141
-
142
- msg = []
143
- msg << " " + "FAIL".ansi(:red)
144
- msg << ""
145
- msg << assertion.to_s.gsub(/^/, ' ')
146
- msg << ""
147
- backtrace.each do |bt|
148
- msg << " " + relative_file(bt)
149
- end
150
- io.puts msg.join("\n")
151
- io.puts
152
- io.print step.text.tabto(4)
153
- end
154
-
155
- def error(step, exception)
156
- raise exception if $DEBUG
157
-
158
- backtrace = sane_backtrace(exception)
159
-
160
- msg = []
161
- msg << " " + "ERROR".ansi(:red)
162
- msg << ""
163
- msg << " " + exception.to_s
164
- msg << ""
165
- backtrace.each do |bt|
166
- msg << " " + relative_file(bt)
167
- end
168
- io.puts msg.join("\n")
169
- io.puts
170
- io.print step.text.tabto(4)
171
- end
172
- =end
173
-
174
- #def report(str)
175
- # count[-1] += 1 unless count.empty?
176
- # str = str.chomp('.') + '.'
177
- # str = count.join('.') + ' ' + str
178
- # io.puts str.strip
179
- #end
180
-
181
- #def report_comment(step)
182
- # txt = step.to_s.strip.tabto(2)
183
- # txt[0,1] = "*"
184
- # io.puts txt
185
- # io.puts
186
- #end
187
-
188
- #def report_macro(step)
189
- # txt = step.to_s.tabto(2)
190
- # txt[0,1] = "*"
191
- # io.puts txt
192
- # #io.puts
193
- # #io.puts "#{step}".ansi(:magenta)
194
- #end
195
-
164
+ #
196
165
  def after_session(session)
197
166
  pass_size = steps.size - (fails.size + errors.size + omits.size)
198
167
 
199
168
  data = {
200
- 'type' => 'footer',
201
- 'tally' => {
202
- 'pass' => pass_size,
203
- 'fail' => fails.size,
204
- 'error' => errors.size,
205
- 'omit' => omits.size,
206
- 'pending' => 0
207
- },
208
- 'time' => time_since_start
169
+ 'type' => 'final',
170
+ 'time' => time_since_start,
171
+ 'counts' => {
172
+ 'total' => steps.size,
173
+ 'pass' => pass_size,
174
+ 'fail' => fails.size,
175
+ 'error' => errors.size,
176
+ 'omit' => omits.size,
177
+ 'todo' => 0
178
+ }
209
179
  }
210
180
 
211
181
  io.puts data.to_yaml
212
182
  end
213
183
 
214
- private
184
+ private
215
185
 
216
186
  #
217
187
  def time_since_start