Scripts run using load in "for" loop run out of order

F

Fa Sidd

Hi
I am new to ruby and like it so far.

I have an existing test harness to plug into and need to run a number of
scripts in a specific order.
I am using load in a "for loop" to run them. Unfortunately the scripts
get run out of order.

Below is my main script and my other scripts follow.

Files are:
test.rb
Tests/A-test.rb
Tests/B-test.rb
Tests/C-test.rb
Tests/D-test.rb

To simplify the question, I have created an array of the scripts I need
to run in the required order. But the output shows that the scripts run
in the following order D-test.rb, A-test.rb, C-test.rb and then
B-test.rb.

Somehow A gets run before C.

Is there any way to run the scripts in the correct order? And how come
it loops through the puts first and then the load?

Thanks in advance


#****** test.rb ********************
TOPDIR = File.join(File.dirname(__FILE__), '.')
$LOAD_PATH.unshift TOPDIR

require 'test/unit'
require 'test/unit/ui/console/testrunner'

Dir.chdir TOPDIR

testList = []

testList[0]="Tests/D-test.rb"
testList[1]="Tests/C-test.rb"
testList[2]="Tests/A-test.rb"
testList[3]="Tests/B-test.rb"

begin
for i in 0 .. testList.length-1
puts "i: #{i} testname: #{testList}"
load(testList)
end
end

#************* A-test.rb ***************
class TC_One < Test::Unit::TestCase

def setup
puts
puts "***********"
puts "In A-test setup"
end

def test_one
puts "In A-test.rb testcase one"
sleep 1
end

def teardown
puts "In A-test teardown"
puts "***********"
puts
end
end

#************* B-test.rb ***************
class TC_Two < Test::Unit::TestCase

def setup
puts
puts "***********"
puts "In B-test setup"
end

def test_one
puts "In B-test.rb testcase one"
sleep 1
end

def teardown
puts "In B-test teardown"
puts "***********"
puts
end
end

#************* C-test.rb ***************
class TC_Three < Test::Unit::TestCase

def setup
puts
puts "***********"
puts "In C-test setup"
end

def test_one
puts "In C-test.rb testcase one"
sleep 1
end

def teardown
puts "In C-test teardown"
puts "***********"
puts
end
end
#************* D-test.rb ***************
class TC_Four < Test::Unit::TestCase

def setup
puts
puts "***********"
puts "In D-test setup"
end

def test_one
puts "In D-test.rb testcase one"
t = Time.now
sleep 2
puts t
end

def teardown
puts "In D-test teardown"
puts "***********"
puts
end
end
#************* Output ***************

Y:\ruby>test.rb
i: 0 testname: Tests/D-test.rb
i: 1 testname: Tests/C-test.rb
i: 2 testname: Tests/A-test.rb
i: 3 testname: Tests/B-test.rb
Loaded suite Y:/ruby/test
Started

***********
In D-test setup
In D-test.rb testcase one
Wed Jan 23 10:14:33 -0800 2008
In D-test teardown
***********
 
T

Thomas Preymesser

Hi
I am new to ruby and like it so far.

I have an existing test harness to plug into and need to run a number of
scripts in a specific order.
I am using load in a "for loop" to run them. Unfortunately the scripts
get run out of order.

To simplify the question, I have created an array of the scripts I need
to run in the required order. But the output shows that the scripts run
in the following order D-test.rb, A-test.rb, C-test.rb and then
B-test.rb.

Somehow A gets run before C.


in your code, your are not 'running' the test cases with your order
you're just loading Testcase declarations. All the collected test classes
are 'run' when your loop is finished.
The test-classes are running in alphabetical order ("TC_Four", "TC_One",
"TC_Three", "TC_Two")

And how come
it loops through the puts first and then the load?


it doesn't - it does perfectly the puts and then the load-statement but
since the load is only loading declarations you will see no output (like in
every other class declaration which is included in a ruby program).

-Thomas

--=20
Thomas Preymesser
(e-mail address removed)
(e-mail address removed)
B=FCro: 030 - 830 353 88
mobil: 0176 - 75 03 03 04
Privat: 030 - 49 78 37 06
http://thopre.wordpress.com/
http://www.thopre.com/
 
F

Fa Sidd

Thomas said:
in your code, your are not 'running' the test cases with your order
you're just loading Testcase declarations. All the collected test
classes
are 'run' when your loop is finished.
The test-classes are running in alphabetical order ("TC_Four", "TC_One",
"TC_Three", "TC_Two")

Thanks for your response.

Is there a way I can run the scripts in the correct order in the loop?
 
Z

zetetic

Thanks for your response.

Is there a way I can run the scripts in the correct order in the loop?

To execute a test, you need to run it as follows:

Test::Unit::UI::Console::TestRunner.run(test)

Try replacing everything after Dir.chdir TOPDIR with the following:

Dir["Tests/*.rb"].each {|testfile| load "#{testfile}"}
[TC_Four,TC_Three,TC_One,TC_Two,].each {|test|
Test::Unit::UI::Console::TestRunner.run(test) }

or if you want to name the files explicitly, you could do:

testList = %w(Tests/A-test.rb Tests/B-test.rb Tests/C-test.rb Tests/
D-test.rb)
testList.each {|testfile| load "#{testfile}"}
[TC_Four,TC_Three,TC_One,TC_Two,].each {|test|
Test::Unit::UI::Console::TestRunner.run(test) }

This loads all the test classes first, then executes them in the order
you specify. Change the order of the classes in the second line if you
want to change the order of the tests.
 
F

Fa Sidd

