pallets / click

Python composable command line interface toolkit
https://click.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
15.76k stars 1.4k forks source link

Testing global exception handling with CliRunner #1547

Closed StopMotionCuber closed 4 years ago

StopMotionCuber commented 4 years ago

Hello everyone,

I'm having an issue with testing my click application that has a custom exception handler with click. I would like to use the CliRunner to test custom exception handling with click. Therefore I'm using a setup similar to the one found below.

Execute this script below with the parameter action (e.g. python3 script_name.py action) to reproduce this error.

Also I'd like to ask if this is the correct way to handle global exceptions. For me it does not make sense to handle the error in each subcommand, when there is e.g. a connection error to the server, which will always be handled the same way.

Expected Behavior

The Exception will be handled by the global handler in both cases, leading to a stdout of

Executing manually:
Exception was catched by application
Executing with CliRunner:
Exception was catched by application

Minimal example:

import click
from click.testing import CliRunner

class ExampleError(Exception):
    pass

class GlobalExceptionHandler(click.Group):
    def __call__(self, *args, **kwargs):
        try:
            return self.main(*args, **kwargs)
        except ExampleError:
            print("Exception was catched by application")

@click.group(cls=GlobalExceptionHandler)
def cli():
    pass

@cli.command(short_help="Upload a Dockerfile or Folder to Database")
def action():
    raise ExampleError()

# Manual running
def main_1():
    cli()

# Option 2
def main_2():
    runner = CliRunner()
    runner.invoke(cli, ["action"])

if __name__ == '__main__':
    print("Executing manually:")
    main_1()
    print("Executing with CliRunner:")
    main_2()

Actual Behavior

Tell us what happens instead.

The Exception is handled when manually executing, but not when ran with CliRunner.

Executing manually:
Exception was catched by application
Executing with CliRunner:

Environment

davidism commented 4 years ago

The object returned by runner.invoke has various attributes to inspect the result, including exception.

Please use Stack Overflow for questions about your own code. This tracker is for issues related to the project itself. Be sure to include a minimal, complete, and verifiable example.