Skip to content

Commit

Permalink
Merge pull request #6 from StratoDem/5-error-messages
Browse files Browse the repository at this point in the history
5 error messages
  • Loading branch information
mjclawar authored May 15, 2018
2 parents 7b4b4dc + 9fbef41 commit f615a08
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ pip-selfcheck.json
*.egg-info/
*.whl
venv/
dist/
13 changes: 0 additions & 13 deletions CHANGELOG

This file was deleted.

50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# CHANGELOG

## 1.2.0 - 2018-05-15
### Changed
- Improves clarity of error messages for large component comparisons
##### Old logic:
raise `AssertionError` with large string difference between JSON objects if the component did not match the snapshot, which led to difficult to read error message like:
```
AssertionError: {'pro[136 chars]en': 'another one'}, 'namespace': 'dash_html_c[77 chars]Div'} != {'pro[136 chars]en': [1, 2, 3]}, 'namespace': 'dash_html_compo[73 chars]Div'}
```
##### New logic:
raise `AssertionError` with large string difference between JSON objects if the component does not match the snapshot, **and**
add new details section about the **first local mismatch** between the component and snapshot:
```
DETAILS:
<class 'list'> != <class 'str'>
CONTEXT 1:
{"children": [1, 2, 3]}
CONTEXT 2:
{"children": "another one"}
```
or
```
DETAILS:
P != Span
CONTEXT 1:
{"type": "P", "props": {"children": "another one"}, "namespace": "dash_html_components"}
CONTEXT 2:
{"type": "Span", "props": {"children": "another one"}, "namespace": "dash_html_components"}
```

## 1.1.0 - 2018-04-11
### Added
- This package now checks for an environment variable (UPDATE_DASH_SNAPSHOTS) and will automatically overwrite snapshots if it is set to TRUE

## 1.0.1 - 2018-03-27
### Added
- MIT License

## 1.0.0 - 2018-03-27
### Added
- Initial publication
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

setup(
name='dash-snapshot-testing',
version='1.1.0',
version='1.2.0',
author='Michael Clawar, Eric Linden',
author_email='tech@stratodem.com',
packages=['snapshot_test'],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"namespace": "dash_html_components", "type": "Div", "props": {"children": [{"namespace": "dash_html_components", "type": "P", "props": {"children": "wow"}}, {"namespace": "dash_html_components", "type": "Span", "props": {"children": "another one"}}], "id": "test-id"}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"namespace": "dash_html_components", "type": "Div", "props": {"children": [{"namespace": "dash_html_components", "type": "P", "props": {"children": "wow!"}}, {"namespace": "dash_html_components", "type": "Span", "props": {"children": "this works"}}], "id": "test-id"}}
20 changes: 20 additions & 0 deletions snapshot_test/__tests__/test_snapshot_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,23 @@ def test_component(self):
my_component = html.Div([html.P('wow'), html.Span('another one')], id='test-id')

self.assertSnapshotEqual(my_component, 'my-test-unique-id')

def test_component_2(self):
my_component = html.Div([html.P('wow'), html.P('another one')], id='test-id')

self.assertRaises(
AssertionError,
lambda: self.assertSnapshotEqual(my_component, 'my-test-unique-id'))

def test_component_3(self):
my_component = html.Div([html.P('wow'), html.Span([1, 2, 3])], id='test-id')

self.assertRaises(
AssertionError,
lambda: self.assertSnapshotEqual(my_component, 'my-test-unique-id'))

my_component = html.Div([html.P('wow'), html.Span((1, 2, 3))], id='test-id')

self.assertRaises(
AssertionError,
lambda: self.assertSnapshotEqual(my_component, 'my-test-unique-id'))
73 changes: 72 additions & 1 deletion snapshot_test/snapshot_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
import os
import plotly.utils
import unittest
from typing import Any

from dash.development.base_component import Component


__all__ = ['DashSnapshotTestCase']


class DashSnapshotMismatch(Exception):
pass


class DashSnapshotTestCase(unittest.TestCase):
snapshots_dir = None

Expand Down Expand Up @@ -60,7 +65,21 @@ def assertSnapshotEqual(self, component: Component, file_id: str) -> None:
# Load a dumped JSON for the passed-in component, to ensure matches standard format
expected_dict = json.loads(
json.dumps(component_json, cls=plotly.utils.PlotlyJSONEncoder))
self.assertEqual(self.__load_snapshot(filename=filename), expected_dict)
existing_snapshot = self.__load_snapshot(filename=filename)
try:
self.__check_object_equality(
expected_dict,
existing_snapshot,
context1=expected_dict,
context2=existing_snapshot)
except DashSnapshotMismatch as e:
self.assertEqual(
existing_snapshot,
expected_dict,
'\n\nDETAILS:\n\n{}'.format(e))
self.assertEqual(
existing_snapshot,
expected_dict)
else:
# Component did not already exist, so we'll write to the file
with open(filename, 'w') as file:
Expand Down Expand Up @@ -127,3 +146,55 @@ def __get_snapshots_dir(cls) -> str:
os.mkdir(cls.snapshots_dir)

return cls.snapshots_dir

@classmethod
def __check_object_equality(cls, obj1: Any, obj2: Any, context1: Any, context2: Any) -> None:
if type(obj1) != type(obj2):
raise DashSnapshotMismatch(
'{} != {} {}'.format(
type(obj1),
type(obj2),
cls.__create_error_context(context1, context2)))
elif isinstance(obj1, (list, tuple)):
if len(obj1) != len(obj2):
raise DashSnapshotMismatch(
'Length of object 1 ({}) does not match object 2 ({}) {}'.format(
len(obj1),
len(obj2),
cls.__create_error_context(obj1, obj2)))
else:
for obj1_element, obj2_element in zip(obj1, obj2):
cls.__check_object_equality(
obj1=obj1_element,
obj2=obj2_element,
context1=obj1,
context2=obj2)
elif isinstance(obj1, dict):
if set(obj1.keys()) != set(obj2.keys()):
raise DashSnapshotMismatch(
'Keys do not match ({} vs {}) {}'.format(
obj1.keys(),
obj2.keys(),
cls.__create_error_context(context1, context2)))
else:
for k1 in obj1.keys():
cls.__check_object_equality(
obj1=obj1[k1],
obj2=obj2[k1],
context1=obj1,
context2=obj2)
elif isinstance(obj1, (str, int, float)):
if obj1 != obj2:
raise DashSnapshotMismatch(
'{} != {} {}'.format(
obj1,
obj2,
cls.__create_error_context(context1, context2)))
else:
raise TypeError('DashSnapshotTesting does not support type {}'.format(type(obj1)))

@staticmethod
def __create_error_context(context1: Any, context2: Any) -> str:
return '\nCONTEXT 1:\n\n{}\n\nCONTEXT 2: \n\n{}'.format(
json.dumps(context1),
json.dumps(context2))

0 comments on commit f615a08

Please sign in to comment.