Rework tests.
This commit is contained in:
98
jsonpatch.py
98
jsonpatch.py
@@ -51,11 +51,14 @@ class JsonPatchConflict(JsonPatchException):
|
||||
|
||||
|
||||
def apply_patch(doc, patch):
|
||||
"""
|
||||
>>> obj = { 'baz': 'qux', 'foo': 'bar' }
|
||||
>>> patch = [ { 'remove': '/baz' } ]
|
||||
>>> apply_patch(obj, patch)
|
||||
{'foo': 'bar'}
|
||||
""" Apply list of patches to specified json document.
|
||||
|
||||
>>> doc = {'foo': 'bar'}
|
||||
>>> other = apply_patch(doc, [{'add': '/baz', 'value': 'qux'}])
|
||||
>>> doc is other
|
||||
True
|
||||
>>> doc
|
||||
{'foo': 'bar', 'baz': 'qux'}
|
||||
"""
|
||||
|
||||
p = JsonPatch(patch)
|
||||
@@ -63,7 +66,20 @@ def apply_patch(doc, patch):
|
||||
|
||||
|
||||
class JsonPatch(object):
|
||||
""" A JSON Patch is a list of Patch Operations """
|
||||
""" A JSON Patch is a list of Patch Operations.
|
||||
|
||||
>>> patch = JsonPatch([
|
||||
... {'add': '/foo', 'value': 'bar'},
|
||||
... {'add': '/baz', 'value': [1, 2, 3]},
|
||||
... {'remove': '/baz/1'},
|
||||
... {'test': '/baz', 'value': [1, 3]},
|
||||
... {'replace': '/baz/0', 'value': 42},
|
||||
... {'remove': '/baz/1'},
|
||||
... ])
|
||||
>>> doc = {}
|
||||
>>> patch.apply(doc)
|
||||
{'foo': 'bar', 'baz': [42]}
|
||||
"""
|
||||
|
||||
def __init__(self, patch):
|
||||
self.patch = patch
|
||||
@@ -105,7 +121,7 @@ class JsonPatch(object):
|
||||
|
||||
|
||||
class PatchOperation(object):
|
||||
""" A single operation inside a JSON Patch """
|
||||
""" A single operation inside a JSON Patch. """
|
||||
|
||||
def __init__(self, location, operation):
|
||||
self.location = location
|
||||
@@ -153,18 +169,7 @@ class PatchOperation(object):
|
||||
|
||||
|
||||
class RemoveOperation(PatchOperation):
|
||||
""" Removes an object property or an array element
|
||||
|
||||
>>> obj = { 'baz': 'qux', 'foo': 'bar' }
|
||||
>>> patch = JsonPatch( [ { 'remove': '/baz' } ] )
|
||||
>>> patch.apply(obj)
|
||||
{'foo': 'bar'}
|
||||
|
||||
>>> obj = { 'foo': [ 'bar', 'qux', 'baz' ] }
|
||||
>>> patch = JsonPatch( [ { "remove": "/foo/1" } ] )
|
||||
>>> patch.apply(obj)
|
||||
{'foo': ['bar', 'baz']}
|
||||
"""
|
||||
""" Removes an object property or an array element. """
|
||||
|
||||
def apply(self, obj):
|
||||
subobj, part = self.locate(obj, self.location)
|
||||
@@ -172,18 +177,7 @@ class RemoveOperation(PatchOperation):
|
||||
|
||||
|
||||
class AddOperation(PatchOperation):
|
||||
""" Adds an object property or an array element
|
||||
|
||||
>>> obj = { "foo": "bar" }
|
||||
>>> patch = JsonPatch([ { "add": "/baz", "value": "qux" } ])
|
||||
>>> patch.apply(obj)
|
||||
{'foo': 'bar', 'baz': 'qux'}
|
||||
|
||||
>>> obj = { "foo": [ "bar", "baz" ] }
|
||||
>>> patch = JsonPatch([ { "add": "/foo/1", "value": "qux" } ])
|
||||
>>> patch.apply(obj)
|
||||
{'foo': ['bar', 'qux', 'baz']}
|
||||
"""
|
||||
""" Adds an object property or an array element. """
|
||||
|
||||
def apply(self, obj):
|
||||
value = self.operation["value"]
|
||||
@@ -206,13 +200,7 @@ class AddOperation(PatchOperation):
|
||||
|
||||
|
||||
class ReplaceOperation(PatchOperation):
|
||||
""" Replaces a value
|
||||
|
||||
>>> obj = { "baz": "qux", "foo": "bar" }
|
||||
>>> patch = JsonPatch([ { "replace": "/baz", "value": "boo" } ])
|
||||
>>> patch.apply(obj)
|
||||
{'foo': 'bar', 'baz': 'boo'}
|
||||
"""
|
||||
""" Replaces an object property or an array element by new value. """
|
||||
|
||||
def apply(self, obj):
|
||||
value = self.operation["value"]
|
||||
@@ -233,18 +221,7 @@ class ReplaceOperation(PatchOperation):
|
||||
|
||||
|
||||
class MoveOperation(PatchOperation):
|
||||
""" Moves a value
|
||||
|
||||
>>> obj = {'foo': {'bar': 'baz', 'waldo': 'fred'}, 'qux': {'corge': 'grault'}}
|
||||
>>> patch = JsonPatch([{'move': '/foo/waldo', 'to': '/qux/thud'}])
|
||||
>>> patch.apply(obj)
|
||||
{'qux': {'thud': 'fred', 'corge': 'grault'}, 'foo': {'bar': 'baz'}}
|
||||
|
||||
>>> obj = {'foo': ['all', 'grass', 'cows', 'eat']}
|
||||
>>> patch = JsonPatch([{'move': '/foo/1', 'to': '/foo/3'}])
|
||||
>>> patch.apply(obj)
|
||||
{'foo': ['all', 'cows', 'eat', 'grass']}
|
||||
"""
|
||||
""" Moves an object property or an array element to new location. """
|
||||
|
||||
def apply(self, obj):
|
||||
subobj, part = self.locate(obj, self.location)
|
||||
@@ -254,26 +231,7 @@ class MoveOperation(PatchOperation):
|
||||
|
||||
|
||||
class TestOperation(PatchOperation):
|
||||
""" Test value by specified location
|
||||
|
||||
>>> obj = {'baz': 'qux', 'foo': ['a', 2, 'c']}
|
||||
>>> patch = JsonPatch([
|
||||
... {'test': '/baz', 'value': 'qux'},
|
||||
... {'test': '/foo/1', 'value': 2}
|
||||
... ])
|
||||
>>> patch.apply(obj)
|
||||
{'foo': ['a', 2, 'c'], 'baz': 'qux'}
|
||||
|
||||
>>> patch = JsonPatch([
|
||||
... {'test': '/foo/1', 'value': 'BOOM!'}
|
||||
... ])
|
||||
>>> try:
|
||||
... patch.apply(obj)
|
||||
... except AssertionError:
|
||||
... pass
|
||||
... else:
|
||||
... assert False, 'test should fall'
|
||||
"""
|
||||
""" Test value by specified location. """
|
||||
|
||||
def apply(self, obj):
|
||||
value = self.operation['value']
|
||||
|
||||
87
tests.py
87
tests.py
@@ -1,44 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import print_function
|
||||
import doctest
|
||||
import unittest
|
||||
import sys
|
||||
import jsonpatch
|
||||
|
||||
modules = ['jsonpatch']
|
||||
coverage_modules = []
|
||||
|
||||
suite = unittest.TestSuite()
|
||||
class ApplyPatchTestCase(unittest.TestCase):
|
||||
|
||||
for module in modules:
|
||||
m = __import__(module, fromlist=[module])
|
||||
coverage_modules.append(m)
|
||||
suite.addTest(doctest.DocTestSuite(m))
|
||||
def test_add_object_key(self):
|
||||
obj = {'foo': 'bar'}
|
||||
jsonpatch.apply_patch(obj, [{'add': '/baz', 'value': 'qux'}])
|
||||
self.assertTrue('baz' in obj)
|
||||
self.assertEqual(obj['baz'], 'qux')
|
||||
|
||||
runner = unittest.TextTestRunner(verbosity=2)
|
||||
def test_add_array_item(self):
|
||||
obj = {'foo': ['bar', 'baz']}
|
||||
jsonpatch.apply_patch(obj, [{'add': '/foo/1', 'value': 'qux'}])
|
||||
self.assertEqual(obj['foo'], ['bar', 'qux', 'baz'])
|
||||
|
||||
try:
|
||||
import coverage
|
||||
except ImportError:
|
||||
coverage = None
|
||||
def test_remove_object_key(self):
|
||||
obj = {'foo': 'bar', 'baz': 'qux'}
|
||||
jsonpatch.apply_patch(obj, [{'remove': '/baz'}])
|
||||
self.assertTrue('baz' not in obj)
|
||||
|
||||
if coverage is not None:
|
||||
coverage.erase()
|
||||
coverage.start()
|
||||
def test_remove_array_item(self):
|
||||
obj = {'foo': ['bar', 'qux', 'baz']}
|
||||
jsonpatch.apply_patch(obj, [{'remove': '/foo/1'}])
|
||||
self.assertEqual(obj['foo'], ['bar', 'baz'])
|
||||
|
||||
result = runner.run(suite)
|
||||
def test_replace_object_key(self):
|
||||
obj = {'foo': 'bar', 'baz': 'qux'}
|
||||
jsonpatch.apply_patch(obj, [{'replace': '/baz', 'value': 'boo'}])
|
||||
self.assertTrue(obj['baz'], 'boo')
|
||||
|
||||
if not result.wasSuccessful():
|
||||
sys.exit(1)
|
||||
def test_replace_array_item(self):
|
||||
obj = {'foo': ['bar', 'qux', 'baz']}
|
||||
jsonpatch.apply_patch(obj, [{'replace': '/foo/1', 'value': 'boo'}])
|
||||
self.assertEqual(obj['foo'], ['bar', 'boo', 'baz'])
|
||||
|
||||
if coverage is not None:
|
||||
coverage.stop()
|
||||
coverage.report(coverage_modules)
|
||||
coverage.erase()
|
||||
def test_move_object_key(self):
|
||||
obj = {'foo': {'bar': 'baz', 'waldo': 'fred'},
|
||||
'qux': {'corge': 'grault'}}
|
||||
jsonpatch.apply_patch(obj, [{'move': '/foo/waldo', 'to': '/qux/thud'}])
|
||||
self.assertEqual(obj, {'qux': {'thud': 'fred', 'corge': 'grault'},
|
||||
'foo': {'bar': 'baz'}})
|
||||
|
||||
if coverage is None:
|
||||
print("""
|
||||
No coverage reporting done (Python module "coverage" is missing)
|
||||
Please install the python-coverage package to get coverage reporting.
|
||||
""", file=sys.stderr)
|
||||
def test_move_array_item(self):
|
||||
obj = {'foo': ['all', 'grass', 'cows', 'eat']}
|
||||
jsonpatch.apply_patch(obj, [{'move': '/foo/1', 'to': '/foo/3'}])
|
||||
self.assertEqual(obj, {'foo': ['all', 'cows', 'eat', 'grass']})
|
||||
|
||||
def test_test_success(self):
|
||||
obj = {'baz': 'qux', 'foo': ['a', 2, 'c']}
|
||||
jsonpatch.apply_patch(obj, [{'test': '/baz', 'value': 'qux'},
|
||||
{'test': '/foo/1', 'value': 2}])
|
||||
|
||||
def test_test_error(self):
|
||||
obj = {'bar': 'qux'}
|
||||
self.assertRaises(AssertionError,
|
||||
jsonpatch.apply_patch,
|
||||
obj, [{'test': '/bar', 'value': 'bar'}])
|
||||
|
||||
|
||||
def suite():
|
||||
suite = unittest.TestSuite()
|
||||
suite.addTest(doctest.DocTestSuite(jsonpatch))
|
||||
suite.addTest(unittest.makeSuite(ApplyPatchTestCase))
|
||||
return suite
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='suite')
|
||||
|
||||
Reference in New Issue
Block a user