Is this a good way to implement testing

Peter Otten __peter__ at web.de
Sun May 3 05:22:19 EDT 2015


Terry Reedy wrote:

> On 5/2/2015 6:29 PM, Cecil Westerhof wrote:
> 
>> At the moment I define the test functionality in the following way:
> 
> Any automated testing is better than none.  For idlelib, I use unittest.
>   For an individual project with specialized needs, I use a custom test
> framework tuned to those needs.
> 
>>          else:
>>              action = options[0][0]
>>              if   action == '--all':
>>                  do_all          = True
>>              elif action == '--factorial':
>>                  do_factorial    = True
>>              elif action == '--fibonacci':
>>                  do_fibonacci    = True
>>              elif action == '--happy':
>>                  do_happy        = True
>>              elif action == '--lucky':
>>                  do_lucky        = True
>>              else:
>>                  print >> sys.stderr, progname + ': Unhandled parameter '
>>                  + action sys.exit(1)
> 
> There is usually a way to factor out the duplication of repetitive code
> like this.  

> Often, a dict is somehow involved. 

That cannot be stressed enough. In Python if you test against multiple 
constant values you should always consider a dict-based approach.

Also, you should not shy away from using functions as variables. Instead of

do_lucky = True
...
if do_lucky:
    do_lucky_func()

you can often write something more direct

action = do_lucky_func
...
action_func()

> I believe the following
> is equivalent to the above.
> 
> else:
>    action = options[0][0]
>    try:
>      globals()['do_'+action[2:]] = True
>    except KeyError:
>      print >> sys.stderr, progname + ': Unhandled parameter ' + action
>      sys.exit(1)

To go a bit farther down that path of using naming conventions, dict instead 
of extensive if ... elif ... and functions instead of flags here's a 
complete implementation with argparse:

$ python3 choose_action.py -h
usage: choose_action.py [-h] [{all,fibonacci,factorial}]

positional arguments:
  {all,fibonacci,factorial}
                        Known actions: all, fibonacci, factorial

optional arguments:
  -h, --help            show this help message and exit
$ python3 choose_action.py all
fibonacci
factorial
$ python3 choose_action.py
factorial
fibonacci
$ python3 choose_action.py fibonacci
fibonacci
$ python3 choose_action.py non-existent
usage: choose_action.py [-h] [{all,factorial,fibonacci}]
choose_action.py: error: argument action: invalid choice: 'non-existent' 
(choose from 'all', 'factorial', 'fibonacci')


$ cat choose_action.py
import argparse


def do_factorial():
    print("factorial")
    # ...


def do_fibonacci():
    print("fibonacci")
    # ...


def do_all():
    for name, action in lookup.items():
        if name != "all":
            action()

lookup = {
    name[3:]: func
    for name, func in globals().items()
    if name.startswith("do_")
}

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "action",
        nargs="?",
        default="all",
        choices=lookup,
        help="Known actions: %(choices)s")
    args = parser.parse_args()

    lookup[args.action]()
$ 





More information about the Python-list mailing list