Opster tests

This is a test suite for opster library. Just read it to get some idea of how it works.

Actors cast

Choose python version:

$   if [ -z "$PYTHON" ]; then
>      PYTHON="python"
>   fi

Add opster to the PYTHONPATH:

$   if [ -z "$OPSTER_DIR" ]; then
>      OPSTER_DIR="$TESTDIR/.."
>   fi
>   export PYTHONPATH="$OPSTER_DIR"

Define function to make it simpler:

$ run() {
>   name=$1
>   shift
>   export COVERAGE_FILE=$TESTDIR/coverage.db
>   if [ -z "$COVERAGE" ]; then
>      "$PYTHON" "$TESTDIR/$name" "$@"
>   else
>      coverage run -a --rcfile="$TESTDIR/../.coveragerc" "$TESTDIR/$name" "$@"
>   fi
> }

Main characters:

Action

Check if usage is working:

$ run multicommands.py
usage: multicommands.py <command> [options]

commands:

 nodoc   (no help text available)
 simple  Just simple command to print keys of received arguments.

Ok, then let’s run it:

$ run multicommands.py simple
['test', 'ui']

Yeah, nice one, but we know that command complex is just hidden there. Let’s check it out:

$ run multicommands.py help complex
multicommands.py complex [-p] [--exit value] ...

That's more complex command intended to do something

    \xd0\x98 \xd1\x81\xd0\xb0\xd0\xbc\xd0\xbe\xd0\xb5 \xd0\xb3\xd0\xbb\xd0\xb0\xd0\xb2\xd0\xbd\xd0\xbe\xd0\xb5 - \xd0\xbc\xd1\x8b \xd1\x82\xd1\x83\xd1\x82 \xd0\xbd\xd0\xb5\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xb6\xd0\xb5\xd1\x87\xd0\xba\xd0\xbe \xd1\x82\xd0\xb5\xd0\xba\xd1\x81\xd1\x82\xd0\xb0 \xd0\xbd\xd0\xb5 \xd0\xb2 ascii \xd0\xbd\xd0\xb0\xd0\xbf\xd0\xb8\xd1\x88\xd0\xb5\xd0\xbc (esc)
    \xd0\xb8 \xd0\xbf\xd0\xbe\xd1\x81\xd0\xbc\xd0\xbe\xd1\x82\xd1\x80\xd0\xb8\xd0\xbc, \xd1\x87\xd1\x82\xd0\xbe \xd0\xb1\xd1\x83\xd0\xb4\xd0\xb5\xd1\x82. :) (esc)

options:

 -p --pass     don't run the command
    --exit     exit with supplied code (default: 100)
 -n --name     optional name
 -v --verbose  enable additional output
 -q --quiet    suppress output
 -h --help     display help

Check if integer errors correctly:

$ run multicommands.py complex --exit q
error: invalid option value 'q' for option 'exit'

multicommands.py complex [-p] [--exit value] ...

That's more complex command intended to do something

    \xd0\x98 \xd1\x81\xd0\xb0\xd0\xbc\xd0\xbe\xd0\xb5 \xd0\xb3\xd0\xbb\xd0\xb0\xd0\xb2\xd0\xbd\xd0\xbe\xd0\xb5 - \xd0\xbc\xd1\x8b \xd1\x82\xd1\x83\xd1\x82 \xd0\xbd\xd0\xb5\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xb6\xd0\xb5\xd1\x87\xd0\xba\xd0\xbe \xd1\x82\xd0\xb5\xd0\xba\xd1\x81\xd1\x82\xd0\xb0 \xd0\xbd\xd0\xb5 \xd0\xb2 ascii \xd0\xbd\xd0\xb0\xd0\xbf\xd0\xb8\xd1\x88\xd0\xb5\xd0\xbc (esc)
    \xd0\xb8 \xd0\xbf\xd0\xbe\xd1\x81\xd0\xbc\xd0\xbe\xd1\x82\xd1\x80\xd0\xb8\xd0\xbc, \xd1\x87\xd1\x82\xd0\xbe \xd0\xb1\xd1\x83\xd0\xb4\xd0\xb5\xd1\x82. :) (esc)

options:

 -p --pass     don't run the command
    --exit     exit with supplied code (default: 100)
 -n --name     optional name
 -v --verbose  enable additional output
 -q --quiet    suppress output
 -h --help     display help

Opster can parse non-global options after the command argument:

$ run multicommands.py complex --name dave
write
info
warn
[100]

We also get the right command when using –opt=value syntax:

$ run multicommands.py complex --name=dave
write
info
warn
[100]

Global options can appear before the command argument.

$ run multicommands.py –quiet complex write warn [100]

However, non-global options before the command argument are not allowed:

$ run multicommands.py --name=dave complex
error: option --name not recognized

usage: multicommands.py <command> [options]

commands:

 help    Show help for a given help topic or a help overview.
 nodoc   (no help text available)
 simple  Just simple command to print keys of received arguments.

regardless of which syntax you use:

$ run multicommands.py --name dave complex
error: option --name not recognized

usage: multicommands.py <command> [options]

commands:

 help    Show help for a given help topic or a help overview.
 nodoc   (no help text available)
 simple  Just simple command to print keys of received arguments.

