# Testing You can **certainly** just directly call any invoke functions directly, manually constructing and providing arguments yourself. You can also just directly call [cappa.parse](cappa.parse) or [cappa.invoke](cappa.invoke) yourself, with relatively little effort. However, Cappa comes with a built in [CommandRunner](cappa.testing.CommandRunner) which is meant to reduce the verbosity of testing CLI commands and in overriding upstream [Dep](cappa.Dep). With it, you can centralize any always-used options, such that only the options which vary from test to test are provided inside the test bodies.. ```{eval-rst} .. autoapimodule:: cappa.testing :members: CommandRunner, RunnerArgs :noindex: ``` ## Pytest Cappa does not come with a built in pytest fixture because we assume that any test suite which might benefit from a fixture will likely have other fixture dependencies. Most users will want to customize the construction of their `CommandRunner`, if they're going to use one at all. It is very straightforward to define you own fixture to produce an appropriately configured runner. For example, let us describe a base CLI which depends upon an [Explicit Dependency](./invoke.md#explicit-dependencies) on a configuration dictionary which pulls data from the environment; which you need to override in a fixture to work with the rest of your testing structure. ```{note} See [Invoke dependency overrides](./invoke.md#overriding-dependencies) for additional details. ``` Your existing code might look like this: ```python import os from typing import Annotated import cappa def config() -> dict: return { "env": os.getenv("ENV") "foo": os.getenv("FOO") } def fn(config: Annotated[dict, cappa.Dep(config)]): print(config) @cappa.command(invoke=fn) class CLI: name: str ``` In your tests, you've decided you want to hard-code a specific alternative `config` value. You could define a pytest fixture like so: ```python import pytest from cappa.testing import CommandRunner from package import CLI, config @pytest.fixture def runner(): # Note `runner` could itself depend on other fixtures, in more complex scenarios return CommandRunner(CLI, deps={config: {"env": "test", "foo": "bar"}}) # OR def stub_config() -> dict: return { "env": "test" "foo": "bar" } @pytest.fixture def runner(): return CommandRunner(CLI, deps={config: cappa.Dep(stub_config)}) ``` Then your tests will be able to omit most configuration, except for the item under test: ```python def test_foo(runner: CommandRunner): runner.invoke('name!') ```