doctests for interactive functions

Neil Cerutti horpner at yahoo.com
Fri Feb 9 09:52:36 EST 2007


On 2007-02-08, Brian van den Broek <broek at cc.umanitoba.ca> wrote:
> Can I run the rough structure of my code past you to see if it
> is in the vicinity of what you mean? (I have removed some
> details for sake of a short(er :-)) post.)

Yes, this is a good way to think about it. Separate input from
validation. The downside is that control flow grows warts.

> My .get method looks like:
>
> def get(self, input_function=raw_input):
>      while True:
>          self._prompt_user()
>          self._input = input_function()
>          if self._is_valid_input():
>              break
>          else:
>              self._process_invalid_input()
>      self._set_data()
>
> The base class ._prompt_user just displays a prompt. Individual
> subclasses might implement ._prompt_user to both display a
> prompt, and further information about constraints on valid
> inputs, or generate a menu of options on the fly, etc.
>
> Subclasses implement ._is_valid_input to return True if the
> input meets the desired constraints, False otherwise. So,
> YesNo._is_valid_input ensures that ._input.lower() is in ['y',
> 'n', 'yes', 'no'], for instance.

Your scheme may run into trouble with unexpected end of file when
input_function is not raw_input. File methods don't raise an
exception for EOF, they just return "", the empty string. So you
may need to check of that return value, and raise IOError for
that case.

> ._process_invalid_input is implemented to provide useful
> feedback about invalid input. So,
> YesNo._process_invalid_input() emits a reminder that a value in
> ['y', 'n', 'yes', 'no'] is needed, for instance.
>
> ._set_data is usually implemented to just store the user's
> input as .data, but in some cases, it first subjects it to
> further processing. For instance YesNo._set_data sets .data to
> True if the user entered a yes value, False if they entered a
> no value.
>
> Is this the sort of thing you mean, or is this the sort of
> coupling you suggest I avoid?

It has to be coupled somewhere. This seems like a good place to
do it. The private methods can all be tested individually, so the
doctests for get can be quite simple, or even absent.

Note that sequestering the test input in a file doesn't allow for
good examples, unfortunately.

-- 
Neil Cerutti



More information about the Python-list mailing list