Rework tests.

This commit is contained in:
Alexander Shorin
2011-12-25 19:41:46 +04:00
parent 6dd658934a
commit 477a1996a5
2 changed files with 86 additions and 99 deletions

View File

@@ -51,11 +51,14 @@ class JsonPatchConflict(JsonPatchException):
def apply_patch(doc, patch): def apply_patch(doc, patch):
""" """ Apply list of patches to specified json document.
>>> obj = { 'baz': 'qux', 'foo': 'bar' }
>>> patch = [ { 'remove': '/baz' } ] >>> doc = {'foo': 'bar'}
>>> apply_patch(obj, patch) >>> other = apply_patch(doc, [{'add': '/baz', 'value': 'qux'}])
{'foo': 'bar'} >>> doc is other
True
>>> doc
{'foo': 'bar', 'baz': 'qux'}
""" """
p = JsonPatch(patch) p = JsonPatch(patch)
@@ -63,7 +66,20 @@ def apply_patch(doc, patch):
class JsonPatch(object): 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): def __init__(self, patch):
self.patch = patch self.patch = patch
@@ -105,7 +121,7 @@ class JsonPatch(object):
class PatchOperation(object): class PatchOperation(object):
""" A single operation inside a JSON Patch """ """ A single operation inside a JSON Patch. """
def __init__(self, location, operation): def __init__(self, location, operation):
self.location = location self.location = location
@@ -153,18 +169,7 @@ class PatchOperation(object):
class RemoveOperation(PatchOperation): class RemoveOperation(PatchOperation):
""" Removes an object property or an array element """ 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']}
"""
def apply(self, obj): def apply(self, obj):
subobj, part = self.locate(obj, self.location) subobj, part = self.locate(obj, self.location)
@@ -172,18 +177,7 @@ class RemoveOperation(PatchOperation):
class AddOperation(PatchOperation): class AddOperation(PatchOperation):
""" Adds an object property or an array element """ 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']}
"""
def apply(self, obj): def apply(self, obj):
value = self.operation["value"] value = self.operation["value"]
@@ -206,13 +200,7 @@ class AddOperation(PatchOperation):
class ReplaceOperation(PatchOperation): class ReplaceOperation(PatchOperation):
""" Replaces a value """ Replaces an object property or an array element by new value. """
>>> obj = { "baz": "qux", "foo": "bar" }
>>> patch = JsonPatch([ { "replace": "/baz", "value": "boo" } ])
>>> patch.apply(obj)
{'foo': 'bar', 'baz': 'boo'}
"""
def apply(self, obj): def apply(self, obj):
value = self.operation["value"] value = self.operation["value"]
@@ -233,18 +221,7 @@ class ReplaceOperation(PatchOperation):
class MoveOperation(PatchOperation): class MoveOperation(PatchOperation):
""" Moves a value """ Moves an object property or an array element to new location. """
>>> 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']}
"""
def apply(self, obj): def apply(self, obj):
subobj, part = self.locate(obj, self.location) subobj, part = self.locate(obj, self.location)
@@ -254,26 +231,7 @@ class MoveOperation(PatchOperation):
class TestOperation(PatchOperation): class TestOperation(PatchOperation):
""" Test value by specified location """ 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'
"""
def apply(self, obj): def apply(self, obj):
value = self.operation['value'] value = self.operation['value']

View File

@@ -1,44 +1,73 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function
import doctest import doctest
import unittest import unittest
import sys import jsonpatch
modules = ['jsonpatch']
coverage_modules = []
suite = unittest.TestSuite() class ApplyPatchTestCase(unittest.TestCase):
for module in modules: def test_add_object_key(self):
m = __import__(module, fromlist=[module]) obj = {'foo': 'bar'}
coverage_modules.append(m) jsonpatch.apply_patch(obj, [{'add': '/baz', 'value': 'qux'}])
suite.addTest(doctest.DocTestSuite(m)) 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: def test_remove_object_key(self):
import coverage obj = {'foo': 'bar', 'baz': 'qux'}
except ImportError: jsonpatch.apply_patch(obj, [{'remove': '/baz'}])
coverage = None self.assertTrue('baz' not in obj)
if coverage is not None: def test_remove_array_item(self):
coverage.erase() obj = {'foo': ['bar', 'qux', 'baz']}
coverage.start() 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(): def test_replace_array_item(self):
sys.exit(1) 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: def test_move_object_key(self):
coverage.stop() obj = {'foo': {'bar': 'baz', 'waldo': 'fred'},
coverage.report(coverage_modules) 'qux': {'corge': 'grault'}}
coverage.erase() 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: def test_move_array_item(self):
print(""" obj = {'foo': ['all', 'grass', 'cows', 'eat']}
No coverage reporting done (Python module "coverage" is missing) jsonpatch.apply_patch(obj, [{'move': '/foo/1', 'to': '/foo/3'}])
Please install the python-coverage package to get coverage reporting. self.assertEqual(obj, {'foo': ['all', 'cows', 'eat', 'grass']})
""", file=sys.stderr)
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')