Classic OOP in Python

Steven D'Aprano steve at pearwood.info
Wed Jun 17 18:58:38 EDT 2015


On Thu, 18 Jun 2015 06:39 am, Marko Rauhamaa wrote:

> Ned Batchelder <ned at nedbatchelder.com>:
> 
>> TDD is about writing tests as a way to design the best system, and
>> putting testing at the center of your development workflow. It works
>> great with Python even without interfaces.
> 
> I wonder how great it really is. Testing is important, that's for sure,
> but to make it a dogmatic starting point of development is not that
> convincing.
> 
> The way it was explained to me was that in TDD you actually don't write
> code to any requirements or design: you simply do the least to pass the
> tests.

You still need requirements and a design. Otherwise how do you know what
tests you need to write?


> Thus, say you need to write a program that inputs a string and 
> outputs the same string surrounded by parentheses (the requirement), the
> starting point might be this test case:
> 
>    - run the program
>    - give it the word "hello" as input
>    - check that the program prints out "(hello)"
>
> The right TDD thing would be to satisfy the test with this program:
> 
>    input()
>    print("(hello)")
> 
> That *ought* to be the first version of the program until further test
> cases are added that invalidate it.

That's certainly the more pedantic approach of TDD proponents. But frankly I
expect that outside of TDD tutorials, nobody *really* starts off that small
in practice. I know I don't.

I would start with this function, and a separate test suite:


# === application.py ===
def bracket(s):
    """Return string s bracketed in parentheses.

    >>> bracket("Hello")
    '(Hello)'

    """
    return "(%s)" % s


# === test_application.py ===
import application

import doctest
import unittest

def load_tests(loader, tests, ignore):
    tests.addTests(doctest.DocTestSuite())
    tests.addTests(doctest.DocTestSuite(application))
    return tests


if __name__ == '__main__':
    unittest.main()


Then call 

python test_application.py


to run the tests. Or even skip the test suite and just call 

python -m doctest application.py


And from there, I would build up extra doc tests and unit tests as needed.

The point is, I don't believe that there is any *necessity* to write
deliberately failing tests for *trivial* functions that are only one or two
lines. You can practically see that the function is correct without even a
test. Deliberately making it fail has only one advantage:

* Getting you used to failing tests and learning that they aren't in and of
themselves a bad thing or something to be ashamed of;

* Instilling the discipline to actually write tests.

Er, that's two advantages.

But really, in practice, how many trivial one liner functions do you end up
writing, as a percentage of your entire application? Unless the app is
pretty simple, chances are that percentage is very small.



-- 
Steven




More information about the Python-list mailing list