1

Hi I made it to the lase exercise os Learn Ruby The Hard Way, and I come at the wall...

Here is the test code:

def test_gothon_map()
    assert_equal(START.go('shoot!'), generic_death)
    assert_equal(START.go('dodge!'), generic_death)

    room = START.go("tell a joke")

    assert_equal(room, laser_weapon_armory)
end

And here is the code of the file it should test:

class Room

  attr_accessor :name, :description, :paths

  def initialize(name, description)
    @name = name
    @description = description
    @paths = {}
  end

  def ==(other)
    self.name==other.name&&self.description==other.description&&self.paths==other.paths
  end

  def go(direction)
    @paths[direction]
  end

  def add_paths(paths)
    @paths.update(paths)
    end

end

generic_death = Room.new("death", "You died.")

And when I try to launch the test file I get an error:

generic_death = Room.new("death", "You died.")

I tried to set the "generic_death = Room.new("death", "You died.")" in test_gothon_map method and it worked but the problem is that description of the next object is extremely long, so my questions are:

  • why assertion doesn't not respond to defined object?
  • can it be done different way then by putting whole object to testing method, since description of the next object is extremely long...
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
Kazik
  • 705
  • 1
  • 8
  • 20

1 Answers1

0

The nature of local variable is that they are, well, local. This means that they are not available outside the scope they were defined.

That's why ruby does not know what generic_death means in your test.

You can solve this in a couple of ways:

  • define rooms as constants in the Room class:

    class Room
      # ...
    
      GENERIC_DEATH = Room.new("death", "You died.")
      LASER_WEAPON_ARMORY = Room.new(...)
    end
    
    def test_gothon_map()
      assert_equal(Room::START.go('shoot!'), Room::GENERIC_DEATH)
      assert_equal(Room::START.go('dodge!'), Room::GENERIC_DEATH)
    
      room = Room::START.go("tell a joke")
    
      assert_equal(room, Room::LASER_WEAPON_ARMORY)
    end
    
  • assert the room by its name, or some other identifier:

    def test_gothon_map()
      assert_equal(START.go('shoot!').name, "death")
      assert_equal(START.go('dodge!').name, "death")
    
      room = START.go("tell a joke")
    
      assert_equal(room.name, "laser weapon armory")
    end
    
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
  • A question so I get this clear, in first example the 'rooms' are assigned to the constant and test assertion is complex (name, description). On the second example the assertion is only made on the 'name' parameter. Right? – Kazik May 11 '14 at 15:02
  • I don't know what you mean by "complex" - it compares that the rooms are the same _object_ (after you remove the `==` override, which I'm not sure is a good idea anyway), even _if_ the assertion was on `name` _and_ `description` I don't believe it is "complex", simply more constrained - if it has any meaning in that context... – Uri Agassi May 11 '14 at 15:14
  • The '==' override is there because when I made assert_equal of two objects returns false because objects id is never the same. By "complex" I meant that it asserts all of the objects parameters. – Kazik May 11 '14 at 15:21
  • `assert_equal` calls `==` between the expected and the actual, and throws an exception if it returns false, so, I guess it is as complex as `==` is... (as you already know - the default `==` returns true only if the `object_id` is the same) – Uri Agassi May 11 '14 at 15:42
  • Your second answer works fine, but I had a problem with first option, and instead of 'START' I had to put 'Room::START', and instead of Room.GENERIC_DEATH' I had to put 'Room::GENERIC_DEATH' – Kazik May 11 '14 at 15:49