diff --git a/typer/testing.py b/typer/testing.py index 09711e66fd..def872284d 100644 --- a/typer/testing.py +++ b/typer/testing.py @@ -1,3 +1,13 @@ +"""Testing utilities for Typer applications. + +Provides a `CliRunner` that wraps Click's test runner with Typer-aware +`invoke`, so you can test `Typer` apps directly without converting them +to Click commands by hand. + +Read more in the +[Typer docs for Testing](https://typer.tiangolo.com/tutorial/testing/). +""" + from collections.abc import Mapping, Sequence from typing import IO, Any @@ -8,6 +18,36 @@ class CliRunner(ClickCliRunner): + """A test runner for `Typer` applications. + + Extends Click's `CliRunner` with a Typer-aware `invoke` method that + accepts a `Typer` instance directly, removing the need to call + `typer.main.get_command` in every test. + + Read more in the + [Typer docs for Testing](https://typer.tiangolo.com/tutorial/testing/). + + ## Example + + ```python + from typer.testing import CliRunner + import typer + + app = typer.Typer() + + @app.command() + def hello(name: str) -> None: + typer.echo(f"Hello {name}") + + runner = CliRunner() + + def test_hello() -> None: + result = runner.invoke(app, ["World"]) + assert result.exit_code == 0 + assert "Hello World" in result.output + ``` + """ + def invoke( # type: ignore self, app: Typer, @@ -18,6 +58,14 @@ def invoke( # type: ignore color: bool = False, **extra: Any, ) -> Result: + """Invoke a `Typer` app in an isolated environment for testing. + + Converts the `Typer` instance to a Click command and delegates to + Click's `CliRunner.invoke`. + + Read more in the + [Typer docs for Testing](https://typer.tiangolo.com/tutorial/testing/). + """ use_cli = _get_command(app) return super().invoke( use_cli,