I agree in part with both of you. I think some kinds of code is
difficult to test without significant test harnessing that is hard to
set up in the doctest format. This especially tends to be the case
with tests of code that touch external resources, such as networks or
databases, that you might prefer to mock for the purposes of unit
testing. Fortunately I haven't personally run into too many examples
like that in Sage, but I'm sure they exist. Doctests can also make
testing some numerical results tricky, but Sage's doctest checker has
already implemented the usual workarounds for that (parsing floats,
etc.)
As to whether or not private functions / methods should have their own
tests, I'm split. I think the "EXAMPLES" section is genuinely useful,
even for code that only programmers will see. But I have also seen
examples like Jeroen has mentioned of literally copy/pasting entire
test sequences just to satisfy this, which is completely pointless and
not useful for example purposes either. I can't find a specific
example right now but it will be things like:
def public_function():
"""
<Tests for public function>
"""
with some_context_manager_that_was_probably_added_later():
_private_implementation_of_public_function()
def _private_implementation_of_public_function():
"""
<Exact copy of tests for public_function, because hey those tests
cover this function too>
"""
and that's just silly.
Personally, when I'm writing unit tests, I will *rarely* write unit
tests specifically for private functions/methods if that code is
covered by the tests for public functions. Although I'm not a TDD
evangelist, tests for the public functions tend to be a more valuable
use of one's time, because they ensure that the public interface works
as intended, and public interfaces are less subject to change.
Whereas private functions are usually implementation details that are
highly subject to change, and there are diminishing returns in writing
specific tests for them when they are covered by the public function
tests.
That said, there are cases where if a private function is complicated
enough on its own, or is used in a complicated way by functions that
are complicated on their own, sometimes it's worth having tests for
it. One has to use their judgement, along with *line* profiling to
see if the most important bits are being covered.
If you're really concerned about keeping a number looking good, most
linting and profiling tools have a way to exclude lines (in Python
this is usually a comment like "# noqa") for those rare exceptions to
whatever rules you're otherwise trying to stick to.