tapout 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.ruby CHANGED
@@ -29,17 +29,18 @@ resources:
29
29
  code: http://github.com/rubyworks/tapout
30
30
  load_path:
31
31
  - lib
32
- extra: {}
33
- date: '2011-10-07'
34
- version: 0.2.3
35
- alternatives: []
36
- revision: 0
32
+ extra:
33
+ manifest: MANIFEST
37
34
  source:
38
35
  - PROFILE
36
+ alternatives: []
37
+ revision: 0
39
38
  name: tapout
40
39
  title: TapOut
40
+ version: 0.3.0
41
41
  summary: Progressive TAP Harness
42
42
  description: Tapout is a TAP consumer that can take any TAP, TAP-Y or TAP-J stream
43
43
  and output it in a variety of useful formats.
44
44
  organization: RubyWorks
45
45
  created: '2010-12-23'
46
+ date: '2011-10-08'
@@ -1,6 +1,17 @@
1
1
  = RELEASE HISTORY
2
2
 
3
3
 
4
+ == 0.3.0 / 2011-10-09
5
+
6
+ This release supports revision 3 of the TAP-Y/J specification, which adds `final`
7
+ to the document types. The `final` document is the last document of a test suite.
8
+ It takes the place of `tally`, which is now simply an optional running subtotal
9
+ document.
10
+
11
+ This release also makes some intreface imporvements to the `Reporters::Abstract`
12
+ base class and ports over all applicable reporters from othe Turn project.
13
+
14
+
4
15
  == 0.2.3 / 2011-10-08
5
16
 
6
17
  Exit code are important for a test output format. This release addressed that
data/PROFILE CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: tapout
3
- version: 0.2.3
3
+ version: 0.3.0
4
4
 
5
5
  title: TapOut
6
6
  summary: Progressive TAP Harness
data/TAP-YJ.md CHANGED
@@ -1,4 +1,4 @@
1
- # TAP-Y/J Format
1
+ # TAP-Y/J Specification
2
2
 
3
3
  TAP-Y and TAP-J are test streams. They are essentially the same except
4
4
  for the underlying format used, which are YAML and JSON repsectively.
@@ -26,12 +26,15 @@ A `suite` document marks the beginning of a forthcoming stream of tests,
26
26
  i.e. a <i>test suite</i>. All TAP-Y streams MUST begin with a suite
27
27
  document.
28
28
 
29
+
29
30
  ---
30
31
  type: suite
31
32
  start: 2011-10-10 12:12:32
32
33
  count: 2
34
+ seed: 32154
33
35
  rev: 2
34
36
 
37
+
35
38
  The `start` field marks the date and time testing began. It MUST be
36
39
  an ISO-8601 formated timestamp.
37
40
 
@@ -40,6 +43,9 @@ If the number of test units is unknown, the total can be omitted or
40
43
  marked as `~` (nil). The total should only indicate the number of
41
44
  <i>test units</i>, not any enumeration of <i>test cases</i>.
42
45
 
46
+ The `seed` is provided if the test runner has randomized the order of
47
+ execution unit tests. The seed can be used to reproduce the same order.
48
+
43
49
  The `rev` field provides the version of the TAP-Y/J format that is
44
50
  being used. The specification will change little, if at all, as it
45
51
  become more mainstream. But just in case, having a revision field
@@ -50,12 +56,14 @@ apps to adjust to any future variation.
50
56
 
51
57
  The `case` type indicates the start of a test case.
52
58
 
59
+
53
60
  ---
54
61
  type: case
55
62
  subtype: feature
56
63
  label: Multiplication
57
64
  level: 0
58
65
 
66
+
59
67
  The case document MAY provide a `class` which is a label for the
60
68
  typ of test case. For example, a test framwework that uses Gherkin
61
69
  nomenclature would classify a test case as a "feature".
@@ -79,6 +87,7 @@ common fields.
79
87
 
80
88
  Here is an example of a passing unit document.
81
89
 
90
+
82
91
  ---
