Skip to content

Commit

Permalink
feat: Added a new CLI flag: --snapshot-patch-pycharm-diff
Browse files Browse the repository at this point in the history
(Only relevant for Pycharm users) If the flag is passed, Syrupy will import and extend Pycharm's default diff script to provide more meaning full diffs when viewing snapshots mismatches in Pycharm's diff viewer
  • Loading branch information
UltimateLobster committed Jun 15, 2024
1 parent c91a5fa commit 5d80870
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 2 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,13 @@ Both options will generate equivalent snapshots but the latter is only viable wh
These are the cli options exposed to `pytest` by the plugin.

| Option | Description | Default |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| ------------------------------ |--------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| `--snapshot-update` | Snapshots will be updated to match assertions and unused snapshots will be deleted. | `False` |
| `--snapshot-details` | Includes details of unused snapshots (test name and snapshot location) in the final report. | `False` |
| `--snapshot-warn-unused` | Prints a warning on unused snapshots rather than fail the test suite. | `False` |
| `--snapshot-default-extension` | Use to change the default snapshot extension class. | [AmberSnapshotExtension](https://github.com/tophat/syrupy/blob/main/src/syrupy/extensions/amber/__init__.py) |
| `--snapshot-no-colors` | Disable test results output highlighting. Equivalent to setting the environment variables `ANSI_COLORS_DISABLED` or `NO_COLOR` | Disabled by default if not in terminal. |
| `--snapshot-patch-pycharm-diff`| Override Pycharm's default diffs viewer when looking at snapshot diffs. More information in [Using Syrupy from Pycharm] | `False` |

### Assertion Options

Expand Down Expand Up @@ -476,6 +477,21 @@ The generated snapshot:
- [JPEG image extension](https://github.com/tophat/syrupy/tree/main/tests/examples/test_custom_image_extension.py)
- [Built-in image extensions](https://github.com/tophat/syrupy/blob/main/tests/syrupy/extensions/image/test_image_svg.py)

### Viewing Snapshot Diffs in Pycharm IDEs
Pycharm IDEs come with a built-in tool that helps you to more easily identify differences between the expected result and the actual result in a test.
However, this tool does not play nicely with syrupy snapshots by default.

Fortunately, Syrupy comes with a runtime flag that will extend Pycharm's default behavior to work nicely with snapshots.
Pass the `--snapshot-patch-pycharm-diff` flag in your pytest run configuration or create a `pytest.ini` in your project with the following content:
```ini
[pytest]
addopts = --snapshot-patch-pycharm-diff

```

Now you will be able to see snapshot diffs more easily.


## Uninstalling

```python
Expand Down
78 changes: 77 additions & 1 deletion src/syrupy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import argparse
import sys
from functools import lru_cache
import warnings
from functools import (
lru_cache,
wraps,
)
from gettext import gettext
from inspect import signature
from typing import (
Any,
ContextManager,
Iterable,
List,
Optional,
)
Expand Down Expand Up @@ -85,6 +91,13 @@ def pytest_addoption(parser: Any) -> None:
dest="no_colors",
help="Disable test results output highlighting",
)
group.addoption(
"--snapshot-patch-pycharm-diff",
action="store_true",
default=False,
dest="patch_pycharm_diff",
help="Patch Pycharm diff",
)


def __terminal_color(config: Any) -> "ContextManager[None]":
Expand Down Expand Up @@ -191,3 +204,66 @@ def snapshot(request: Any) -> "SnapshotAssertion":
test_location=PyTestLocation(request.node),
session=request.session.config._syrupy,
)


@pytest.fixture(scope="session", autouse=True)
def _patch_pycharm_diff_viewer_for_snapshots(request: Any) -> Iterable[None]:
if not request.config.option.patch_pycharm_diff:
yield
return

try:
from teamcity.diff_tools import EqualsAssertionError # type: ignore
except ImportError:
warnings.warn(
"Pycharm's diff tools have failed to be imported. "
"Snapshot diffs will not be patched.",
stacklevel=2,
)
yield
return

old_init = EqualsAssertionError.__init__
old_init_signature = signature(old_init)

@wraps(old_init)
def new_init(self: EqualsAssertionError, *args: Any, **kwargs: Any) -> None:

# Extract the __init__ arguments as originally passed in order to
# process them later
parameters = old_init_signature.bind(self, *args, **kwargs)
parameters.apply_defaults()
expected = parameters.arguments["expected"]
actual = parameters.arguments["actual"]
real_exception = parameters.arguments["real_exception"]

if isinstance(expected, SnapshotAssertion):
snapshot = expected
elif isinstance(actual, SnapshotAssertion):
snapshot = actual
else:
snapshot = None

old_init(self, *args, **kwargs)

# No snapshot was involved in the assertion. Let the old logic do its
# thing.
if snapshot is None:
return

# Although a snapshot was involved in the assertion, it seems the error
# was a result of a non-assertion exception (Ex. `assert 1/0`).
# Therefore, We will not do anything here either.
if real_exception is not None:
return

assertion_result = snapshot.executions[snapshot.num_executions - 1]
if assertion_result.exception is not None:
return

self.expected = str(assertion_result.recalled_data)
self.actual = str(assertion_result.asserted_data)

EqualsAssertionError.__init__ = new_init
yield
EqualsAssertionError.__init__ = old_init

0 comments on commit 5d80870

Please sign in to comment.