Skip to content

Commit

Permalink
docs: documented new features
Browse files Browse the repository at this point in the history
  • Loading branch information
15r10nk committed Dec 7, 2024
1 parent 68100a6 commit acf1877
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 27 deletions.
20 changes: 13 additions & 7 deletions docs/customize_repr.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

`repr()` can be used to convert a python object into a source code representation of the object, but this does not work for every type.
Here are some examples:

```pycon
>>> repr(int)
"<class 'int'>"
Expand Down Expand Up @@ -58,16 +59,14 @@ for name, obj in sorted(
print(f"- `{name}`")
```

Container types like `dict` or `dataclass` need a special implementation because it is necessary that the implementation uses `repr()` for the child elements.
!!! note
Container types like `dict`, `list`, `tuple` or `dataclass` are handled in a different way, because inline-snapshot also needs to inspect these types to implement [unmanaged](/eq_snapshot.md#unmanaged-snapshot-values) snapshot values.


``` python exec="1" result="python"
print('--8<-- "src/inline_snapshot/_code_repr.py:list"')
```

!!! note
using `#!python f"{obj!r}"` or `#!c PyObject_Repr()` will not work, because inline-snapshot replaces `#!python builtins.repr` during the code generation.

## customize

## customize recursive repr

You can also use `repr()` inside `__repr__()`, if you want to make your own type compatible with inline-snapshot.

Expand Down Expand Up @@ -102,6 +101,13 @@ def test_enum():
assert Pair(E.a, [E.b]) == snapshot(Pair(E.a, [E.b]))
```

!!! note
using `#!python f"{obj!r}"` or `#!c PyObject_Repr()` will not work, because inline-snapshot replaces `#!python builtins.repr` during the code generation. The only way to use the custom repr implementation is to use the `repr()` function.

!!! note
This implementation allows inline-snapshot to use the custom `repr()` recursively, but it does not allow you to use [unmanaged](/eq_snapshot.md#unmanaged-snapshot-parts) snapshot values like `#!python Pair(Is(some_var),5)`


you can also customize the representation of datatypes in other libraries:

``` python
Expand Down
67 changes: 47 additions & 20 deletions docs/eq_snapshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,20 @@ Example:
def test_something():
assert 2 + 40 == snapshot(42)
```
## unmanaged snapshot parts
## unmanaged snapshot values

inline-snapshots manages everything inside `snapshot(...)`, which means that the developer should not change these parts, but there are cases where it is useful to give the developer a bit more control over the snapshot content.
inline-snapshots manages everything inside `snapshot(...)`, which means that the developer should not change these parts, but there are cases where it is useful to give the developer the control over the snapshot content back.

Therefor some types will be ignored by inline-snapshot and will **not be updated or fixed**, even if they cause tests to fail.

These types are:

* dirty-equals expression
* dynamic code inside `Is(...)`
* and snapshots inside snapshots.
* [dirty-equals](#dirty-equals) expressions,
* [dynamic code](#is) inside `Is(...)`,
* [snapshots](#inner-snapshots) inside snapshots and
* [f-strings](#f-strings).

inline-snapshot is able to handle these types inside the following containers:
inline-snapshot is able to handle these types within the following containers:

* list
* tuple
Expand All @@ -57,6 +58,8 @@ inline-snapshot is able to handle these types inside the following containers:
* attrs
-->

Other types are converted with a [customizable](customize_repr.md) `repr()` into code. It is not possible to use unmanaged snapshot values within these objects.

### dirty-equals

It might be, that larger snapshots with many lists and dictionaries contain some values which change frequently and are not relevant for the test.
Expand Down Expand Up @@ -102,9 +105,7 @@ Example:
)
```

inline-snapshot tries to change only the values that it needs to change in order to pass the equality comparison.
This allows to replace parts of the snapshot with [dirty-equals](https://dirty-equals.helpmanual.io/latest/) expressions.
This expressions are preserved even if the `==` comparison with them is `False`.
The date can be replaced with the [dirty-equals](https://dirty-equals.helpmanual.io/latest/) expressions `IsDatetime()`.

Example:

Expand Down Expand Up @@ -203,9 +204,9 @@ def test_function():
)
```

The `current_version` can now be changed without having to correct the snapshot.
The snapshot does not need to be fixed when `current_version` changes in the future, but `"page data"` will still be fixed if it changes.

`Is()` can also be used when the snapshot is evaluated multiple times.
`Is()` can also be used when the snapshot is evaluated multiple times, which is useful in loops or parametrized tests.

=== "original code"
<!-- inline-snapshot: first_block outcome-failed=1 outcome-errors=1 -->
Expand Down Expand Up @@ -234,12 +235,14 @@ The `current_version` can now be changed without having to correct the snapshot.
Snapshots can be used inside other snapshots in different use cases.

#### conditional snapshots
It is possible to describe version specific parts of snapshots by replacing the specific part with `#!python snapshot() if some_condition else snapshot()`.
It is also possible to use snapshots inside snapshots.

This is useful to describe version specific parts of snapshots by replacing the specific part with `#!python snapshot() if some_condition else snapshot()`.
The test has to be executed in each specific condition to fill the snapshots.

The following example shows how this can be used to run a tests with two different library versions:

=== "my_lib v1"
=== "my_lib.py v1"

<!-- inline-snapshot-lib: my_lib.py -->
``` python
Expand All @@ -250,7 +253,7 @@ The following example shows how this can be used to run a tests with two differe
return [{"name": "var_1", "type": "int"}]
```

=== "my_lib v2"
=== "my_lib.py v2"

<!-- inline-snapshot-lib: my_lib.py -->
``` python
Expand Down Expand Up @@ -281,9 +284,33 @@ def test_function():

The advantage of this approach is that the test uses always the correct values for each library version.

You can also extract the version logic into its own function.
<!-- inline-snapshot: create fix first_block outcome-passed=1 -->
``` python
from inline_snapshot import snapshot, Snapshot
from my_lib import version, get_schema


def version_snapshot(v1: Snapshot, v2: Snapshot):
return v1 if version < 2 else v2


def test_function():
assert get_schema() == snapshot(
[
{
"name": "var_1",
"type": version_snapshot(
v1=snapshot("int"), v2=snapshot("string")
),
}
]
)
```

#### common snapshot parts

Another usecase is the extraction of common snapshot parts into an extra snapshot:
Another use case is the extraction of common snapshot parts into an extra snapshot:

<!-- inline-snapshot: create fix first_block outcome-passed=1 -->
``` python
Expand Down Expand Up @@ -346,12 +373,12 @@ def test_get_error():
It is not required to wrap the changed value in `Is(f"...")`, because inline-snapshot knows that *f-strings* are only generated by the developer.

!!! Warning "Limitation"
inline-snapshot is currently not able to fix the string constants inside *f-strings*.
This feature is planned for a future version.
The formatted values within the *f-string* (`{__file__}` in the example above) will be treated as unmanaged snapshot values.
`Is()` will not be required in this case.
inline-snapshot is currently not able to fix the string constants within *f-strings*.

`#!python f"...{var}..."` works **currently** like `#!python Is(f"...{var}...")` and issues a warning if the value changes, giving you the opportunity to fix your f-string.

`#!python f"...{var}..."` will in the **future** work like `#!python f"...{Is(var)}"`. inline-snapshot will then be able to *fix* the string parts within the f-string.

The current implementation shows a warning which contains the new string value if the value is different to the current one.

## pytest options

Expand Down
5 changes: 5 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ theme:
media: '(prefers-color-scheme: dark)'
primary: teal

validation:
links:
absolute_links: relative_to_docs


watch:
- CONTRIBUTING.md
- CHANGELOG.md
Expand Down

0 comments on commit acf1877

Please sign in to comment.