Test/unit question. Accessing class variables?

Hello.
   This is my first attempt in trying to use the ruby library test/
unit. Additionally my programming and ruby skills are still around
the beginner stage.

  I have a unix utility which I've written in ruby and now that it
actually does some work I want to be able to test it. My first
attempt at a unit test was to check the value of a class variable but
this results in the following error

NameError: uninitialized class variable @@bad_users in FindUsersTest

   Here is a class and test which demonstrates what I'm trying to
do.

-- start class
class Simple
@@whatisit = "false"

  def parse(n)
    @@whatisit = true if n =~ /yes/
  end
end

--- start test
require 'simple'
require 'test/unit'

class SimpleTest < Test::Unit::TestCase

  def test_parse
   v = Simple.new
   v.parse("yes")

  assert @@whatisit
   end
end

--- run test
./test_simple.rb
Started
E
Finished in 0.003813 seconds.

  1) Error:
test_parse(SimpleTest):
NameError: uninitialized class variable @@whatisit in SimpleTest
    ./test_simple.rb:14:in `test_parse'

1 tests, 0 assertions, 0 failures, 1 errors

I then added this method into the simple class above

def return_whatisit
  @@whatisit
end

   Then in my test created a Simple object (v = Simple.new) and then
called the return_whatisit method (eg: v.return_whatisit). I dont
really want to have to add extra methods to the code to support the
retreival of class variables from within the tests. I dont
understand why I'm not able to access the class variable @@whatisit
from within the test script? Is it possible to extend the Simple
class from within the test file itself?
   For example iin the test file I would like to add this method to
the Simple class
def return_whatisit
  @@whatisit
end

   So if you have any tips on how to best approach this situation I
would appreciate it. I figure if I get a better understanding of
using and writing tests that will influence how I write scripts down
the road.

  TIA. G

I don't know how to solve your problem under the constraints you impose -- that is, with a class variable but without writing some kind of accessor method. The following quote from the Pickaxe book suggests there is no support for what you want in Ruby.

    Class variables are private to a class and its instances. If you want to make them acces-
    sible to the outside world, you’ll need to write an accessor method. This method could
    be either an instance method or ... a class method.

Do you really need to use a class variable?

Regards, Morton

···

On Nov 14, 2007, at 5:15 PM, weathercoach@gmail.com wrote:

   Hello.
   This is my first attempt in trying to use the ruby library test/
unit. Additionally my programming and ruby skills are still around
the beginner stage.

  I have a unix utility which I've written in ruby and now that it
actually does some work I want to be able to test it. My first
attempt at a unit test was to check the value of a class variable but
this results in the following error

NameError: uninitialized class variable @@bad_users in FindUsersTest

   Here is a class and test which demonstrates what I'm trying to
do.

-- start class
class Simple
@@whatisit = "false"

  def parse(n)
    @@whatisit = true if n =~ /yes/
  end
end

--- start test
require 'simple'
require 'test/unit'

class SimpleTest < Test::Unit::TestCase

  def test_parse
   v = Simple.new
   v.parse("yes")

  assert @@whatisit
   end
end

--- run test
./test_simple.rb
Started
E
Finished in 0.003813 seconds.

  1) Error:
test_parse(SimpleTest):
NameError: uninitialized class variable @@whatisit in SimpleTest
    ./test_simple.rb:14:in `test_parse'

1 tests, 0 assertions, 0 failures, 1 errors

I then added this method into the simple class above

def return_whatisit
  @@whatisit
end

   Then in my test created a Simple object (v = Simple.new) and then
called the return_whatisit method (eg: v.return_whatisit). I dont
really want to have to add extra methods to the code to support the
retreival of class variables from within the tests. I dont
understand why I'm not able to access the class variable @@whatisit
from within the test script? Is it possible to extend the Simple
class from within the test file itself?
   For example iin the test file I would like to add this method to
the Simple class
def return_whatisit
  @@whatisit
end

   So if you have any tips on how to best approach this situation I
would appreciate it. I figure if I get a better understanding of
using and writing tests that will influence how I write scripts down
the road.

  Hello.
  This is my first attempt in trying to use the ruby library test/
unit. Additionally my programming and ruby skills are still around
the beginner stage.

I have a unix utility which I've written in ruby and now that it
actually does some work I want to be able to test it. My first
attempt at a unit test was to check the value of a class variable but
this results in the following error

NameError: uninitialized class variable @@bad_users in FindUsersTest

  Here is a class and test which demonstrates what I'm trying to
do.

-- start class
class Simple
@@whatisit = "false"

def parse(n)
   @@whatisit = true if n =~ /yes/
end
end

--- start test
require 'simple'
require 'test/unit'

class SimpleTest < Test::Unit::TestCase

def test_parse
  v = Simple.new
  v.parse("yes")

assert @@whatisit
  end
end

--- run test
./test_simple.rb
Started
E
Finished in 0.003813 seconds.

1) Error:
test_parse(SimpleTest):
NameError: uninitialized class variable @@whatisit in SimpleTest
   ./test_simple.rb:14:in `test_parse'

1 tests, 0 assertions, 0 failures, 1 errors

I then added this method into the simple class above

def return_whatisit
@@whatisit
end

  Then in my test created a Simple object (v = Simple.new) and then
called the return_whatisit method (eg: v.return_whatisit). I dont
really want to have to add extra methods to the code to support the
retreival of class variables from within the tests. I dont
understand why I'm not able to access the class variable @@whatisit
from within the test script? Is it possible to extend the Simple
class from within the test file itself?

The class 'SimpleTest' has nothing to do with your class 'Simple'. They share a name but nothing else so you can't access the class variable directly.

  For example iin the test file I would like to add this method to
the Simple class
def return_whatisit
@@whatisit
end

  So if you have any tips on how to best approach this situation I
would appreciate it. I figure if I get a better understanding of
using and writing tests that will influence how I write scripts down
the road.

TIA. G

The approach you suggest (defining an extra helper method in the test) seems to work fine though?

[alexg@powerbook]/Users/alexg/Desktop(6): cat simple.rb
class Simple
   @@whatisit = "false"

   def parse(n)
     @@whatisit = true if n =~ /yes/
   end
end
[alexg@powerbook]/Users/alexg/Desktop(7): cat test.rb
require 'simple'
require 'test/unit'

class Simple
   def return_whatisit
     @@whatisit
   end
end

class SimpleTest < Test::Unit::TestCase

  def test_parse
    v = Simple.new
    v.parse("yes")

    assert v.return_whatisit
   end

end
[alexg@powerbook]/Users/alexg/Desktop(8): ruby test.rb
Loaded suite test
Started
.
Finished in 0.004223 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

Alex Gutteridge

Bioinformatics Center
Kyoto University

···

On 15 Nov 2007, at 07:15, weathercoach@gmail.com wrote:

weathercoach wrote:

  This is my first attempt in trying to use the ruby library test/
unit. Additionally my programming and ruby skills are still around
the beginner stage.
I have a unix utility which I've written in ruby and now that it
actually does some work I want to be able to test it.

Next time, write the tests at the same time as you write the code. This is called "Test Driven Development", and it usually prevents issues like yours before they have a chance to exist.

Specifically, your objects' interfaces will remain very narrow and decoupled. Tests usually sense the program state from convenient return values, and private variables remain private.

···

--
   Phlip