Skip to content
Become a
Sponsor or follow @15r10nk on
or
for updates

# Testing

`inline_snapshot.testing` provides tools that can be used to test inline-snapshot workflows. This might be useful if you want to build your own libraries based on inline-snapshot.

The following example shows how you can use the `Example` class to test what inline-snapshot would do with the given source code. The snapshots in the argument are asserted inside the `run_*` methods. Some arguments are optional, and some are required. Please see the reference below for details.

    from inline_snapshot import snapshot
    from inline_snapshot.testing import Example

    def test_something():

        Example(
            {
                "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot()
    """
            }
        ).run_pytest(  # run with the create flag and check the changed files
            ["--inline-snapshot=create"],
            changed_files=snapshot(),
        )

Inline-snapshot will then populate the empty snapshots.

    from inline_snapshot import snapshot
    from inline_snapshot.testing import Example

    def test_something():

        Example(
            {
                "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot()
    """
            }
        ).run_pytest(  # run with the create flag and check the changed files
            ["--inline-snapshot=create"],
            changed_files=snapshot(
                {
                    "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot(2)
    """
                }
            ),
            returncode=1,
            outcomes={"passed": 1, "errors": 1},
        )

The `Example` object is immutable and not connected to any directory. A temporary directory is only created when you call a `run_*` method. The result of the `run_*` method is always a new `Example` object with the updated files. This means that you can create an `Example` and call the `run_*` methods on it in any order you want, with the arguments that are useful for your test case.

This allows for more complex tests where you create one example and perform multiple test runs on it. Every test run will work on the changed files from the previous one.

    from inline_snapshot import snapshot
    from inline_snapshot.testing import Example

    def test_something():

        Example(
            {
                "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot()
        assert 1+5 == snapshot(2)
    """
            }
        ).run_pytest(  # run with the create flag and check the changed files
            ["--inline-snapshot=create"],
            changed_files=snapshot(
                {
                    "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot(2)
        assert 1+5 == snapshot(2)
    """
                }
            ),
            returncode=1,
            outcomes={"passed": 1, "errors": 1},
        ).run_pytest(  # run with the create flag and check the changed files
            ["--inline-snapshot=fix"],
            changed_files=snapshot(
                {
                    "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot(2)
        assert 1+5 == snapshot(6)
    """
                }
            ),
            returncode=1,
            outcomes={"passed": 1, "errors": 1},
        )

You can also use the same example multiple times and call different methods on it.

    from inline_snapshot import snapshot
    from inline_snapshot.testing import Example

    def test_something():

        e = Example(
            {
                "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot()
        assert 1+5 == snapshot(2)
    """
            }
        )
        e.run_inline(  # run without flags
            reported_categories={"create", "fix"}, raises="AssertionError"
        )

        e.run_pytest(
            ["--inline-snapshot=short-report"],  # check the pytest report
            changed_files=snapshot({}),
            report=snapshot(
                """\
    Error: one snapshot has incorrect values (--inline-snapshot=fix)
    Error: one snapshot is missing a value (--inline-snapshot=create)
    You can also use --inline-snapshot=review to approve the changes interactively\
    """
            ),
            returncode=1,
            error="""\
    >       assert 1+5 == snapshot(2)
    E       assert (1 + 5) == 2
    E        +  where 2 = snapshot(2)
    """,
            outcomes={"failed": 1, "errors": 1},
        )
        e.run_pytest(  # run with the create flag and check the changed files
            ["--inline-snapshot=create"],
            changed_files=snapshot(
                {
                    "test_a.py": """\
    from inline_snapshot import snapshot
    def test_a():
        assert 1+1 == snapshot(2)
        assert 1+5 == snapshot(2)
    """
                }
            ),
            returncode=1,
            outcomes={"passed": 1, "errors": 1},
        )

## API

### `` `Example`

#### `` `__init__(files)`

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`files` | `str | bytes | dict[str, str | bytes]` | a collection of files which are used as your example project, or just a string which will be saved as tests/test_something.py. | required

#### `` `change_code(mapping)`

Changes example tests by mapping every file with the given function.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`mapping` | `Callable[[str], str]` | function to apply to each file's content. | required

#### `` `format(filename='tests/test_something.py')`

Formats a Python file using black.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`filename` | `str` | the file to format (default: "tests/test_something.py"). | `'tests/test_something.py'`

#### `` `is_formatted(filename='tests/test_something.py')`

Checks if a Python file is properly formatted with black.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`filename` | `str` | the file to check (default: "tests/test_something.py"). | `'tests/test_something.py'`

#### `` `read_file(filename)`

Reads a file from the example.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`filename` | `str` | the filename. | required

#### `` `remove_file(filename)`

Removes a file from the example.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`filename` | `str` | the file to be removed. | required

#### `` `replace(old_text, new_text)`

Changes example tests by replacing old_text with new_text.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`old_text` | `str` | the text to be replaced. | required
`new_text` | `str` | the new text to use instead. | required

#### `` `run_inline(args=[], *, context_managers=(), reported_categories=None, changed_files={}, report=None, raises='<no exception>', stderr='')`

Execute the example files in process and run every `test_*` function.

This is useful for fast test execution.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`args` | `list[str]` | inline-snapshot arguments (supports only "--inline-snapshot=fix|create|..."). | `[]`
`context_managers` | `Sequence[ContextManager]` | list of context managers to use when the code is executed. | `()`
`reported_categories` | `SnapshotArg[set[Category]] | None` | snapshot of categories which inline-snapshot thinks could be applied or `None` when they are equal to the CLI flags. | `None`
`changed_files` | `SnapshotArg[dict[str, str]]` | snapshot of files which are changed by this run. | `{}`
`raises` | `SnapshotArg[str]` | snapshot of the exception raised during test execution. Required if your code raises an exception. | `'<no exception>'`

Returns:

Type | Description
--- | ---
`Example` | A new Example instance containing the changed files.

#### `` `run_pytest(args=[], *, term_columns=80, env={}, changed_files={}, report=None, error='', stderr='', returncode=0, stdin=b'', outcomes={'passed': 1})`

Run pytest with the given args and environment variables in a separate process.

It can be used to test the interaction between your code and pytest, but it is a bit slower than `run_inline`.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`args` | `list[str]` | pytest arguments like "--inline-snapshot=fix" | `[]`
`env` | `dict[str, str]` | dict of environment variables | `{}`
`changed_files` | `SnapshotArg[dict[str, str]]` | snapshot of files changed by this run. | `{}`
`report` | `Snapshot[str] | None` | snapshot of the report at the end of the pytest run. | `None`
`stderr` | `SnapshotArg[str]` | pytest stderr output | `''`
`returncode` | `SnapshotArg[int]` | snapshot of the pytest return code. | `0`

Returns:

Type | Description
--- | ---
`Example` | A new Example instance containing the changed files.

#### `` `with_files(extra_files)`

Adds extra files to the example.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`extra_files` | `dict[str, str | bytes]` | dictionary of filenames and file contents. | required