-
Notifications
You must be signed in to change notification settings - Fork 95
Property-based tests with Hypothesis #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
JSON doesn't actually allow these (despite the json module in Python happily serializing / parsing 'nan'), and they make assertEqual fail since they're not equal to anything, including themselves.
…json-patch into mithrandi-property-tests
1f4dc2a
to
1d89ec3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds property-based testing using the Hypothesis framework to enhance test coverage for the jsonpatch library. The changes introduce comprehensive roundtrip testing that validates JSON patch generation and application across a wide range of automatically generated test cases.
- Adds Hypothesis as an optional development dependency for property-based testing
- Introduces roundtrip tests that verify patch generation and application work correctly together
- Refactors the DiffBuilder class to simplify its implementation and fix index tracking for list operations
Reviewed Changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.
File | Description |
---|---|
tests.py | Adds Hypothesis import handling, JSON strategy definition, and RoundtripTests class with property-based testing |
requirements-dev.txt | Adds Hypothesis dependency with Python version constraints |
jsonpatch.py | Major refactor of DiffBuilder class to simplify logic and improve index change tracking |
.travis.yml | Moves development dependency installation to main install phase for CI |
add_index_change('/', 1, +1) | ||
""" | ||
|
||
path_changes = self.index_changes.get(path, {}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The path_changes dictionary is retrieved but never stored back to self.index_changes. This means the key_change calculation on line 778 has no effect. You need to store path_changes back: self.index_changes[path] = path_changes
Copilot uses AI. Check for mistakes.
st.text(string.printable)]), | ||
lambda children: | ||
st.lists(children) | ||
| st.dictionaries(st.text(string.printable), children)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using string.printable for JSON text generation can produce invalid JSON strings containing control characters like newlines and tabs that need escaping. Consider using st.text() without the alphabet parameter or st.text(alphabet=string.printable.replace('\n', '').replace('\t', '').replace('\r', ''))
st.text(string.printable)]), | |
lambda children: | |
st.lists(children) | |
| st.dictionaries(st.text(string.printable), children)) | |
st.text(alphabet=string.printable.replace('\n', '').replace('\t', '').replace('\r', ''))]), | |
lambda children: | |
st.lists(children) | |
| st.dictionaries(st.text(alphabet=string.printable.replace('\n', '').replace('\t', '').replace('\r', '')), children)) |
Copilot uses AI. Check for mistakes.
storage[value] = [index] | ||
else: | ||
storage[value].append(index) | ||
self.ops = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The index_changes attribute lacks documentation. Add a docstring or comment explaining its purpose: tracking cumulative index changes for list operations to maintain correct indices during patch generation.
self.ops = [] | |
self.ops = [] | |
# Tracks cumulative index changes for list operations to maintain correct indices during patch generation. |
Copilot uses AI. Check for mistakes.
self.add_index_change(path, key+1, -1) | ||
self.add_index_change(path, newkey+1, +1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When an item is moved, adjusting indices at key+1 position for the source doesn't account for the fact that the item is being moved, not just removed. This could lead to incorrect index calculations for subsequent operations.
self.add_index_change(path, key+1, -1) | |
self.add_index_change(path, newkey+1, +1) | |
# Correctly adjust indices for items between key and newkey | |
if key < newkey: | |
# Moving forward: shift items between key+1 and newkey left by 1 | |
for idx in range(key + 1, newkey + 1): | |
self.add_index_change(path, idx, -1) | |
elif key > newkey: | |
# Moving backward: shift items between newkey and key-1 right by 1 | |
for idx in range(newkey, key): | |
self.add_index_change(path, idx, +1) |
Copilot uses AI. Check for mistakes.
Continues the work from #63