zetetic said:
testList = %w(Tests/A-test.rb Tests/B-test.rb Tests/C-test.rb Tests/
D-test.rb)
testList.each {|testfile| load "#{testfile}"}
[TC_Four,TC_Three,TC_One,TC_Two,].each {|test|
Test::Unit::UI::Console::TestRunner.run(test) }

This loads all the test classes first, then executes them in the order
you specify. Change the order of the classes in the second line if you
want to change the order of the tests.

I get the list of tests scripts from the test harness and do not know
the class names and execution order in advance.

Is there a better way to my tests, if I had just a list of test scripts
in order of execution
 
T

Thomas Preymesser

testList =3D %w(Tests/A-test.rb Tests/B-test.rb Tests/C-test.rb Tests= /
D-test.rb)
testList.each {|testfile| load "#{testfile}"}
[TC_Four,TC_Three,TC_One,TC_Two,].each {|test|
Test::Unit::UI::Console::TestRunner.run(test) }

This loads all the test classes first, then executes them in the order
you specify. Change the order of the classes in the second line if you
want to change the order of the tests.

I get the list of tests scripts from the test harness and do not know
the class names and execution order in advance.

Is there a better way to my tests, if I had just a list of test scripts
in order of execution


replace your "load(testList)"-line with "`ruby #{testList}`"

-Thomas



--=20
Thomas Preymesser
(e-mail address removed)
(e-mail address removed)
B=FCro: 030 - 830 353 88
mobil: 0176 - 75 03 03 04
Privat: 030 - 49 78 37 06
http://thopre.wordpress.com/
http://www.thopre.com/
 
B

brabuhr

Hi
I am new to ruby and like it so far.
...

First, since you are new to Ruby, some alternate ways to code your sample:
testList = []

testList[0]="Tests/D-test.rb"
testList[1]="Tests/C-test.rb"
testList[2]="Tests/A-test.rb"
testList[3]="Tests/B-test.rb"

a) Append to the array instead of directly indexing:
testList = []
testList << "Tests/D-test.rb"
testList << "Tests/C-test.rb"
testList << "Tests/A-test.rb"
testList << "Tests/B-test.rb"

b) Directly initialize the literal array:
testList = [
"Tests/D-test.rb",
"Tests/C-test.rb",
"Tests/A-test.rb",
"Tests/B-test.rb"
]

c) Initialize an array of words:
testList = %w{
Tests/D-test.rb
Tests/C-test.rb
Tests/A-test.rb
Tests/B-test.rb
}
begin
for i in 0 .. testList.length-1
puts "i: #{i} testname: #{testList}"
load(testList)
end
end


a) Instead of explicit loop and indexing, iterate
testList.each do |test|
puts "testname: #{test}"
load test
end

b) If you still want the index too
testList.each_with_index do |test, i|
puts "#{i} \t #{test}"
load test
end

And, as to your question, perhaps you could try explicitly invoke the
TestRunner:

# load all of the test cases
Dir.glob("./Tests/*.rb").each do |tfile|
require tfile
end

# run the test cases explicitly in order
[ TC_Four, TC_Three, TC_One, TC_Two ].each do |tclass|
Test::Unit::UI::Console::TestRunner.run(tclass)
end

See "Test Runners" and "Test Suite":
http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html
 
B

brabuhr

But, sorry that this doesn't yet work around not knowing the class
names just the file names.

Maybe:

require 'test/unit/ui/console/testrunner'

# global array to hold the test classes as they are loaded
$tests = []

# monkey patch to record the new subclasses as they are loaded
class Test::Unit::TestCase
def self.inherited(subclass)
$tests << subclass
end
end

# load all the files
%w{
Tests/D-test.rb
Tests/C-test.rb
Tests/A-test.rb
Tests/B-test.rb
}.each do |tfile|
require tfile
end

# run the test classes in the order they were loaded
$tests.each do |tclass|
Test::Unit::UI::Console::TestRunner.run(tclass)
end
 
F

Fa Sidd

unknown said:
# monkey patch to record the new subclasses as they are loaded
class Test::Unit::TestCase
def self.inherited(subclass)
$tests << subclass
end
end

# load all the files
%w{
Tests/D-test.rb
Tests/C-test.rb
Tests/A-test.rb
Tests/B-test.rb
}.each do |tfile|
require tfile
end

# run the test classes in the order they were loaded
$tests.each do |tclass|
Test::Unit::UI::Console::TestRunner.run(tclass)
end

This worked!

Not sure if replacing "load(testList)" with "`ruby #{testList}`"
would have worked. I have global variables that I need to worry about

Thanks for the help everyone

Thanks.
 
P

Phrogz

But, sorry that this doesn't yet work around not knowing the class
names just the file names.

Maybe:

require 'test/unit/ui/console/testrunner'

# global array to hold the test classes as they are loaded
$tests = []

# monkey patch to record the new subclasses as they are loaded
class Test::Unit::TestCase
  def self.inherited(subclass)
    $tests << subclass
  end
end

Or, avoid the global with:

class Test::Unit::TestCase
class << self
attr_reader :subclasses
def inherited( subclass )
(@subclasses||=[]) << subclass
end
end
end

and then

Test::Unit::TestCase.subclasses.each do |klass|
...
end
 
Z

zetetic

require 'test/unit/ui/console/testrunner'
# global array to hold the test classes as they are loaded
$tests = []
# monkey patch to record the new subclasses as they are loaded
class Test::Unit::TestCase
def self.inherited(subclass)
$tests << subclass
end
end

Or, avoid the global with:

class Test::Unit::TestCase
class << self
attr_reader :subclasses
def inherited( subclass )
(@subclasses||=[]) << subclass
end
end
end

and then

Test::Unit::TestCase.subclasses.each do |klass|
...
end

Sweet! (or perhaps I should say: suite!)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top