New*_*Guy 5 python command-line-interface pytest python-click
I have a CLI application built that uses grouped commands and sub-commands. Everything is working. However, I want to ensure this continues to be the case in the future, so I want to ensure that all of my commands and sub-commands have loaded correctly.
My first thought to do this was to just run
commands = ["config", "othercommand"]
runner = CliRunner()
result = runner.invoke(cli.main)
for command in commands:
assert command in result.output
Run Code Online (Sandbox Code Playgroud)
This has a few pitfalls, from my point of view.
commands each time I add a new one. I'd love to be able to automatically generate this.config), I could get a false result. My application is laid out like this:
@click.group()
def main():
"""My entry point"""
@click.group()
def config():
"""config group"""
@config.command()
def add_config():
"""this is a subcommand to config"""
@click.group()
def othercommand():
"""othercommand group"""
@othercommand.command()
def do_thing():
"""this is a subcommand to othercommand"""
Run Code Online (Sandbox Code Playgroud)
My question: Is there a way to get a list of all commands (and sub-commands) that I can use and do this from my test suite? Preferably without all the surrounding help test so that I can eliminate false results.
可以内省 cli 以获得其结构,如下所示:
def command_tree(obj):
if isinstance(obj, click.Group):
return {name: command_tree(value)
for name, value in obj.commands.items()}
Run Code Online (Sandbox Code Playgroud)
import click
@click.group()
def main():
"""My entry point"""
@main.group()
def config():
"""config group"""
@config.command()
def add_config():
"""this is a subcommand to config"""
@main.group()
def othercommand():
"""othercommand group"""
@othercommand.command()
def do_thing():
"""this is a subcommand to othercommand"""
print(command_tree(main))
Run Code Online (Sandbox Code Playgroud)
{'config': {'add_config': None}, 'othercommand': {'do_thing': None}}
Run Code Online (Sandbox Code Playgroud)