rutema 0.1

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