7

I am working on a command-line shell, and I'm trying to test some functions that parse command arguments.

parser.py:

import shlex
import click


def process_cmd(args, called_self=False):
    result = args

    # Replace aliases
    if not called_self:
        aliases = click.get_current_context().obj.config['ALIASES']
        if result[0] in aliases:
            substitution = process_cmd(split_args(aliases[result[0]]), True)
            if len(result) == 1:
                result = substitution
            else:
                result = substitution + result[1:]

    return result


def split_pipeline(args):
    cmd = []
    for arg in args:
        if arg == '|':
            yield process_cmd(cmd)
            cmd = []
        else:
            cmd.append(arg)
    # yield the last part of the pipeline
    yield process_cmd(cmd)

This is a unit test I wrote for split_pipeline:

import parser

def test_pipeline():
    args = ['1', '2', '|', '3', '|', '4']
    result = [i for i in parser.split_pipeline(args)]
    assert result == [['1', '2'], ['3'], ['4']]

When this unit test is run, I get an error saying that there is no active Click context.

0

2 Answers 2

7

The click library Context() object can be used as a Python context. So to set an active context in a test, you can simply do:

with ctx:
    ....

To create a Context to test with, you can instantiate one like:

ctx = click.Context(a_click_command, obj=my_context_object)

Test Code:

import click


def process_cmd():
    click.echo(click.get_current_context().obj['prop'])


def test_with_context():
    ctx = click.Context(click.Command('cmd'), obj={'prop': 'A Context'})
    with ctx:
        process_cmd()

test_with_context()

Results:

A Context
Sign up to request clarification or add additional context in comments.

1 Comment

I made a pytest fixture which returns a Click context
0

For those using mocks, it is possible to also push a Mock context using the following:

from unittest.mock import MagicMock
from click.globals import push_context

def test_foo():
    ctx = MagicMock()
    push_context(ctx)
    
    # subsequent calls will use the mocked ctx

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.