hyllos hyllos - 1 month ago 11
Python Question

How can I pass a ctx (Context) to CliRunner?

CliRunner
lists no parameter to provide a context in its documentation.

The following should qualify as a minimum working example.
The real problem is a bit different.
It could be solved by moving the click decorated function into its own function for test coverage. Then the click function would be rendered almost useless.

import click
from click.testing import CliRunner

class Config():
def __init__(self):
self.value = 651

@click.command()
@click.pass_context
def print_numberinfo(ctx):
if not hasattr(ctx.obj, 'value'):
ctx.obj = Config()
click.echo(ctx.obj.value)

def test_print_numberinfo():
ctx = click.Context(print_numberinfo, obj = Config())
ctx.obj.value = 777
runner = CliRunner()
# how do I pass ctx to runner.invoke?
result = runner.invoke(print_numberinfo)
assert result.output == str(ctx.obj.value) + '\n'

Answer

You would directly pass your Config instance as keyword argument obj to runner.invoke:

import click
from click.testing import CliRunner

class Config():
    def __init__(self):
        self.value = 651

@click.command()
@click.pass_context
def print_numberinfo(ctx):
    if not hasattr(ctx.obj, 'value'):
        ctx.obj = Config()
    click.echo(ctx.obj.value)

def test_print_numberinfo():
    obj = Config()
    obj.value = 777
    runner = CliRunner()
    # how do I pass ctx to runner.invoke?
    result = runner.invoke(print_numberinfo, obj=obj)
    assert result.output == str(obj.value) + '\n'