Why does python not have a mechanism for data hiding?

Ben Finney bignose+hates-spam at benfinney.id.au
Wed Jun 4 07:55:38 CEST 2008


Marc 'BlackJack' Rintsch <bj_666 at gmx.net> writes:

> On Wed, 04 Jun 2008 13:50:42 +1000, Ben Finney wrote:
> 
> > It seems you [alex23] have a different idea of what unit testing
> > is for from me.
> 
> For me it's about finding bugs where documentation and
> implementation disagree.

Where "documentation" is "specified externally-visible behaviour of
the unit", I agree with this.

> And if you document private functions

By definition, "private" functions are not part of the publicly
documented behaviour of the unit. Any behaviour exhibited by some
private component is seen externally as a behaviour of some public
component.

> it makes sense to me to also test if they work as documented.

If they affect the behaviour of some public component, that's where
the documentation should be.

If they *don't* affect the external behaviour, then they shouldn't be
there :-) Or, at least, their behaviour shouldn't be asserted as part
of the tests of external behaviour.

> Because the official API relies on the correct implementation of the
> private parts it uses under the hood.

Only to the extent that the documented behaviour of the API is
affected. The main benefit of marking something as "not public" is
that one *is* free to change its behaviour, so long as the public API
is preserved.

> One part of writing unit tests is invoking functions with arguments
> that you think are "corner cases". For example test if a function
> that takes a list doesn't bomb out when you feed the empty list into
> it. Or if it handles all errors correctly.

This sounds like part of the externally-visible behaviour of the code
unit; i.e. something that belongs in the public API. I agree that this
is the domain of a unit test.

> If a function `f()` calls internally `_g()` and that function might
> even call other private functions, then you have to know how `f()`
> works internally to create input that checks if error handling in
> `_g()` works correctly.

No, you don't need to know how it works internally; you need only know
what guarantees it must keep for its external behaviour.

If someone wants to alter the `_g()` function, or remove it entirely
while preserving the correct behaviour of `f()`, that should have no
effect on the external behaviour of `f()`.

That is to say, the knowledge of the "internals" of `f()` in your
example is actually knowledge of something that should be documented
as part of the external behaviour of `f()` — that, or it's not
relevant to the behaviour of `f()` and shouldn't be unit tested in
order that encapsulation is preserved.

> What do you do in such a situation? Build something from untested
> private parts and just test the assembled piece?

Assert the corner-case behaviour of `f()`, through unit tests that
operate on `f()` without caring about its internals.

> I prefer to test the private functions too. After all the private
> functions are not private to the everybody, there *are* functions
> that rely on them working correctly.

Then for *those* interfaces, unit tests can be devised that make
assertions about those interfaces.

-- 
 \       "[T]he speed of response of the internet will re-introduce us |
  `\    to that from which our political systems have separated us for |
_o__) so long, the consequences of our own actions."  -- Douglas Adams |
Ben Finney



More information about the Python-list mailing list