83
92
  type: test
84
93
  subtype: step
@@ -100,6 +109,7 @@ Here is an example of a passing unit document.
100
109
  code: Foo#*
101
110
  time: 0.01
102
111
 
112
+
103
113
  Besides the `status`, all test documents MUST have a `label`.
104
114
 
105
115
  A test document MAY provide a `setup` field, which is used to describe
@@ -140,6 +150,7 @@ If a test has a status other than `pass` it MUST also provide a `exception`
140
150
  subsection which is used to describe the nature of the failure, error or
141
151
  omission.
142
152
 
153
+
143
154
  ---
144
155
  type: test
145
156
  subtype: step
@@ -176,6 +187,7 @@ omission.
176
187
  - test/test_foo.rb:45
177
188
  time: 0.02
178
189
 
190
+
179
191
  The `exception` section MUST give the `message`, describing the nature
180
192
  of the failure or exception. In this subsection, `file` and `line` indicate
181
193
  the location in code that triggered the exception or failed assertion.
@@ -200,25 +212,28 @@ code with having to do additional processing.
200
212
  The `note` type is used to interject a message between tests that
201
213
  is not tied to a specific unit or case. It has only a few fields.
202
214
 
215
+
203
216
  ---
204
217
  type: note
205
218
  text:
206
219
  This is an example note.
207
220
 
221
+
208
222
  The note document is simply used to interject any information the
209
223
  tester might want to know, but doesn't properly fit elsewhere in the
210
224
  stream. A note cna appear any where in the document stream prior
211
225
  to the tally.
212
226
 
213
- ### Tally
227
+ ### Final & Tally
228
+
229
+ The `final` and `tally` types are the same. The difference is only that a `tally`
230
+ entry is a running tally, and can technically occur anywhere in the document
231
+ stream. The `final` entry on the other hand incidates the end of a test suite,
232
+ which will be followed by an end-document-marker (`...`).
214
233
 
215
- While a running tally can technically occur anywhere in the document
216
- stream without consequence, it generally incidates the end of a test
217
- suite, which is strictly complete with the end-document-marker (`...`)
218
- appears.
219
234
 
220
235
  ---
221
- type : tally
236
+ type : final
222
237
  time : 0.03
223
238
  counts:
224
239
  total: 2
@@ -229,11 +244,17 @@ appears.
229
244
  todo : 0
230
245
  ...
231
246
 
232
- A tally document MUST provide a counts mapping with the `total` number of
247
+
248
+ A tally/final document MUST provide a counts mapping with the `total` number of
233
249
  tests (this MUST be same as `count` in the suite document if it was given)
234
250
  and the totals for each test status. It SHOULD also give the time elapsed
235
251
  since the suite time.
236
252
 
253
+ Tally documents are very rare, if used at all. They only make sense for very
254
+ large test suites as a progress report mechanism. As a rule of thumb, TAP-Y/J
255
+ consumer apps will ignore them unless a configuration option (e.g. `--verbose`)
256
+ is used.
257
+
237
258
  As mentioned, the test stream ends when a full ellipsis (<code>...</code>)
238
259
  appears.
239
260
 
@@ -241,7 +262,6 @@ As you can see TAP-Y streams provides a great deal of detail. They are not
241
262
  intended for the end-user, but rather to pipe to a consuming app to process
242
263
  into a human readable form.
243
264
 
244
-
245
265
  ## Glossery of Fields
246
266
 
247
267
  ### count
@@ -321,10 +341,10 @@ On the other hand, `todo` means the test will be used in the future
321
341
  but implementation has not been completed. It serves as reminder to developers
322
342
  to write a missing test.
323
343
 
324
- ### tally
344
+ ### counts
325
345
 
326
- The footer MUST provide a tally for all status categories. This is like `count`
327
- but broken down into status groups.
346
+ The footer MUST provide counts for all status categories and the total.
347
+ This is like `count` in the suite entry but broken down into status groups.
328
348
 
329
349
  ### time
330
350
 
