test isolation: default ignores & repository acquisition

John Arbash Meinel john at arbash-meinel.com
Wed Sep 23 04:55:28 BST 2009


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


...

> 
> 1) Shorter tests address your point, by making tests shorter you
> can see more in the same page. That means: put more code in
> setUp() and create higher level helpers.
> 
> 2) I don't buy the argument that tests have to be on the same
> page that their setup. It's a bit like saying that inheritance
> can be used only if all classes fit in the same page.
> 

I also want to point out a small but valid point. If I want to chain my
setup code. In the inheritance case I would have:


class TestBase(TestCase):

  def setUp(self):
        super(TestBase, self).setUp()
  	self.state = do_one()


class TestAndThenSome(TestBase):

   def setUp(self):
        super(TestAndThenSome, self).setUp()
        self.state.do_two()


class TestAndYetSomeMore(TestAndThenSome):

   def setUp(self):
        super(TestAndYetSomeMore, self).setUp()
        self.state.do_three()


class TestsNeedOne(TestBase):

   def test_needs_one(self):
       self.assertEqual(self.state, 'foo')


class TestsNeedTwo(TestAndThenSome):

   def test_needs_two(self):
       self.assertEqual(self.state, 'bar')


class TestsNeedsThree(TestAndYetSomeMore):

   def test_needs_three(self):
       self.assertEqual(self.state, 'baz')


Compare that to:

class TestBase(TestCase):

  def make_one(self):
      return do_one()

  def make_two(self):
      state = self.make_one()
      state.do_two()
      return state

  def make_three(self):
      state = self.make_two()
      state.do_three()
      return state

  def test_needs_one(self):
      state = self.make_one()
      self.assertEqual(state, 'foo')

  def test_needs_two(self):
      state = self.make_two()
      self.assertEqual(state, 'bar')

  def test_needs_three(self):
      state = self.make_three()
      self.assertEqual(state, 'baz')


I can agree that in the former case, the test_needs_* are 'cleaner'. But
actually finding the actual state is not any easier. And it is a *lot*
more structural overhead (38 lines versus 27).

I was also originally tempted to just put the "test_needs_one" on the
TestBase class, but that would actually fail, because it would try to
run 'test_needs_one' in the TestAndYetSomeMore case.

And if you really cared about lines of code, you could ahve 'do_two()'
return the state object, and you end up with:

  def make_two(self):
      return self.make_one().do_two()

  def make_three(self):
      return self.make_two().do_three()


Now, I've written some code that points to the benefit of 'make_*' style
set up. I'd love for you to give me an example where you feel 'setUp()'
plus inheritance is better, so that I have a feel for when to use it.

John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkq5nDAACgkQJdeBCYSNAAPOTACfWYmscsYQp1P+zTKgmPOFRDZI
efcAoMn0W8Vu11IAaifMdAzn66ZavIiC
=dOyz
-----END PGP SIGNATURE-----



More information about the bazaar mailing list