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

Discussion in 'Ruby' started by Fa Sidd, Jan 23, 2008.

  1. Fa Sidd

    Fa Sidd Guest

    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
    ***********
    Fa Sidd, Jan 23, 2008
    #1
    1. Advertising

  2. On 23/01/2008, Fa Sidd <> wrote:
    >
    > 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


    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/
    Thomas Preymesser, Jan 23, 2008
    #2
    1. Advertising

  3. Fa Sidd

    Fa Sidd Guest

    Thomas Preymesser wrote:

    > 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?
    --
    Posted via http://www.ruby-forum.com/.
    Fa Sidd, Jan 23, 2008
    #3
  4. Fa Sidd

    zetetic Guest

    On Jan 23, 1:32 pm, Fa Sidd <> wrote:
    > Thomas Preymesser wrote:
    > > 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?
    > --
    > Posted viahttp://www.ruby-forum.com/.


    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.
    zetetic, Jan 24, 2008
    #4
  5. Fa Sidd

    Fa Sidd Guest

    zetetic wrote:
    >
    > 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
    --
    Posted via http://www.ruby-forum.com/.
    Fa Sidd, Jan 24, 2008
    #5
  6. On 24/01/2008, Fa Sidd <> wrote:
    >
    > zetetic wrote:
    > >
    > > 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


    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/
    Thomas Preymesser, Jan 24, 2008
    #6
  7. Fa Sidd

    Guest

    On Jan 23, 2008 1:31 PM, Fa Sidd <> wrote:
    > 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
    , Jan 24, 2008
    #7
  8. Fa Sidd

    Guest

    , Jan 24, 2008
    #8
  9. Fa Sidd

    Guest

    On Jan 24, 2008 6:06 PM, <> wrote:
    > 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
    , Jan 24, 2008
    #9
  10. Fa Sidd

    Fa Sidd Guest

    unknown wrote:
    > On Jan 24, 2008 6:06 PM, <> wrote:
    >
    > # 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.

    --
    Posted via http://www.ruby-forum.com/.
    Fa Sidd, Jan 25, 2008
    #10
  11. Fa Sidd

    Phrogz Guest

    On Jan 24, 4:24 pm, wrote:
    > On Jan 24, 2008 6:06 PM,  <> wrote:
    >
    > > 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
    Phrogz, Jan 25, 2008
    #11
  12. Fa Sidd

    zetetic Guest

    On Jan 24, 6:06 pm, Phrogz <> wrote:
    > On Jan 24, 4:24 pm, wrote:
    >
    >
    >
    > > On Jan 24, 2008 6:06 PM, <> wrote:

    >
    > > > 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


    Sweet! (or perhaps I should say: suite!)
    zetetic, Jan 25, 2008
    #12
  13. Fa Sidd

    ara howard Guest

    On Jan 25, 2008, at 3:24 PM, zetetic wrote:

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


    check out my dynaload gem, it abstracts this very pattern for
    objects, classses, and modules.

    regards.

    a @ http://codeforpeople.com/
    --
    share your knowledge. it's a way to achieve immortality.
    h.h. the 14th dalai lama
    ara howard, Jan 26, 2008
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jan Danielsson
    Replies:
    8
    Views:
    621
    Mike Meyer
    Jul 22, 2005
  2. Jp Calderone
    Replies:
    0
    Views:
    449
    Jp Calderone
    Jul 21, 2005
  3. davidj411
    Replies:
    0
    Views:
    493
    davidj411
    Jun 27, 2008
  4. Replies:
    13
    Views:
    528
    Anno Siegel
    Sep 10, 2007
  5. Isaac Won
    Replies:
    9
    Views:
    372
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page