@@ -3,27 +3,35 @@ require 'tapout/parsers'
3
3
 
4
4
  module TapOut
5
5
 
6
- # Usable formats.
7
- FORMATS = %w{breakdown dotprogress html outline progressbar tap}
6
+ #
7
+ def self.trace
8
+ @trace
9
+ end
10
+
11
+ #
12
+ def self.trace=(depth)
13
+ @trace = depth.to_i
14
+ end
8
15
 
16
+ # Command line interface.
9
17
  #
10
18
  def self.cli(*argv)
11
19
  options = {}
12
20
  type = :modern
13
21
 
14
22
  parser = OptionParser.new do |opt|
15
- opt.banner = "tapout [options] [format]"
23
+ opt.banner = "tapout [options] [reporter]"
16
24
 
17
25
  opt.separator("\nOPTIONS:")
18
26
 
19
- #opt.on('--format', '-f FORMAT', 'Report format') do |fmt|
20
- # options[:format] = fmt
21
- #end
22
-
23
27
  #opt.on('-t', '--tap', 'Consume legacy TAP input') do |fmt|
24
28
  # type = :legacy
25
29
  #end
26
30
 
31
+ opt.on('--trace', '-t DEPTH', 'set backtrace depth') do |depth|
32
+ self.trace = depth
33
+ end
34
+
27
35
  opt.on('--no-color', 'Supress ANSI color codes') do
28
36
  $ansi = false # TODO: Is this correct?
29
37
  end
@@ -32,7 +40,7 @@ module TapOut
32
40
  $DEBUG = true
33
41
  end
34
42
 
35
- opt.separator("\nFORMATS:\n " + FORMATS.join("\n "))
43
+ opt.separator("\nREPORTERS:\n " + Reporters.index.keys.join("\n "))
36
44
  end
37
45
 
38
46
  parser.parse!(argv)
@@ -0,0 +1,46 @@
1
+ ---
2
+ authors:
3
+ - name: Thomas Sawyer
4
+ email: transfire@gmail.com
5
+ copyrights:
6
+ - holder: Thomas Sawyer
7
+ year: '2010'
8
+ license: BSD-2-Clause
9
+ replacements: []
10
+ conflicts: []
11
+ requirements:
12
+ - name: ansi
13
+ - name: json
14
+ - name: detroit
15
+ groups:
16
+ - build
17
+ development: true
18
+ - name: qed
19
+ groups:
20
+ - test
21
+ development: true
22
+ dependencies: []
23
+ repositories:
24
+ - uri: git://github.com/rubyworks/tapout.git
25
+ scm: git
26
+ name: upstream
27
+ resources:
28
+ home: http://rubyworks.github.com/tapout
29
+ code: http://github.com/rubyworks/tapout
30
+ load_path:
31
+ - lib
32
+ extra:
33
+ manifest: MANIFEST
34
+ source:
35
+ - PROFILE
36
+ alternatives: []
37
+ revision: 0
38
+ name: tapout
39
+ title: TapOut
40
+ version: 0.3.0
41
+ summary: Progressive TAP Harness
42
+ description: Tapout is a TAP consumer that can take any TAP, TAP-Y or TAP-J stream
43
+ and output it in a variety of useful formats.
44
+ organization: RubyWorks
45
+ created: '2010-12-23'
46
+ date: '2011-10-08'
@@ -156,7 +156,7 @@ module TapOut
156
156
  groups = @entries.group_by{ |e| e['status'] }
157
157
 
158
158
  entry = {}
