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