Which mock library do you prefer?

Phlip phlip2005 at gmail.com
Mon Feb 15 14:56:53 EST 2010


Lacrima wrote:

> Thanks for your reply! Isn't what you are talking about integration
> tests? And unit tests should be fully isolated? So even for method
> 'some_method()' of class A I should mock instance of class A (i.e. to
> mock 'self') to test 'some_method()'.

"Unit test" is a high-end QA concept. Developers can get the best
return on "developer tests". They don't bother with aerospace-quality
isolation between units.

If a TDD test needs to pull in a bunch of modules to pass, that's
generally a good thing, because they all get indirect testing. If they
catch a bug, their local tests might not catch it, but the higher
level tests still have a chance.

(And if your product still needs unit tests, TDD will make them very
easy for a formal QA team to add.)

However, expensive setup is a design smell. That means if a test case
requires too many lines of code for its Assemble phase (before its
Activate and Assert phases), then maybe those lines of code support
objects that are too coupled, and they need a better design.

Throwing mocks at these objects, instead of decoupling them, will
"perfume" the design smell, instead of curing it.

> > "construction encapsulation")

> And could you give an example.

  def test_frob(self):
      frob = Frob()
      frob.knob = Mock()
      frob.knob.value = Mock(return_value = 42)
      assert 42 == frob.method_using_knob()

We need the mock because we can't control how Frob's constructor built
its knob. So instead, give Frob the option to construct with a Knob:

  def test_frob(self):
      knob = Knob(42)
      frob = Frob(knob)
      assert frob.method_using_knob()

Note that in production the Knob constructor never takes a Knob. Maybe
we should upgrade the production code too (!), or maybe Knob's
constructor should only create a knob if it didn't get passed one.
Either technique is acceptable, because the resulting code decouples
Frobs and Knobs just a little bit more.

> For me it's really hard to develop test first. Often I don't know what
> tests to write to replace hardcoded return values by objects that
> perform actual work.

You have read too many books on TDD. C-:

Alternate between writing lines of test and lines of code. Run the
tests after the fewest possible edits, and always correctly predict if
the tests will pass, or will fail, and with what diagnostic. (And
configure your editor to run the stankin tests, no matter how hard it
fights you!) The high-end tricks will get easier after you get the
basic cycle down.

--
  Phlip
  http://c2.com/cgi/wiki?ZeekLand



More information about the Python-list mailing list