question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

0.5.1 Breaks tests

See original GitHub issue

After upgrading from 0.5.0 -> 0.5.1, it looks like the value in the snapshot is being returning as non-serializable generator?

    def assert_equals(self, value, snapshot):
>       assert value == snapshot
E       assert <[TypeError("...x7f40bc5cd3f8> == [{'geometry': ...': 'Feature'}]
E         (pytest_assertion plugin: representation of details failed.  Probably an object has a faulty __repr__.)
E         /home/app/.local/share/virtualenvs/app-4PlAip0Q/lib/python2.7/site-packages/simplejson/encoder.py:273: TypeError: Object of type generator is not JSON serializable
E       assert <[TypeError("...x7f40c119aab8> == {'features': [...reCollection'}
E         Omitting 1 identical items, use -vv to show
E         Differing items:
E         {'features': <generator object <genexpr> at 0x7f40bc63fb90>} != {'features': [{'geometry': {'coordinates': [-0.077092051506, 51.5275860195], 'type': 'Point'}, 'properties': {'name': ..., ...], 'type': 'LineString'}, 'properties': {'distance': 608.4, 'duration': 60.0, 'name': 'Raw'}, 'type': 'Feature'}]}
E         Use -v to get the full diff

Anyone found a fix?

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:15 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
medmundscommented, Oct 15, 2020

@StoicLoofah thanks for tracking this down.

I think there is a snapshottest bug or mis-feature in CollectionFormatter.normalize:

class CollectionFormatter(TypeFormatter):
    def normalize(self, value, formatter):
        iterator = iter(value.items()) if isinstance(value, dict) else iter(value)
        # ... This line is the problem:
        return value.__class__([formatter.normalize(item) for item in iterator])

This is going to have problems with all collection subclasses that require additional parameters in their constructors. (And indeed, there’s already an override for defaultdict.)

At a minimum, CollectionFormatter.normalize should probably catch exceptions trying to re-construct a normalized object, and issue a more helpful error message (suggesting the user either convert the snapshotted object to a simpler type, or that they add a custom formatter). Ideally, snapshottest would also preflight this while writing snapshot files, so that the error is reported then, not only when comparing snapshots later.

But I’m wondering if a better fix might be to change the value.__class__(...) line to instead construct the base type the formatter writes into snapshots. E.g., CollectionFormatter(dict, format_dict).normalize(value) should just try to construct a plain dict—even if value is a DRF ReturnDict—because format_dict always just writes snapshots as plain dicts. Then we wouldn’t need all these extra custom formatters: if a formatter is willing to write a snapshot, then it really should be able to compare the same type of object to that snapshot later.

(I confess I’m getting a little lost in understanding the need for this normalize logic in the first place. It transforms the actual value being compared (not the expected snapshot value) prior to comparison. I think this was added in #82 to fix problems introduced in a bunch of other major changes between v0.5.0 and v0.5.1.)

Also, it seems like the original report from @hobochild is probably related, but I think that specific case might be covered by the fix in #116 that went into v0.6.0.

1reaction
StoicLoofahcommented, Oct 12, 2020

I was able to fix it by adding the following into my conftest.py

from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList
from snapshottest import formatter, formatters

class DrfReturnCollectionFormatter(formatters.TypeFormatter):
    def normalize(self, value, formatter):
        iterator = iter(value.items()) if isinstance(value, dict) else iter(value)
        # Added the serializer kwarg as required by ReturnDict or ReturnList
        return value.__class__([formatter.normalize(item) for item in iterator],
                               serializer=None)

formatter.Formatter.register_formatter(DrfReturnCollectionFormatter(ReturnDict,
                                                                    formatters.format_dict))
formatter.Formatter.register_formatter(DrfReturnCollectionFormatter(ReturnList,
                                                                    formatters.format_list))

Not sure how you guys want to handle this since it’s an upstream issue but figured I would let you know how I addressed it!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Bone Density Test, Osteoporosis Screening & T-score ...
This is used to diagnose osteoporosis BEFORE you break a bone, help to estimate your chances of breaking a bone in the future,...
Read more >
Wald-Type Tests for Detecting Breaks in the Trend Function of ...
In this paper, test statistics for detecting a break at an unknown date in the trend function of a dynamic univariate time series...
Read more >
SCoV-2 Ag Detect™ Rapid Self -Test Instructions - FDA
IMPORTANT! Hold swab close to the tip so it does not break when putting in the test. IMPORTANT! Invalid or incorrect results can...
Read more >
A narrative review of manual muscle testing and implications ...
Applied kinesiologists use submaximal manual break tests and a binary grading scale to test short-term changes in muscle function in response to challenges....
Read more >
Six Minute Walk Test / 6 Minute Walk Test - Physiopedia
The six minute walking test (6MWT) was developed by the American Thoracic Society and it was officially introduced in 2002, coming along with...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found