Opster won’t accidentally run the simple command because you tried to pass simple as an argument to the –name option:

$ run multicommands.py --name simple complex
error: option --name not recognized

usage: multicommands.py <command> [options]

commands:

 help    Show help for a given help topic or a help overview.
 nodoc   (no help text available)
 simple  Just simple command to print keys of received arguments.

We also have completion:

$ run multicommands.py _completion
# opster bash completion start
_opster_completion()
{
    COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \
                   COMP_CWORD=$COMP_CWORD \
                   OPSTER_AUTO_COMPLETE=1 $1 ) )
}
complete -o default -F _opster_completion multicommands.py
# opster bash completion end

Now we’re going to test if a script with a single command will work (not everyone needs subcommands, you know):

$ run test_opts.py
test_opts.py: invalid arguments

test_opts.py [-l HOST] DIR

Command with option declaration as keyword arguments

options:

 -l --listen       ip to listen on (default: localhost)
 -p --port         port to listen on (default: 8000)
 -d --daemonize    daemonize process
    --pid-file     name of file to write process ID to
 -D --definitions  just some definitions
 -t --test         testing help for a function (default: test)
 -h --help         display help

Yeah, I’ve got it, I should supply some arguments:

$ run test_opts.py -d -p 5656 --listen anywhere right-here
{'daemonize': True,
 'definitions': {},
 'dirname': 'right-here',
 'listen': 'anywhere',
 'pid_file': '',
 'port': 5656,
 'test': 'test'}

Now let’s test our definitions:

$ run test_opts.py -D a=b so-what?
{'daemonize': False,
 'definitions': {'a': 'b'},
 'dirname': 'so-what?',
 'listen': 'localhost',
 'pid_file': '',
 'port': 8000,
 'test': 'test'}

As long as only the last option has a parameter We can combine short options into one argument:

$ run test_opts.py -dDa=b so-what?
{'daemonize': True,
 'definitions': {'a': 'b'},
 'dirname': 'so-what?',
 'listen': 'localhost',
 'pid_file': '',
 'port': 8000,
 'test': 'test'}

The parameter can be in a separate argument:

$ run test_opts.py -dD a=b so-what?
{'daemonize': True,
 'definitions': {'a': 'b'},
 'dirname': 'so-what?',
 'listen': 'localhost',
 'pid_file': '',
 'port': 8000,
 'test': 'test'}

$ run test_opts.py -D can-i-haz fail?
error: wrong definition: 'can-i-haz' (should be in format KEY=VALUE)

test_opts.py [-l HOST] DIR

Command with option declaration as keyword arguments

options:

 -l --listen       ip to listen on (default: localhost)
 -p --port         port to listen on (default: 8000)
 -d --daemonize    daemonize process
    --pid-file     name of file to write process ID to
 -D --definitions  just some definitions
 -t --test         testing help for a function (default: test)
 -h --help         display help

Should we check passing some invalid arguments? I think so:

$ run test_opts.py --wrong-option
error: option --wrong-option not recognized

test_opts.py [-l HOST] DIR

Command with option declaration as keyword arguments

options:

 -l --listen       ip to listen on (default: localhost)
 -p --port         port to listen on (default: 8000)
 -d --daemonize    daemonize process
    --pid-file     name of file to write process ID to
 -D --definitions  just some definitions
 -t --test         testing help for a function (default: test)
 -h --help         display help

Another things should be checked: calling help display from the function itself:

$ run selfhelp.py --assist
selfhelp.py [OPTIONS]

Displays ability to show help

options:

    --assist  show help
 -h --help    display help

Are we getting nicely stripped body when not following subject/body convention of writing commands?

$ run hello.py --help
hello.py [OPTIONS] NAME [TIMES]

Hello world continues the long established tradition
of delivering simple, but working programs in all
kinds of programming languages.

This tests different docstring formatting (just text instead of having
subject and body).

options:

 -g --greeting  Greeting to use (default: Hello)
 -h --help      display help

There is no problems with having required and optional arguments at the same time:

$ run hello.py stranger
Hello stranger
$ run hello.py stranger 2 -g 'Good bye'
Good bye stranger
Good bye stranger
$ run hello.py stranger -g 'Good bye' 2
Good bye stranger
Good bye stranger

There is no problems with TypeError: function() got multiple values for keyword argument 'option':

$ run multivalueserr.py some arguments hehe
I work! False bopt some arguments ('hehe',)

Scripts can exit with an error message at any time by raising command.Error:

$ run quit.py --algorithm=quick
unrecognised algorithm "quick"

That’s all for today; see you next time!

There is no problems with handling variable argumentrs and underscores:

$ run varargs.py --test-option test1 var1 var2
{'args': ('var1', 'var2'), 'test_option': 'test1'}
$ run varargs.py var1 var2
{'args': ('var1', 'var2'), 'test_option': 'test'}

We can have an option that uses the ‘-h’ short name (although we use it as a short name for ‘–help’:

$ run ls.py --help
ls.py [-h]

(no help text available)

options:

 -h --human  Pretty print filesizes
    --help   display help

Project Versions

Table Of Contents

Previous topic

API

This Page