Test scope issue

My tests are broken. I generally suck at writing tests, so please bear
with me.

require 'test/unit'
require '../life.rb'

class TestLife < Test::Unit::TestCase
  def setup
    @life = Life.new
  end

  def test_life_exists
    assert( @life )
  end

  def test_vivify_vivifies
    @life.vivify(2,-1)
    assert( @life.world[2][-1] )
  end

  def test_murder_kills
    @life.murder(2,-1)
    assert( [email protected][2][-1] )
  end
end

I seem to be having a scoping issue here, where the changes made in
test_vivify_vivifies are not applying to @life in the general case; they
go away after test_vivify_vivifies ends, so that test_murder_kills
errors
out because @life.world[2] doesn’t exist at all at that point.

I have verified that when I run the code in life.rb using irb, the
@life.vivify actually gives me what I expect, and @life.murder thus
works
perfectly well there. Actually, I don’t even use the @ for an instance
variable when doing that; I only included it here to avoid scoping
issues
with local variables, but I seem to be having different scoping issues
as
a result. It so far seems to be only when running tests that there is
an
error.

I’m probably doing something stupid, but I have not yet seen it.

Each test method gets a new @life instance because the setup method runs
before each test. The theory is each test should run without side
affects
from other tests. I am no testing expert either, but I would write your
test in one method.

def test_vivify_and_murder
@life.vivify(2,-1)
assert( @life.world[2][-1] )
@life.murder(2,-1)
assert( !@life.world[2][-1] )
end

Again, I’m sure this is considered poor style and not pure TDD/BDD.

-Doug

On Sun, Jun 19, 2011 at 10:17:19AM +0900, Douglas S. wrote:

end

Again, I’m sure this is considered poor style and not pure TDD/BDD.

I should have read a bit more closely about setup, I guess. I had no
idea that was where the problem existed, though.

Thanks for the information! I’ll make good use of it.

On Saturday, June 18, 2011 08:17:19 PM Douglas S. wrote:

end

Again, I’m sure this is considered poor style and not pure TDD/BDD.

You generally want one assertion per test. More doesn’t hurt, but you
probably
still want a separate ‘test_vivify_vivifies’ method.

Also, if you find yourself writing a lot of tests which want a life
already
vivified, you may want to write another test class which does that in
its
setup. I’m not sure of the best way to do that in Test::Unit, though. I
think
I end up doing a lot of things like this in RSpec:

describe ‘A life’ do
before :each do
@life = Life.new
end

it 'should exist' do
  @life.should_not be_nil
end

describe 'A vivified life' do
  before :each do
    @life.vivify(2,-1)
  end

  it 'should exist in the world' do
    @life.world[2][-1].should_not be_nil
  end

  it 'should be killed when murdered' do
    @life.murder(2,-1)
    @life.world[2][-1].should be_nil
  end
end

end

Be careful with this, though. While DRY (Don’t Repeat Yourself) is a
good
principle in developing actual code, it’s often better to have explicit
readability in tests than implicit magic to avoid repeating yourself.