rscm-accurev 0.0 → 0.0.1
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/Rakefile +7 -76
- data/TODO +3 -17
- data/lib/rscm/accurev.rb +1 -13
- data/lib/rscm/scm/accurev/#command.rb# +95 -0
- data/lib/rscm/scm/accurev/api.rb +77 -258
- data/lib/rscm/scm/accurev/command.rb +40 -97
- data/lib/rscm/scm/accurev/filterio.rb +4 -6
- data/lib/rscm/scm/accurev/xml.rb +11 -199
- data/test/t_command.rb +11 -59
- data/test/t_load.rb +0 -1
- data/test/t_scrubio.rb +6 -1
- data/{apitest.rb → test.rb} +0 -1
- data/{test/eg/update-newwksp.xml → testing.log} +138 -0
- metadata +15 -57
- data/STATUS +0 -63
- data/bumprelease.sh +0 -13
- data/lib/rscm/scm/accurev/api.rb.mine +0 -382
- data/lib/rscm/scm/accurev/api.rb.r263 +0 -364
- data/lib/rscm/scm/accurev/api.rb.r265 +0 -393
- data/lib/rscm/scm/accurev/exception.rb +0 -38
- data/lib/test/unit/ui/xml/testrunner.rb +0 -165
- data/lib/test/unit/ui/xml/xmltestrunner.xslt +0 -79
- data/test/coverage/analyzer.rb +0 -127
- data/test/coverage/c_loader.rb +0 -34
- data/test/coverage/cover.rb +0 -91
- data/test/coverage/coverage_loader.rb +0 -21
- data/test/coverage/coveragetask.rb +0 -38
- data/test/coverage/index_tmpl.html +0 -42
- data/test/coverage/template.html +0 -36
- data/test/eg/ac-files.xml +0 -172
- data/test/eg/ac-pop.txt +0 -195
- data/test/eg/files-various-states.xml +0 -188
- data/test/eg/hist-oneweek-all.xml +0 -1483
- data/test/eg/hist-oneweek-external.xml +0 -246
- data/test/eg/hist-oneweek-promotes.xml +0 -1092
- data/test/eg/info.txt +0 -14
- data/test/eg/stat-a-various.xml +0 -1789
- data/test/eg/stat-m.xml +0 -13
- data/test/eg/stat-overlap.xml +0 -13
- data/test/eg/stat-x.xml +0 -20
- data/test/eg/update-i-mods-and-updates-and-overlap.xml +0 -73
- data/test/eg/update-i-nochanges.xml +0 -8
- data/test/eg/update-i-stale.xml +0 -0
- data/test/eg/update-i-updates.xml +0 -125
- data/test/eg/update-nochanges.xml +0 -7
- data/test/eg/update-stale.xml +0 -12
- data/test/eg/update-updates.xml +0 -147
- data/test/t_api.rb +0 -163
- data/test/t_xmlmapper.rb +0 -75
@@ -1,393 +0,0 @@
|
|
1
|
-
# -*- ruby -*-
|
2
|
-
#
|
3
|
-
# = api.rb
|
4
|
-
#
|
5
|
-
# API for interacting with accurev workspaces.
|
6
|
-
#
|
7
|
-
# Includes:
|
8
|
-
#
|
9
|
-
# * API
|
10
|
-
#
|
11
|
-
require 'stringio'
|
12
|
-
require 'rscm/base'
|
13
|
-
require 'rscm/path_converter'
|
14
|
-
require 'rexml/document'
|
15
|
-
require 'rscm/scm/accurev/xml'
|
16
|
-
require 'rscm/scm/accurev/filterio'
|
17
|
-
require 'rscm/scm/accurev/command'
|
18
|
-
require 'rscm/scm/accurev/exception'
|
19
|
-
|
20
|
-
# need to define module within module before you can use module X::Y
|
21
|
-
module RSCM; module Accurev; end; end
|
22
|
-
|
23
|
-
module RSCM::Accurev
|
24
|
-
|
25
|
-
#
|
26
|
-
# RSCM implementation for Accurev (http://www.accurev.com).
|
27
|
-
#
|
28
|
-
# Requires an accurev cli executable on the path (see also
|
29
|
-
# RSCM::Accurev::Command), and the correct environment
|
30
|
-
# configuration for ac server/principal/password.
|
31
|
-
#
|
32
|
-
# ---
|
33
|
-
#
|
34
|
-
# === Example
|
35
|
-
#
|
36
|
-
# api = RSCM::Accurev::API.new( "./ws/proj-1", "proj", "proj-1" )
|
37
|
-
# api.checkout() each do |file|
|
38
|
-
# puts "Updated #{file}..."
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
class API < RSCM::Base
|
42
|
-
register self
|
43
|
-
|
44
|
-
ann :description => "Accurev Depot"
|
45
|
-
attr_accessor :depot
|
46
|
-
|
47
|
-
ann :description => "Backing Stream (autodetected)"
|
48
|
-
attr_accessor :backing_stream
|
49
|
-
|
50
|
-
# If workspace stream is nil (the default), checkout/update will be
|
51
|
-
# done using `accurev pop`. This is faster and more appropriate for
|
52
|
-
# read-only use; however a workspace is required for commits.
|
53
|
-
ann :description => "Workspace Stream"
|
54
|
-
attr_accessor :workspace_stream
|
55
|
-
|
56
|
-
# [defined in Base]
|
57
|
-
# ann :description => "Filesystem Path to Workspace"
|
58
|
-
# attr_accessor :checkout_dir
|
59
|
-
|
60
|
-
ann :description => "Overwrite Mode: if true, co overwrites existing"
|
61
|
-
attr_accessor :overwrite
|
62
|
-
|
63
|
-
def initialize(checkout_dir=nil, backing_stream=nil, workspace_stream=nil)
|
64
|
-
@depot = nil # will be pulled from files cmd output
|
65
|
-
@workspace_stream = workspace_stream
|
66
|
-
@backing_stream = backing_stream
|
67
|
-
@checkout_dir = checkout_dir
|
68
|
-
@overwrite = false
|
69
|
-
end
|
70
|
-
|
71
|
-
def name()
|
72
|
-
return "Accurev"
|
73
|
-
end
|
74
|
-
|
75
|
-
# Accurev operations are atomic: returns true.
|
76
|
-
def transactional?
|
77
|
-
return true
|
78
|
-
end
|
79
|
-
|
80
|
-
# "Adds +relative_filename+ to the working copy."
|
81
|
-
def add( relative_filename )
|
82
|
-
raise "XXX implement me"
|
83
|
-
end
|
84
|
-
|
85
|
-
def edit( relative_filename )
|
86
|
-
# NOP - not required for ac
|
87
|
-
end
|
88
|
-
|
89
|
-
# "Returns a Revisions object for the period specified ... (inclusive)."
|
90
|
-
#
|
91
|
-
# list txns (promotes to bs) from hist within the period
|
92
|
-
#
|
93
|
-
def revisions( from_identifier, to_identifier=Time.infinity )
|
94
|
-
raise "XXX implement me"
|
95
|
-
end
|
96
|
-
|
97
|
-
# default impl depends on a correct impl of revisions()
|
98
|
-
# def uptodate?( identifier=nil )
|
99
|
-
#
|
100
|
-
# end
|
101
|
-
|
102
|
-
# def checked_out? - base
|
103
|
-
|
104
|
-
# accurev actually does have triggers, but I haven't implemented that yet
|
105
|
-
def supports_trigger?
|
106
|
-
false
|
107
|
-
end
|
108
|
-
|
109
|
-
# def diff() XXX
|
110
|
-
|
111
|
-
|
112
|
-
# --- ac specific
|
113
|
-
|
114
|
-
def ac_files( relative_path )
|
115
|
-
cmd = Command.instance
|
116
|
-
ret = []
|
117
|
-
with_working_dir( @checkout_dir ) do
|
118
|
-
acresponse = cmd.accurev( "files", relative_path )
|
119
|
-
acresponse['element'].each do |fd|
|
120
|
-
yield fd if block_given?
|
121
|
-
ret << fd
|
122
|
-
end
|
123
|
-
end
|
124
|
-
return ret
|
125
|
-
end
|
126
|
-
|
127
|
-
# yeilds the TransactionData objects for the given time period
|
128
|
-
# (promotes only)
|
129
|
-
def ac_hist( from, to=Time.infinite )
|
130
|
-
cmd = Command.instance
|
131
|
-
lower = from.to_accurev
|
132
|
-
upper = "now"
|
133
|
-
unless to == Time.infinite
|
134
|
-
upper = to.to_accurev
|
135
|
-
end
|
136
|
-
with_working_dir( self.co_filepath ) do
|
137
|
-
acresponse = cmd.accurev( "hist",
|
138
|
-
"-t", "'#{upper}-#{lower}'",
|
139
|
-
"-k", "promote"
|
140
|
-
)
|
141
|
-
ret = []
|
142
|
-
acresponse['transaction'].each do |txn|
|
143
|
-
ret << txn
|
144
|
-
yield txn if block_given?
|
145
|
-
end
|
146
|
-
return ret
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def ac_keep( files=[], message="" )
|
151
|
-
raise "XXX implement me"
|
152
|
-
end
|
153
|
-
|
154
|
-
def ac_promote( files=[], message="" )
|
155
|
-
raise "XXX implement me"
|
156
|
-
end
|
157
|
-
|
158
|
-
def ac_update( relative_path="." )
|
159
|
-
d = accurev( "update", relative_path )
|
160
|
-
if xxx_error_stale
|
161
|
-
raise StaleWorkspaceError.new( "#{relative_path} is stale -- keep/anchor all changes and re-update" )
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def ac_purge( files=[] )
|
166
|
-
raise "XXX implement me"
|
167
|
-
end
|
168
|
-
|
169
|
-
def ac_revert( files=[] )
|
170
|
-
raise "XXX implement me"
|
171
|
-
end
|
172
|
-
|
173
|
-
def ac_move( current_file, new_file )
|
174
|
-
raise "XXX implement me"
|
175
|
-
end
|
176
|
-
|
177
|
-
#
|
178
|
-
# Performs an "accurev info" command in the workspace.
|
179
|
-
# Returns a map of
|
180
|
-
#
|
181
|
-
# ac info: shows eg, backing stream
|
182
|
-
# but doesn't support -fx!
|
183
|
-
#
|
184
|
-
def ac_info()
|
185
|
-
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
186
|
-
unless File.exists?( co )
|
187
|
-
raise AccurevException.new( "Checkout dir #{co} does not exist" )
|
188
|
-
end
|
189
|
-
info = {}
|
190
|
-
with_working_dir( co ) do
|
191
|
-
cmd = Command.instance
|
192
|
-
io = StringIO.new( cmd.accurev_nofx( "info" ) )
|
193
|
-
io.each_line do |line|
|
194
|
-
next unless line =~ /\S/
|
195
|
-
if line =~ /^(.*?):\s+(.*)$/
|
196
|
-
info[$1] = $2
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
return info
|
201
|
-
end
|
202
|
-
|
203
|
-
# ac mkws
|
204
|
-
# -b orbitz-host-gt3-0-impl
|
205
|
-
# -w orbitz-host-gt3-0-impl-test2_gfast
|
206
|
-
# -l `pwd`
|
207
|
-
# - does not support fx (argh!@)
|
208
|
-
# - does not pop
|
209
|
-
#
|
210
|
-
|
211
|
-
# diff: /usr/local/bin/acdiff (!) --fx
|
212
|
-
# (after an ac cat on the backed file)
|
213
|
-
# (eg, no in-process diffing ala cvs diff)
|
214
|
-
# lists modified lines in xml
|
215
|
-
|
216
|
-
#
|
217
|
-
# "Checks out or updates[!] contents from a central SCM
|
218
|
-
# to +checkout_dir+ - a local working copy."
|
219
|
-
#
|
220
|
-
# "The +to_identifier+ parameter may be optionally specified to
|
221
|
-
# obtain files up to a particular time or label."
|
222
|
-
#
|
223
|
-
# For accurev, this:
|
224
|
-
# * checks to see if +@checkout_dir+ exists and appears checked out.
|
225
|
-
# If it's already checked out, this calls +update()+. If
|
226
|
-
# +@checkout_dir+ exists and +to_identifier+ is given, an
|
227
|
-
# exception is raised.
|
228
|
-
# * otherwise, this creates a new workspace stream and populates it
|
229
|
-
# at +@checkout_dir+.
|
230
|
-
#
|
231
|
-
# This both returns and yields a list of updated files.
|
232
|
-
# Only updated files are returned, not directories.
|
233
|
-
#
|
234
|
-
# Current, ac_update returns both files and directories, including
|
235
|
-
# deleted files.
|
236
|
-
#
|
237
|
-
def checkout( to_identifier=Time.infinite )
|
238
|
-
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
239
|
-
if @backing_stream.nil?
|
240
|
-
self.attempt_init_from_info()
|
241
|
-
end
|
242
|
-
if @workspace_stream.nil?
|
243
|
-
self.checkout_pop()
|
244
|
-
else
|
245
|
-
unless File.exists?( co )
|
246
|
-
# create new workspace
|
247
|
-
self.checkout_workspace()
|
248
|
-
end
|
249
|
-
# update workspace
|
250
|
-
self.update( to_identifier )
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def checkout_pop()
|
255
|
-
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
256
|
-
raise "A backing stream is required" if @backing_stream.nil?
|
257
|
-
raise "A working stream may not be given" unless @working_stream.nil?
|
258
|
-
# for `accurev pop`: remove and re-pop the checkout copy
|
259
|
-
if File.exists?( co )
|
260
|
-
unless @overwrite
|
261
|
-
raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)"
|
262
|
-
end
|
263
|
-
rm_rf( co )
|
264
|
-
end
|
265
|
-
mkdir(co)
|
266
|
-
with_working_dir( co ) do
|
267
|
-
cmd = Command.instance
|
268
|
-
pop_out = cmd.accurev_nofx("pop",
|
269
|
-
"-R",
|
270
|
-
"-v", @backing_stream,
|
271
|
-
"-L", ".", ".")
|
272
|
-
elems = []
|
273
|
-
popio = StringIO.new( pop_out )
|
274
|
-
popio.each_line do |line|
|
275
|
-
if line =~ /^Populating element \/.\/(.*)$/
|
276
|
-
loc = $1
|
277
|
-
elems << loc
|
278
|
-
yield loc if block_given?
|
279
|
-
end
|
280
|
-
end
|
281
|
-
return elems
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
def checkout_workspace()
|
286
|
-
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
287
|
-
raise "A backing stream is required" if @backing_stream.nil?
|
288
|
-
raise "A workspace is required" if @working_stream.nil?
|
289
|
-
if File.exist?( co ) and !@overwrite
|
290
|
-
raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)"
|
291
|
-
end
|
292
|
-
cmd = Command.instance
|
293
|
-
mkws_out = cmd.accurev_nofx( "mkws",
|
294
|
-
"-b", @backing_stream,
|
295
|
-
"-w", @workspace_stream,
|
296
|
-
"-l", co )
|
297
|
-
# kinda sucks:
|
298
|
-
if ( mkws_out =~ /already exists/ )
|
299
|
-
raise AccurevException.new( "Failed to checkout", mkws_out )
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
def update( to_identifier=Time.infinite )
|
304
|
-
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
305
|
-
unless File.exists?( co )
|
306
|
-
raise AccurevException.new( "Workspace does not exist!" )
|
307
|
-
end
|
308
|
-
updated = []
|
309
|
-
with_working_dir( co ) do
|
310
|
-
cmd = Command.instance
|
311
|
-
acresponse = cmd.accurev( "update" )
|
312
|
-
if acresponse.error
|
313
|
-
if acresponse.error =~ /workspace have been modified/
|
314
|
-
raise StaleWorkspaceException.new( "Workspace stale",
|
315
|
-
acresponse.error )
|
316
|
-
else
|
317
|
-
# some other update problem
|
318
|
-
raise AccurevException.new( "Error on update", acresponse.error )
|
319
|
-
end
|
320
|
-
end
|
321
|
-
if acresponse['element']
|
322
|
-
acresponse['element'].each do |up|
|
323
|
-
# "ac update" on a new workspace yields element locations
|
324
|
-
# with leading "/"s, which should be removed to get a proper
|
325
|
-
# relative path:
|
326
|
-
loc = up.location.sub( /^\//, "" )
|
327
|
-
yield loc if block_given?
|
328
|
-
updated << loc
|
329
|
-
end
|
330
|
-
end
|
331
|
-
end
|
332
|
-
return updated
|
333
|
-
end
|
334
|
-
|
335
|
-
# --- internals
|
336
|
-
|
337
|
-
# status flag mappings for "stat", "file" commands
|
338
|
-
STATUSES = {
|
339
|
-
'(backed)' => :backed,
|
340
|
-
'(external)' => :external,
|
341
|
-
'(modified)' => :modified,
|
342
|
-
'(kept)' => :kept,
|
343
|
-
'(defunct)' => :defunct,
|
344
|
-
'(missing)' => :missing,
|
345
|
-
'(stranded)' => :stranded,
|
346
|
-
'(overlap)' => :overlap
|
347
|
-
}
|
348
|
-
|
349
|
-
# private
|
350
|
-
|
351
|
-
# psuedo-accessor (cached)
|
352
|
-
def co_filepath
|
353
|
-
if @co_filepath.nil?
|
354
|
-
@co_filepath = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
355
|
-
end
|
356
|
-
return @co_filepath
|
357
|
-
end
|
358
|
-
|
359
|
-
#
|
360
|
-
# Runs an `ac info` command in +@checkout_dir+, and tries to
|
361
|
-
# set +@backing_stream+ and +@workspace_stream+ from the output.
|
362
|
-
#
|
363
|
-
def attempt_init_from_info()
|
364
|
-
if File.exists?( self.co_filepath )
|
365
|
-
info = self.ac_info
|
366
|
-
if info.has_key?( "Basis" )
|
367
|
-
@backing_stream = info["Basis"]
|
368
|
-
end
|
369
|
-
if info.has_key?( "ws/ref" )
|
370
|
-
@workspace_stream = info["ws/ref"]
|
371
|
-
end
|
372
|
-
end
|
373
|
-
end
|
374
|
-
|
375
|
-
# Takes a status flags line (eg, "(modified)(kept)")
|
376
|
-
# and returns a list of status flags.
|
377
|
-
def map_status( status_line )
|
378
|
-
l = status_line.split( " " ).map {|x| x.trim}
|
379
|
-
end
|
380
|
-
|
381
|
-
end
|
382
|
-
|
383
|
-
end
|
384
|
-
|
385
|
-
class Time
|
386
|
-
def to_accurev
|
387
|
-
self.strftime( "%Y/%m/%d %H:%M:%S" )
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
#
|
392
|
-
# Copyright (c) 2005 Gregory D. Fast <gdf@speakeasy.net>
|
393
|
-
#
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# -*- ruby -*-
|
2
|
-
#
|
3
|
-
# = exception.rb
|
4
|
-
#
|
5
|
-
# Exception classes for RSCM::Accurev
|
6
|
-
#
|
7
|
-
# Includes:
|
8
|
-
#
|
9
|
-
# * AccurevException
|
10
|
-
#
|
11
|
-
# * StaleWorkspaceException
|
12
|
-
#
|
13
|
-
module RSCM
|
14
|
-
module Accurev
|
15
|
-
|
16
|
-
#
|
17
|
-
# General exception class for errors processing commands.
|
18
|
-
#
|
19
|
-
# @attr error_msg Error message output by accurev.
|
20
|
-
#
|
21
|
-
class AccurevException < Exception
|
22
|
-
attr_reader :error_msg
|
23
|
-
def initialize( msg, error_msg=nil )
|
24
|
-
super( "#{msg}: #{error_msg}" )
|
25
|
-
@error_msg = error_msg
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
#
|
30
|
-
# Exception thrown when an update is performed
|
31
|
-
# on a workspace with unkept/unanchored modifications.
|
32
|
-
# Accurev requires that all modifications be handled before
|
33
|
-
# an update is performed.
|
34
|
-
#
|
35
|
-
class StaleWorkspaceException < AccurevException; end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
@@ -1,165 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'test/unit/ui/testrunnermediator'
|
4
|
-
require 'test/unit/ui/testrunnerutilities'
|
5
|
-
require 'test/unit/ui/console/testrunner'
|
6
|
-
require 'test/unit/autorunner'
|
7
|
-
require 'rexml/document'
|
8
|
-
|
9
|
-
module Test
|
10
|
-
module Unit
|
11
|
-
module UI
|
12
|
-
module XML
|
13
|
-
|
14
|
-
#
|
15
|
-
# XML::TestRunner - generate xml output for test results
|
16
|
-
#
|
17
|
-
# Example use:
|
18
|
-
#
|
19
|
-
# $ ruby -rtest/unit/ui/xml/testrunner test/test_1.rb --runner=xml
|
20
|
-
#
|
21
|
-
# By default, XML::TestRunner will output to stdout.
|
22
|
-
# You can set the environment variable $XMLTEST_OUTPUT to
|
23
|
-
# a filename to send the output to that file.
|
24
|
-
#
|
25
|
-
# The summary file created by this testrunner is XML, but
|
26
|
-
# this module also includes a stylesheet
|
27
|
-
# (test/unit/ui/xml/xmltestrunner.xslt) which converts it to
|
28
|
-
# HTML. Copy the XSLT file into the same directory as the
|
29
|
-
# test results file, and open the results file with a browser.
|
30
|
-
#
|
31
|
-
# ---
|
32
|
-
#
|
33
|
-
# (todo: use with rake)
|
34
|
-
#
|
35
|
-
class TestRunner < Test::Unit::UI::Console::TestRunner
|
36
|
-
|
37
|
-
def initialize( suite, output_level )
|
38
|
-
super( suite )
|
39
|
-
if ENV['XMLTEST_OUTPUT']
|
40
|
-
fn = ENV['XMLTEST_OUTPUT']
|
41
|
-
puts "Writing to #{fn}"
|
42
|
-
@io = File.open( fn, "w" )
|
43
|
-
@using_stdout = false
|
44
|
-
else
|
45
|
-
puts "Writing to stdout (along with everyone else...)"
|
46
|
-
@io = STDOUT
|
47
|
-
@using_stdout = true
|
48
|
-
end
|
49
|
-
create_document()
|
50
|
-
end
|
51
|
-
|
52
|
-
def create_document()
|
53
|
-
@doc = REXML::Document.new()
|
54
|
-
@doc << REXML::XMLDecl.new()
|
55
|
-
|
56
|
-
pi = REXML::Instruction.new(
|
57
|
-
"xml-stylesheet",
|
58
|
-
"type='text/xsl' href='xmltestrunner.xslt' "
|
59
|
-
)
|
60
|
-
@doc << pi
|
61
|
-
|
62
|
-
e = REXML::Element.new( "testsuite" )
|
63
|
-
e.attributes['rundate'] = Time.now
|
64
|
-
@doc << e
|
65
|
-
end
|
66
|
-
|
67
|
-
def to_s
|
68
|
-
@doc.to_s
|
69
|
-
end
|
70
|
-
|
71
|
-
def start
|
72
|
-
@current_test = nil
|
73
|
-
# setup_mediator
|
74
|
-
@mediator = TestRunnerMediator.new( @suite )
|
75
|
-
suite_name = @suite.to_s
|
76
|
-
if @suite.kind_of?(Module)
|
77
|
-
suite_name = @suite.name
|
78
|
-
end
|
79
|
-
@doc.root.attributes['name'] = suite_name
|
80
|
-
# attach_to_mediator - define callbacks
|
81
|
-
@mediator.add_listener( TestResult::FAULT,
|
82
|
-
&method(:add_fault) )
|
83
|
-
@mediator.add_listener( TestRunnerMediator::STARTED,
|
84
|
-
&method(:started) )
|
85
|
-
@mediator.add_listener( TestRunnerMediator::FINISHED,
|
86
|
-
&method(:finished) )
|
87
|
-
@mediator.add_listener( TestCase::STARTED,
|
88
|
-
&method(:test_started) )
|
89
|
-
@mediator.add_listener( TestCase::FINISHED,
|
90
|
-
&method(:test_finished) )
|
91
|
-
# return start_mediator
|
92
|
-
return @mediator.run_suite
|
93
|
-
end
|
94
|
-
|
95
|
-
# callbacks
|
96
|
-
|
97
|
-
def add_fault( fault )
|
98
|
-
##STDERR.puts "Fault:"
|
99
|
-
@faults << fault
|
100
|
-
e = REXML::Element.new( "fault" )
|
101
|
-
e << REXML::CData.new( fault.long_display )
|
102
|
-
@current_test << e
|
103
|
-
end
|
104
|
-
|
105
|
-
def started( result )
|
106
|
-
#STDERR.puts "Started"
|
107
|
-
@result = result
|
108
|
-
end
|
109
|
-
|
110
|
-
def finished( elapsed_time )
|
111
|
-
#STDERR.puts "Finished"
|
112
|
-
res = REXML::Element.new( "result" )
|
113
|
-
summ = REXML::Element.new( "summary" )
|
114
|
-
summ.text = @result
|
115
|
-
res << summ
|
116
|
-
# @result is a Test::Unit::TestResults
|
117
|
-
res.attributes['passed'] = @result.passed?
|
118
|
-
res.attributes['testcount'] = @result.run_count
|
119
|
-
res.attributes['assertcount'] = @result.assertion_count
|
120
|
-
res.attributes['failures'] = @result.failure_count
|
121
|
-
res.attributes['errors'] = @result.error_count
|
122
|
-
@doc.root << res
|
123
|
-
|
124
|
-
e = REXML::Element.new( "elapsed-time" )
|
125
|
-
e.text = elapsed_time
|
126
|
-
@doc.root << e
|
127
|
-
@io.puts( @doc.to_s )
|
128
|
-
|
129
|
-
unless @using_stdout
|
130
|
-
puts @result
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_started( name )
|
135
|
-
#STDERR.puts "Test: #{name} started"
|
136
|
-
e = REXML::Element.new( "test" )
|
137
|
-
e.attributes['name'] = name
|
138
|
-
#e.attributes['status'] = "failed"
|
139
|
-
@doc.root << e
|
140
|
-
@current_test = e
|
141
|
-
end
|
142
|
-
|
143
|
-
def test_finished( name )
|
144
|
-
#STDERR.puts "Test: #{name} finished"
|
145
|
-
# find //test[@name='name']
|
146
|
-
@current_test = nil
|
147
|
-
end
|
148
|
-
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
# "plug in" xmltestrunner into autorunner's list of known runners
|
156
|
-
# This enables the "--runner=xml" commandline option.
|
157
|
-
Test::Unit::AutoRunner::RUNNERS[:xml] = proc do |r|
|
158
|
-
require 'test/unit/ui/xml/testrunner'
|
159
|
-
Test::Unit::UI::XML::TestRunner
|
160
|
-
end
|
161
|
-
|
162
|
-
if __FILE__ == $0
|
163
|
-
Test::Unit::UI::XML::TestRunner.start_command_line_test
|
164
|
-
end
|
165
|
-
|
@@ -1,79 +0,0 @@
|
|
1
|
-
<?xml version="1.0"?>
|
2
|
-
<xsl:stylesheet
|
3
|
-
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
4
|
-
>
|
5
|
-
|
6
|
-
<xsl:output method="html" />
|
7
|
-
|
8
|
-
<xsl:template match="/testsuite">
|
9
|
-
<html>
|
10
|
-
<head>
|
11
|
-
<title>Test Suite Results for <xsl:value-of select="@name" /></title>
|
12
|
-
<style>
|
13
|
-
.error { color: #ff0000; }
|
14
|
-
.eresult {
|
15
|
-
background: #ffcccc;
|
16
|
-
color: #ff0000;
|
17
|
-
}
|
18
|
-
h1,h2 {
|
19
|
-
background: #cccccc;
|
20
|
-
color: #000055;
|
21
|
-
border: 1px dotted black;
|
22
|
-
}
|
23
|
-
</style>
|
24
|
-
</head>
|
25
|
-
<body>
|
26
|
-
<h1>Test Suite Results</h1>
|
27
|
-
|
28
|
-
<p>Results for: <xsl:value-of select="@name" /></p>
|
29
|
-
|
30
|
-
<p>
|
31
|
-
Test suite run at: <b><xsl:value-of select="@rundate" /></b>
|
32
|
-
</p>
|
33
|
-
|
34
|
-
<h2>Summary</h2>
|
35
|
-
|
36
|
-
<p>
|
37
|
-
<xsl:if test="result[@passed = 'false']">
|
38
|
-
<xsl:attribute name="class">error</xsl:attribute>
|
39
|
-
</xsl:if>
|
40
|
-
<xsl:value-of select="result/summary/text()" />
|
41
|
-
</p>
|
42
|
-
<p>
|
43
|
-
Elapsed time: <xsl:value-of select="elapsed-time/text()" />
|
44
|
-
</p>
|
45
|
-
|
46
|
-
<table border="1">
|
47
|
-
<tr>
|
48
|
-
<th>Case</th>
|
49
|
-
<th>Result</th>
|
50
|
-
</tr>
|
51
|
-
<xsl:for-each select="test">
|
52
|
-
<tr>
|
53
|
-
<td>
|
54
|
-
<xsl:if test="fault/text()">
|
55
|
-
<xsl:attribute name="class">error</xsl:attribute>
|
56
|
-
</xsl:if>
|
57
|
-
<xsl:value-of select="@name" />
|
58
|
-
</td>
|
59
|
-
<td>
|
60
|
-
<xsl:choose>
|
61
|
-
<xsl:when test="fault/text()">
|
62
|
-
<xsl:attribute name="class">eresult</xsl:attribute>
|
63
|
-
<pre>
|
64
|
-
<xsl:value-of select="fault/text()" />
|
65
|
-
</pre>
|
66
|
-
</xsl:when>
|
67
|
-
<xsl:otherwise>
|
68
|
-
(pass)
|
69
|
-
</xsl:otherwise>
|
70
|
-
</xsl:choose>
|
71
|
-
</td>
|
72
|
-
</tr>
|
73
|
-
</xsl:for-each>
|
74
|
-
</table>
|
75
|
-
</body>
|
76
|
-
</html>
|
77
|
-
</xsl:template>
|
78
|
-
|
79
|
-
</xsl:stylesheet>
|