rutema 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.
@@ -0,0 +1,599 @@
1
+ # Copyright (c) 2007 Vassilis Rizopoulos. All rights reserved.
2
+
3
+ require 'rexml/document'
4
+
5
+ require 'rutema/specification'
6
+ require 'rutema/configuration'
7
+
8
+ require 'rubygems'
9
+ require 'highline'
10
+ require 'mailfactory'
11
+ require 'patir/command'
12
+
13
+ module Rutema
14
+ VERSION_MAJOR=0
15
+ VERSION_MINOR=1
16
+ #Is raised when an error is found in a specification
17
+ class ParserError<RuntimeError
18
+ end
19
+
20
+ #Base class that bombs out when used....
21
+ class SpecificationParser
22
+ def parse_specification
23
+ raise ParserError,"not implemented. You should derive a parser implementation from SpecificationParser!"
24
+ end
25
+ end
26
+
27
+ class BaseXMLParser<SpecificationParser
28
+ ELEM_SPEC="specification"
29
+ ELEM_DESC="specification/description"
30
+ ELEM_TITLE="specification/title"
31
+ ELEM_SCENARIO="specification/scenario"
32
+ ELEM_REQ="requirement"
33
+ def initialize params
34
+ @logger=params[:logger]
35
+ @logger||=Patir.setup_logger
36
+ end
37
+ #Parses __param__ and returns the Rutema::TestSpecification instance
38
+ #
39
+ #param can be the filename of the specification or the contents of that file.
40
+ #
41
+ #Will throw ParserError if something goes wrong
42
+ def parse_specification param
43
+ @logger.debug("Loading #{param}")
44
+ begin
45
+ file=false
46
+ if File.exists?(param)
47
+ #read the file
48
+ txt=File.read(param)
49
+ file=true
50
+ else
51
+ #try to parse the parameter
52
+ txt=param
53
+ end
54
+ spec=parse_case(txt)
55
+ spec.filename=""
56
+ spec.filename=param if file
57
+ raise "Missing required attribute 'name' in specification element" unless spec.has_name? && !spec.name.empty?
58
+ return spec
59
+ rescue
60
+ @logger.debug($!)
61
+ raise ParserError,"Error loading #{param}: #{$!.message}"
62
+ end
63
+ end
64
+
65
+ private
66
+ #Parses the XML specification of a testcase and creates the corresponding TestSpecification instance
67
+ def parse_case xmltxt
68
+ #the testspec to return
69
+ spec=TestSpecification.new
70
+ #read the test spec
71
+ xmldoc=REXML::Document.new( xmltxt )
72
+ #validate it
73
+ validate_case(xmldoc)
74
+ #parse it
75
+ el=xmldoc.elements[ELEM_SPEC]
76
+ xmldoc.root.attributes.each do |attr,value|
77
+ add_attribute(spec,attr,value)
78
+ end
79
+ #get the title
80
+ spec.title=xmldoc.elements[ELEM_TITLE].text
81
+ spec.title||=""
82
+ spec.title.strip!
83
+ #get the description
84
+ #strip line feeds, cariage returns and remove all tabs
85
+ spec.description=xmldoc.elements[ELEM_DESC].text
86
+ spec.description||=""
87
+ begin
88
+ spec.description.strip!
89
+ spec.description.gsub!(/\t/,'')
90
+ end unless spec.description.empty?
91
+ #get the requirements
92
+ reqs=el.elements.select{|e| e.name==ELEM_REQ}
93
+ reqs.collect!{|r| r.attributes["name"]}
94
+ spec.requirements=reqs
95
+ #Get the scenario
96
+ spec.scenario=parse_scenario(xmldoc.elements[ELEM_SCENARIO].to_s) if xmldoc.elements[ELEM_SCENARIO]
97
+ return spec
98
+ end
99
+ #Validates the XML file from our point of view.
100
+ #
101
+ #Checks for the existence of ELEM_SPEC, ELEM_DESC and ELEM_TITLE and raises ParserError if they're missing.
102
+ def validate_case xmldoc
103
+ raise ParserError,"missing #{ELEM_SPEC} element" unless xmldoc.elements[ELEM_SPEC]
104
+ raise ParserError,"missing #{ELEM_DESC} element" unless xmldoc.elements[ELEM_DESC]
105
+ raise ParserError,"missing #{ELEM_TITLE} element" unless xmldoc.elements[ELEM_TITLE]
106
+ end
107
+ #Parses the scenario XML element and returns the Rutema::TestScenario instance
108
+ def parse_scenario xmltxt
109
+ scenario=Rutema::TestScenario.new
110
+ xmldoc=REXML::Document.new( xmltxt )
111
+ xmldoc.root.attributes.each do |attr,value|
112
+ add_attribute(scenario,attr,value)
113
+ end
114
+ number=0
115
+ xmldoc.root.elements.each do |el|
116
+ number+=1
117
+ step=parse_step(el.to_s)
118
+ step.number=number
119
+ scenario.add_step(step)
120
+ end
121
+ return scenario
122
+ end
123
+ #Parses xml and returns the Rutema::TestStep instance
124
+ def parse_step xmltxt
125
+ xmldoc=REXML::Document.new( xmltxt )
126
+ #any step element
127
+ step=Rutema::TestStep.new()
128
+ xmldoc.root.attributes.each do |attr,value|
129
+ add_attribute(step,attr,value)
130
+ end
131
+ step.text=xmldoc.root.text.strip if xmldoc.root.text
132
+ step.step_type=xmldoc.root.name
133
+ return step
134
+ end
135
+
136
+ def add_attribute element,attr,value
137
+ if boolean?(value)
138
+ element.attribute(attr,eval(value))
139
+ else
140
+ element.attribute(attr,value)
141
+ end
142
+ end
143
+ def boolean? attribute_value
144
+ return true if attribute_value=="true" || attribute_value=="false"
145
+ return false
146
+ end
147
+ end
148
+
149
+ class MinimalXMLParser<BaseXMLParser
150
+ def parse_specification param
151
+ handle_specification(super(param))
152
+ end
153
+ private
154
+ def handle_specification spec
155
+ spec.scenario.steps.each do |step|
156
+ case step.step_type
157
+ when "echo"
158
+ step.cmd=Patir::RubyCommand.new("echo"){|cmd| cmd.output="#{step.text}";$stdout.puts(cmd.output) ;:success}
159
+ when "command"
160
+ raise ParserError,"missing required attribute cmd in #{step}"
161
+ wd=step.working_directory if step.has_working_directory?
162
+ step.cmd=Patir::ShellCommand.new(:cmd=>step.cmd,:working_directory=>wd)
163
+ when "prompt"
164
+ step.cmd=Patir::RubyCommand.new("prompt") do |cmd|
165
+ cmd.output=""
166
+ cmd.error=""
167
+ if HighLine.agree("#{step.text}?")
168
+ :success
169
+ else
170
+ :error
171
+ end#if
172
+ end#do rubycommand
173
+ end#case
174
+ end#do spec.scenario.steps
175
+ return spec
176
+ end
177
+ end
178
+
179
+ class Coordinator
180
+ attr_accessor :configuration,:parse_errors,:parsed_files
181
+ def initialize configuration,logger=nil
182
+ @logger=logger
183
+ @logger||=Patir.setup_logger
184
+ @parse_errors=Array.new
185
+ @configuration=configuration
186
+ @parser=instantiate_class(@configuration.parser)
187
+ raise "Could not instantiate parser" unless @parser
188
+ @reporters=@configuration.reporters.collect{ |reporter| instantiate_class(reporter) }
189
+ @reporters.compact!
190
+ @configuration.tests.collect!{|t| File.expand_path(t)}
191
+ @runner=create_runner
192
+ @parsed_files=Array.new
193
+ end
194
+ #Runs a set of tests
195
+ #
196
+ #mode can be :all, :attended, :unattended or a test filename
197
+ def run mode
198
+ @configuration.context.start_time=Time.now
199
+ @logger.info("Run started")
200
+ case mode
201
+ when :all
202
+ specs=parse_all_specifications
203
+ run_scenarios(specs)
204
+ when :attended
205
+ specs=parse_all_specifications
206
+ @logger.debug(specs)
207
+ run_scenarios(specs.select{|s| s.scenario && s.scenario.attended?})
208
+ when :unattended
209
+ specs=parse_all_specifications
210
+ @logger.debug(specs)
211
+ run_scenarios(specs.select{|s| s.scenario && !s.scenario.attended?})
212
+ when String
213
+ spec=parse_specification(mode)
214
+ run_test(spec) if spec
215
+ else
216
+ @logger.error("Don't know how to run '#{mode}'")
217
+ end
218
+ @configuration.context.end_time=Time.now
219
+ @logger.info("Run completed in #{@configuration.context.end_time-@configuration.context.start_time}s")
220
+ end
221
+
222
+ #Delegates reporting to all configured reporters spawning one thread per reporter
223
+ #
224
+ #It then joins the threads and returns when all of them are finished.
225
+ def report
226
+ threads=Array.new
227
+ runner_status=Patir::CommandSequenceStatus.new("",@runner.states.values)
228
+ #get the runner stati and the configuration and give it to the reporters
229
+ @reporters.each do |reporter|
230
+ threads<<Thread.new(reporter,runner_status,@parse_errors,@configuration) do |reporter,status,perrors,configuration|
231
+ @logger.debug(reporter.report(status,perrors,configuration))
232
+ end
233
+ end
234
+ threads.each do |t|
235
+ @logger.debug("Joining #{t}")
236
+ t.join
237
+ end
238
+ end
239
+
240
+ def to_s
241
+ runner_status=Patir::CommandSequenceStatus.new("",@runner.states.values)
242
+ "Parsed #{@parsed_files.size} files\n#{Rutema.text_report(runner_status,@parse_errors)}"
243
+ end
244
+ private
245
+ def instantiate_class definition
246
+ if definition[:class]
247
+ #add the logger to the definition
248
+ definition[:logger]=@logger
249
+ klass=definition[:class]
250
+ return klass.new(definition)
251
+ end
252
+ return nil
253
+ end
254
+
255
+ def create_runner
256
+ setup=nil
257
+ teardown=nil
258
+ if @configuration.setup
259
+ @logger.info("Parsing setup specification from '#{@configuration.setup}'")
260
+ setup=@parser.parse_specification(@configuration.setup).scenario
261
+ end
262
+ if @configuration.teardown
263
+ @logger.info("Parsing teardown specification from '#{@configuration.teardown}'")
264
+ teardown=@parser.parse_specification(@configuration.teardown).scenario
265
+ end
266
+ if @configuration.step
267
+ @logger.info("Using StepRunner")
268
+ return StepRunner.new(setup,teardown,@logger)
269
+ else
270
+ return Runner.new(setup,teardown,@logger)
271
+ end
272
+ end
273
+
274
+ def parse_specification spec_file
275
+ filename=File.expand_path(spec_file)
276
+ if File.exists?(filename)
277
+ begin
278
+ @parsed_files<<filename
279
+ @parsed_files.uniq!
280
+ return @parser.parse_specification(spec_file)
281
+ rescue ParserError
282
+ @logger.error("Error parsing '#{spec_file}': #{$!.message}")
283
+ @parse_errors<<{:filename=>filename,:error=>$!.message}
284
+ end
285
+ else
286
+ msg="'#{filename}' not found."
287
+ @logger.error(msg)
288
+ @parse_errors<<{:filename=>filename,:error=>msg}
289
+ end
290
+ return nil
291
+ end
292
+ def parse_all_specifications
293
+ @configuration.tests.collect{|t| parse_specification(t)}.compact
294
+ end
295
+
296
+ def run_scenarios specs
297
+ specs.compact!
298
+ if specs.empty?
299
+ @logger.error("No tests to run")
300
+ else
301
+ specs.each{|s| run_test(s)}
302
+ end
303
+ end
304
+ def run_test specification
305
+ @logger.info("Running #{specification.name} - #{specification.title}")
306
+ if specification.scenario
307
+ status=@runner.run(specification.name,specification.scenario)
308
+ else
309
+ @logger.warn("#{specification.name} has no scenario")
310
+ status=:not_executed
311
+ end
312
+ return status
313
+ end
314
+ end
315
+
316
+ #Runner executes TestScenario instances and maintains the state of all scenarios run.
317
+ class Runner
318
+ attr_reader :states,:number_of_runs
319
+ attr_accessor :setup,:teardown
320
+ attr_writer :attended
321
+
322
+ #setup and teardown are TestScenario instances that will run before and after each call
323
+ #to the scenario.
324
+ def initialize setup=nil, teardown=nil,logger=nil
325
+ @setup=setup
326
+ @teardown=teardown
327
+ @attended=false
328
+ @logger=logger
329
+ @logger||=Patir.setup_logger
330
+ @states=Hash.new
331
+ @number_of_runs=0
332
+ end
333
+
334
+ def attended?
335
+ return @attended
336
+ end
337
+ #Runs a scenario and stores the result internally
338
+ #
339
+ #Returns the result of the run as a Patir::CommandSequenceStatus
340
+ def run name,scenario
341
+ @logger.debug("Starting run for #{name} with #{scenario.inspect}")
342
+ @states[name]=Patir::CommandSequenceStatus.new(name,scenario.steps)
343
+ @states[name].sequence_id="s#{@number_of_runs}"
344
+ #if setup /teardown is defined we need to execute them before and after
345
+ if @setup
346
+ @logger.info("Setup for #{name}")
347
+ @states["#{name}_setup"]=run_scenario("#{name}_setup",@setup)
348
+ @states["#{name}_setup"].sequence_id="s#{@number_of_runs}"
349
+ if @states["#{name}_setup"].executed?
350
+ #do not execute the scenario unless the setup was succesfull
351
+ if @states["#{name}_setup"].success?
352
+ @logger.info("Scenario for #{name}")
353
+ @states[name]=run_scenario(name,scenario)
354
+ end
355
+ end
356
+ else
357
+ @logger.info("Scenario for #{name}")
358
+ @states[name]=run_scenario(name,scenario)
359
+ end
360
+ if @teardown
361
+ #always execute teardown
362
+ @logger.warn("Teardown for #{name}")
363
+ @states["#{name}_teardown"]=run_scenario("#{name}_teardown",@teardown)
364
+ @states["#{name}_teardown"].sequence_id="t#{@number_of_runs}"
365
+ end
366
+ @number_of_runs+=1
367
+ return @states[name]
368
+ end
369
+
370
+ #Returns the state of the scenario with the given name.
371
+ #
372
+ #Will return nil if no scenario is found under that name.
373
+ def [](name)
374
+ return @states[name]
375
+ end
376
+
377
+ def reset
378
+ @states.clear
379
+ @number_of_runs=0
380
+ end
381
+ private
382
+ def run_scenario name,scenario
383
+ state=Patir::CommandSequenceStatus.new(name,scenario.steps)
384
+ if scenario.attended? && !self.attended?
385
+ @logger.warn("Attended scenario cannot be run in unattended mode")
386
+ state..status=:warning
387
+ else
388
+ stps=scenario.steps
389
+ if stps.empty?
390
+ @logger.warn("Scenario #{name} contains no steps")
391
+ state.status=:warning
392
+ else
393
+ stps.each do |s|
394
+ state.step=run_step(s)
395
+ break if !state.success?
396
+ end
397
+ end
398
+ end
399
+ state.stop_time=Time.now
400
+ state.sequence_id=@number_of_runs
401
+ return state
402
+ end
403
+ def run_step step
404
+ @logger.info("#{step.to_s}")
405
+ if step.has_cmd? && step.cmd.respond_to?(:run)
406
+ step.cmd.run
407
+ else
408
+ @logger.warn("No command associated with step '#{step.step_type}'")
409
+ end
410
+ msg="#{step.number} - #{step.step_type} - #{step.status}"
411
+ # we might not have a command object
412
+ if step.has_cmd? && step.cmd.executed? && !step.cmd.success?
413
+ msg<<"\n#{step.cmd.output}" unless step.cmd.output.empty?
414
+ end
415
+ if step.status==:error
416
+ @logger.error(msg)
417
+ else
418
+ @logger.info(msg)
419
+ end
420
+ return step
421
+ end
422
+ end
423
+
424
+ #StepRunner halts before every step and asks if it should be executed or not.
425
+ class StepRunner<Runner
426
+ def run_step step
427
+ if HighLine.agree("Execute #{step.to_s}?")
428
+ return super
429
+ else
430
+ state[:state]=:not_executed
431
+ msg="#{step.number} - #{step.step_type} - #{state[:state]}"
432
+ @logger.info(msg)
433
+ return state
434
+ end
435
+ end
436
+ end
437
+
438
+ #The application class
439
+ class RutemaX
440
+ require 'optparse'
441
+ def initialize command_line_args
442
+ parse_command_line(command_line_args)
443
+ @logger=Patir.setup_logger(@log_file)
444
+ begin
445
+ @configuration=RutemaConfigurator.new(@config_file,@logger).configuration
446
+ @coordinator=Coordinator.new(@configuration,@logger)
447
+ application_flow
448
+ rescue Patir::ConfigurationException
449
+ @logger.debug($!)
450
+ @logger.fatal("Configuration error '#{$!.message}'")
451
+ exit 1
452
+ rescue
453
+ @logger.debug($!)
454
+ @logger.fatal("#{$!.message}")
455
+ exit 1
456
+ end
457
+ end
458
+ private
459
+ def parse_command_line args
460
+ args.options do |opt|
461
+ opt.on("Options:")
462
+ opt.on("--debug", "-d","Turns on debug messages") { $DEBUG=true }
463
+ opt.on("--config FILE", "-c FILE",String,"Loads the configuration from FILE") { |@config_file|}
464
+ opt.on("--log FILE", "-l FILE",String,"Redirects the log output to FILE") { |@log_file|}
465
+ opt.on("--check","Runs just the check test"){@check=true}
466
+ opt.on("-V", "--version","Displays the version") { $stdout.puts("v#{VERSION_MAJOR}.#{VERSION_MINOR}");exit 0 }
467
+ opt.on("--help", "-h", "-?", "This text") { $stdout.puts opt; exit 0 }
468
+ opt.parse!
469
+ #and now the rest
470
+ if args.empty?
471
+ @mode=:unattended
472
+ else
473
+ command=args.shift
474
+ case command
475
+ when "attended"
476
+ @mode=:attended
477
+ when "all"
478
+ @mode=:all
479
+ when "unattended"
480
+ @mode=:unattended
481
+ else
482
+ if File.exists?(command)
483
+ @mode=command
484
+ else
485
+ $stderr.puts "Can't find '#{command}'. Don't know what to do with it."
486
+ exit 1
487
+ end
488
+ end
489
+ end
490
+ end
491
+ end
492
+ def application_flow
493
+ if @check
494
+ #run just the check test
495
+ if @configuration.check
496
+ @coordinator.run(@configuration.check)
497
+ else
498
+ @logger.error("There is no check test defined in the configuration.")
499
+ end
500
+ else
501
+ #run everything
502
+ @coordinator.run(@mode)
503
+ end
504
+ @logger.info("Report:\n#{@coordinator.to_s}")
505
+ @coordinator.report
506
+ end
507
+ end
508
+ #Reporter is meant as a base class for reporter classes.
509
+ class Reporter
510
+ #params should be a Hash containing the parameters used to initialize the class
511
+ def initialize params
512
+ end
513
+
514
+ #Coordinator will pass the Rutema __configuration__ giving you access to the context which can contain data like headings and version numbers to use in the report.
515
+ #
516
+ #runner_status is a Patir::CommandSequenceStatus containing the status of the last run (so it contains all the Scenario stati for the loaded tests)
517
+ #
518
+ #parse_errors is an Array of {:filename,:error} hashes containing the errors encounter by the parser when loading the specifications
519
+ def report runner_status,parse_errors,configuration
520
+
521
+ end
522
+ end
523
+
524
+ #The following configuration keys are used by EmailReporter:
525
+ #
526
+ #:server - the smtp server to use
527
+ #
528
+ #:port - the port to use (defaults to 25)
529
+ #
530
+ #:sender - the sender of the email (defaults to rutema@domain)
531
+ #
532
+ #:recipients - an array of strings with the recipients of the report emails
533
+ #
534
+ #The :logger key is set by the Coordinator
535
+ #
536
+ #Customization keys:
537
+ #
538
+ #:subject - the string of this key will be prefixed as a subject for the email
539
+ class EmailReporter
540
+ attr_reader :last_message
541
+ def initialize definition
542
+ #get the logger
543
+ @logger=definition[:logger]
544
+ @logger||=Patir.setup_logger
545
+ #extract the parameters from the definition
546
+ #address and port of the smtp server
547
+ @server=definition[:server]
548
+ @port=definition[:port]
549
+ @port||=25
550
+ #the domain we're coming from
551
+ @domain=definition[:domain]
552
+ #construct the mail factory object
553
+ @mail = MailFactory.new()
554
+ @mail.from = definition[:sender]
555
+ @mail.from||="rutema@#{@domain}"
556
+ @recipients=definition[:recipients]
557
+ @mail.to=@recipients
558
+ #customize
559
+ @subject=definition[:subject]
560
+ @subject||=""
561
+ #this is a way to test without sending
562
+ @dummy=true if definition[:dummy]
563
+ @logger.info("Reporter '#{self.to_s}' registered")
564
+ end
565
+
566
+ def to_s
567
+ list=@recipients.join(', ')
568
+ "EmailReporter - #{@server}:#{@port} from #{@mail.from} to #{list}"
569
+ end
570
+
571
+ def report runner_status,parse_errors,configuration
572
+ @mail.subject = "#{@subject}"
573
+ @mail.text = Rutema.text_report(runner_status,parse_errors)
574
+ begin
575
+ if @mail.to.empty?
576
+ @logger.error("No recipients for the report mail")
577
+ else
578
+ #
579
+ #~ if @password
580
+ #~ #if a password is defined, use cram_md5 authentication
581
+ #~ else
582
+ Net::SMTP.start(@server, @port, @domain) {|smtp| smtp.sendmail(@mail.to_s(),@mail.from,mail_to)} unless @dummy
583
+ #~ end
584
+ end#recipients empty
585
+ rescue
586
+ @logger.error("Sending of email report failed: #{$!}")
587
+ end
588
+ @mail.to_s
589
+ end
590
+ end
591
+ private
592
+ def self.text_report runner_status,parse_errors
593
+ msg="Parse errors: #{parse_errors.size}"
594
+ parse_errors.each{|e| msg<<"\n\t#{e[:filename]}"}
595
+ msg<<"\nCurrent run:\nScenarios: #{runner_status.step_states.size}"
596
+ msg<<"\n#{runner_status.summary}"
597
+ return msg
598
+ end
599
+ end
@@ -0,0 +1,5 @@
1
+ <specification name="check">
2
+ <title></title>
3
+ <description></description>
4
+ <scenario></scenario>
5
+ </specification>
@@ -0,0 +1,7 @@
1
+ <specification name="setup">
2
+ <title></title>
3
+ <description></description>
4
+ <scenario>
5
+ <echo>Hello Testing World</echo>
6
+ </scenario>
7
+ </specification>
@@ -0,0 +1,7 @@
1
+ <specification name="teardown">
2
+ <title></title>
3
+ <description></description>
4
+ <scenario>
5
+ <echo>Hello Testing World</echo>
6
+ </scenario>
7
+ </specification>
@@ -0,0 +1,7 @@
1
+ <specification name="sample">
2
+ <title>Sample specification</title>
3
+ <description>Something to play with</description>
4
+ <scenario>
5
+ <echo>Hello Testing World</echo>
6
+ </scenario>
7
+ </specification>
@@ -0,0 +1,4 @@
1
+ <specification name="no_title">
2
+ <description>Expect a parser error</description>
3
+ <scenario></scenario>
4
+ </specification>
@@ -0,0 +1,7 @@
1
+ <specification name="sample">
2
+ <title>Sample specification</title>
3
+ <description>Something to play with</description>
4
+ <scenario>
5
+ <echo text="Hello testing world"/>
6
+ </scenario>
7
+ </specification>
@@ -0,0 +1,20 @@
1
+ require 'rake'
2
+ #
3
+ configuration.parser={:class=>Rutema::MinimalXMLParser}
4
+ configuration.reporter={:class=>Rutema::EmailReporter,
5
+ :server=>"localhost",
6
+ :port=>25,
7
+ :recipients=>["test"],
8
+ :sender=>"rutema",
9
+ :subject=>"test",
10
+ :dummy=>true
11
+ }
12
+ configuration.tool={:name=>"echo",:path=>"echo.exe"}
13
+ configuration.tool={:name=>"tool",:path=>"tool.exe"}
14
+ configuration.path={:name=>"SourcePath",:path=>"../../lib"}
15
+ configuration.setup="setup.spec"
16
+ configuration.teardown="teardown.spec"
17
+ configuration.check="check.spec"
18
+ configuration.tests=["test.spec"]
19
+ configuration.tests=Rake::FileList["tests/*.spec"]
20
+ configuration.context_data={:tester=>"riva"}
@@ -0,0 +1,37 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+
5
+ module TestRutema
6
+ require 'rutema/system'
7
+
8
+ class TestRutemaConfigurator<Test::Unit::TestCase
9
+ def setup
10
+ @prev_dir=Dir.pwd
11
+ Dir.chdir(File.dirname(__FILE__))
12
+ end
13
+ def teardown
14
+ Dir.chdir(@prev_dir)
15
+ end
16
+ def test_configuration
17
+ cfg=nil
18
+ #load the valid configuration
19
+ assert_nothing_raised() { cfg=Rutema::RutemaConfigurator.new("samples/valid_config.rb").configuration}
20
+ assert_not_nil(cfg.parser)
21
+ assert_not_nil(cfg.reporters)
22
+ assert_equal(1, cfg.reporters.size)
23
+ assert_not_nil(cfg.tools)
24
+ assert_not_nil(cfg.paths)
25
+ assert_not_nil(cfg.setup)
26
+ assert_not_nil(cfg.teardown)
27
+ assert_not_nil(cfg.check)
28
+ assert_not_nil(cfg.tests)
29
+ assert_not_nil(cfg.context)
30
+ end
31
+ def test_specification_paths
32
+ cfg=Rutema::RutemaConfigurator.new("samples/valid_config.rb").configuration
33
+ assert_not_nil(cfg.tests)
34
+ p cfg.tests
35
+ end
36
+ end
37
+ end