qed 2.6.3 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
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