159
- entry['type'] = 'tally'
159
+ entry['type'] = 'final'
160
160
  entry['counts'] = {
161
161
  'total' => @count,
162
162
  'pass' => (groups['pass'] || []).size,
@@ -0,0 +1,31 @@
1
+ # Borrowed methods from Ruby Facets.
2
+
3
+ class String
4
+
5
+ # Aligns each line n spaces.
6
+ def tab(n)
7
+ gsub(/^ */, ' ' * n)
8
+ end
9
+
10
+ # Preserves relative tabbing.
11
+ # The first non-empty line ends up with n spaces before nonspace.
12
+ def tabto(n)
13
+ if self =~ /^( *)\S/
14
+ indent(n - $1.length)
15
+ else
16
+ self
17
+ end
18
+ end
19
+
20
+ # Indent left or right by n spaces.
21
+ # (This used to be called #tab and aliased as #indent.)
22
+ def indent(n, c=' ')
23
+ if n >= 0
24
+ gsub(/^/, c * n)
25
+ else
26
+ gsub(/^#{Regexp.escape(c)}{0,#{-n}}/, "")
27
+ end
28
+ end
29
+
30
+ end
31
+
@@ -19,7 +19,7 @@ module TapOut
19
19
  while line = input.gets
20
20
  self << line
21
21
  end
22
- return @reporter.exit_code
22
+ @reporter.finalize
23
23
  end
24
24
 
25
25
  #
@@ -1,7 +1,11 @@
1
1
  require 'tapout/reporters/abstract'
2
- require 'tapout/reporters/breakdown'
3
- require 'tapout/reporters/dotprogress'
4
- require 'tapout/reporters/html'
5
- require 'tapout/reporters/outline'
6
- require 'tapout/reporters/progressbar'
7
- require 'tapout/reporters/tap'
2
+
3
+ require 'tapout/reporters/dot_reporter'
4
+ require 'tapout/reporters/pretty_reporter'
5
+ require 'tapout/reporters/turn_reporter'
6
+ require 'tapout/reporters/html_reporter'
7
+ require 'tapout/reporters/outline_reporter'
8
+ require 'tapout/reporters/progress_reporter'
9
+ require 'tapout/reporters/breakdown_reporter'
10
+ require 'tapout/reporters/tap_reporter'
11
+
@@ -22,9 +22,11 @@ module TapOut
22
22
  #
23
23
  # TODO: Simplify this class and have the sublcasses handle more of the load.
24
24
  class Abstract
25
+
25
26
  # When Abstract is inherited it saves a reference to it in `Reporters.index`.
26
27
  def self.inherited(subclass)
27
28
  name = subclass.name.split('::').last.downcase
29
+ name = name.chomp('reporter')
28
30
  Reporters.index[name] = subclass
29
31
  end
30
32
 
@@ -36,55 +38,16 @@ module TapOut
36
38
  @skipped = []
37
39
  @omitted = []
38
40
 
39
- @source = {}
40
- @previous_case = nil
41
- @exit_code = 0 # assume passing
41
+ @case_stack = []
42
+ @source = {}
43
+ @exit_code = 0 # assume passing
42
44
  end
43
45
 
44
- # Exit code.
45
- def exit_code
46
+ # When all is said and done.
47
+ def finalize
46
48
  @exit_code
47
49
  end
48
50
 
49
- #
50
- def <<(entry)
51
- handle(entry)
52
- end
53
-
54
- # Handler method. This dispatches a given entry to the appropriate
55
- # report methods.
56
- def handle(entry)
57
- case entry['type']
58
- when 'suite'
59
- start_suite(entry)
60
- when 'case'
61
- finish_case(@previous_case) if @previous_case
62
- @previous_case = entry
63
- start_case(entry)
64
- when 'note'
65
- note(entry)
66
- when 'test'
67
- test(entry)
68
- case entry['status']
69
- when 'pass'
70
- pass(entry)
71
- when 'fail'
72
- @exit_code = -1
73
- fail(entry)
74
- when 'error'
75
- @exit_code = -1
76
- err(entry)
77
- when 'omit'
78
- omit(entry)
79
- when 'todo', 'skip', 'pending'
80
- skip(entry)
81
- end
82
- when 'tally'
83
- finish_case(@previous_case) if @previous_case
84
- finish_suite(entry)
85
- end
86
- end
87
-
88
51
  # Handle header.
89
52
  def start_suite(entry)
90
53
  end
@@ -93,12 +56,8 @@ module TapOut
93
56
  def start_case(entry)
94
57
  end
95
58
 
96
- # Handle an arbitray note.
97
- def note(entry)
98
- end
99
-
100
59
  # Handle test. This is run before the status handlers.
101
- def test(entry)
60
+ def start_test(entry)
102
61
  end
103
62
 
104
63
  # Handle test with pass status.
@@ -112,7 +71,7 @@ module TapOut
112
71
  end
113
72
 
114
73
  # Handle test with error status.
115
- def err(entry)
74
+ def error(entry)
116
75
  @raised << entry
117
76
  end
118
77
 
@@ -126,16 +85,79 @@ module TapOut
126
85
  @skipped << entry
127
86
  end
128
87
 
88
+ # Handle an arbitray note.
89
+ def note(entry)
90
+ end
91
+
92
+ # Handle running tally.
93
+ def tally(entry)
94
+ end
95
+
96
+ # When a test unit is complete.
97
+ def finish_test(entry)
98
+ end
99
+
129
100
  # When a test case is complete.
130
101
  def finish_case(entry)
131
102
  end
132
103
 
133
- # Handle footer.
104
+ # Handle final entry.
134
105
  def finish_suite(entry)
135
106
  end
136
107
 
137
- # TODO: get the tally's from the footer entry ?
138
- def tally(entry)
108
+ # -- H A N D L E R --
109
+
110
+ #
111
+ def <<(entry)
112
+ handle(entry)
113
+ end
114
+
115
+ # Handler method. This dispatches a given entry to the appropriate
116
+ # report methods.
117
+ def handle(entry)
118
+ case entry['type']
119
+ when 'suite'
120
+ start_suite(entry)
121
+ when 'case'
122
+ complete_cases(entry)
123
+ @case_stack << entry
124
+ start_case(entry)
125
+ when 'note'
126
+ note(entry)
127
+ when 'test'
128
+ start_test(entry)
129
+ case entry['status']
130
+ when 'pass'
131
+ pass(entry)
132
+ when 'fail'
133
+ @exit_code = -1
134
+ fail(entry)
135
+ when 'error'
136
+ @exit_code = -1
137
+ error(entry)
138
+ when 'omit'
139
+ omit(entry)
140
+ when 'todo', 'skip', 'pending'
141
+ skip(entry)
142
+ end
143
+ finish_test(entry)
144
+ when 'tally'
145
+ tally(entry)
146
+ when 'final'
147
+ complete_cases
148
+ finish_suite(entry)
149
+ end
150
+ end
151
+
152
+ # Get the exit code.
153
+ def exit_code
154
+ @exit_code
155
+ end
156
+
157
+ # Generate a tally message given a tally or final entry.
158
+ #
159
+ # @return [String] tally message
160
+ def tally_message(entry)
139
161
  total = @passed.size + @failed.size + @raised.size #+ @skipped.size + @omitted.size
140
162
 
141
163
  if entry['counts']
@@ -174,7 +196,9 @@ module TapOut
174
196
  end
175
197
  end
176
198
 
199
+ # Used to clean-up backtrace.
177
200
  #
201
+ # TODO: Use Rubinius global system instead.
178
202
  INTERNALS = /(lib|bin)#{Regexp.escape(File::SEPARATOR)}tapout/
179
203
 
180
204
  # Clean the backtrace of any reference to ko/ paths and code.
@@ -270,6 +294,19 @@ module TapOut
270
294
  returnf source_file, source_line
271
295
  end
272
296
 
297
+ #
298
+ def complete_cases(case_entry=nil)
299
+ if case_entry
300
+ while @case_stack.last and @case_stack.last['level'].to_i >= case_entry['level'].to_i
301
+ finish_case(@case_stack.pop)
302
+ end
303
+ else
304
+ while @case_stack.last
305
+ finish_case(@case_stack.pop)
306
+ end
307
+ end
308
+ end
309
+
273
310
  end#class Abstract
274
311
 
275
312
  end#module Reporters