What does it mean to keep tests isolated?

I’ve been reading the Objects on Rails book by Avdi Grimm and he stresses the importance of keeping your tests isolated from one another.

This may very well be newb question, but what exactly does that mean?

@Rene_Escobar One of the most important rules of tests is that they should not depend on each other, or the running order of the test suite. Examples would include tests which mutate a shared state. Tests should be setup, executed and torn down in isolation so that they can be run as a true “unit”.

Allow me to give a short example of isolation from one angles:

class A
end

class B
end

class C
  def do_something_with(a,b)
    ...
    a = A.do_something(a)
    ...
    b = B.do_something(b)
    ...
    ...
    [a,b]
  end
end

This is an antipattern for isolation because the A and B are concrete in C.

A fix is:

class A
end

class B
end

class C
  def do_something_with(a_class, a, b_class, b)
    ...
    a_ret = a_class.do_something(a)
    ...
    b_ret = b_class.do_something(b)
    ...
    ...
    [a_ret, b_ret]
  end
end

Here would be another, isolating out an external dependency:

bad

require 'something_else'
class A
  def do_something(a)
    ret = SomethingElse.new(a)
    ...
    ...
    ...
    ret
  end
end

better:

require 'something_else'
class A
  def do_something(a)
    ret = something_else.new(a)
    ...
    ...
    ...
    ret
  end

private

  def something_else(val)
    SomethingElse.new(val)
  end
end

Now I can stub out that method because_I_own_it_

A.stubs(:something_else) { ... }
2 Likes

Thanks everyone!

@Dreamr Isn’t it a little bit better to pass instances as dependencies because then C in your example isn’t coupled to the constructors of A or B?

@Rene_Escobar, this check isn’t really explaining the definition of test isolation (or idempotency), but the easiest way to test to see if your tests are isolated is to run them in a random order every time. RSpec can do this with the order = 'random' setting in spec_helper. If you get sporadic failures that sometimes go away without any code changing, note the seed number when the run fails, and you can re-run that specific run to check for what was causing the problem.

Yes, I hate these contrived examples :slight_smile: I would much rather you join me Sundays 12pm CST on google hangouts where I discuss this sort of thing and do live code and live tests. :smiley:

Yeah that’d be pretty cool! Can you PM me your google username?