Skip to content

Add property-based tests using Hypothesis - #194

Merged
stefankoegl merged 3 commits into
masterfrom
claude/dazzling-bardeen-cprykw
Oct 8, 2026
Merged

stefankoegl merged 3 commits into
masterfrom
claude/dazzling-bardeen-cprykw

Conversation

@stefankoegl

Copy link
Copy Markdown
Owner

This PR adds comprehensive property-based testing to jsonpatch using the Hypothesis framework, complementing the existing example-based tests.

Summary

A new test suite (property_tests.py) has been added that uses Hypothesis to generate many test cases and verify general properties of the jsonpatch implementation. This helps uncover edge cases and ensures the library behaves correctly across a wide range of inputs.

Key Changes

  • New property_tests.py module: Contains 600+ lines of property-based tests organized into several test classes:

    • MakePatchProperties: Tests for the make_patch() function, including roundtrip verification
    • ApplyPatchProperties: Tests for patch application, document/patch immutability, and exception handling
    • OperationProperties: Tests for individual RFC 6902 operations (add, remove, replace, move, copy, test)
    • JsonPatchProperties: Tests for JsonPatch class behavior
    • PatchOperationMachine: A stateful test machine that applies valid operations sequentially and verifies results
  • Test utilities: Helper functions for JSON comparison (json_equal), pointer manipulation (to_pointer), document traversal (locations, containers), and outcome tracking

  • Strategy definitions: Hypothesis strategies for generating:

    • JSON scalars and documents with various edge cases
    • JSON pointers (both valid and invalid)
    • Well-formed patch operations
    • Safe documents that avoid known issues
  • Known issues documented: Tests marked with @unittest.expectedFailure document 8 known issues in the implementation with minimal counterexamples, allowing them to be tracked and fixed incrementally

  • Updated build configuration:

    • Added hypothesis to CI dependencies and dev requirements
    • Integrated property tests into the makefile test target
    • Added .hypothesis to .gitignore

Notable Implementation Details

  • Tests use json_equal() for RFC 6902-compliant equality (e.g., treating 1 and True as different)
  • Separate "safe" document strategies avoid inputs that trigger known failures
  • Stateful testing with PatchOperationMachine verifies that sequential operations produce consistent results
  • Configurable Hypothesis profiles (standard/thorough) for different test depths
  • Each expected failure includes explicit @example decorators with minimal counterexamples for deterministic testing

https://claude.ai/code/session_01JqGXptMsaz9bfrMoaMpZ1A

claude added 3 commits October 8, 2026 11:56
property_tests.py checks general properties of jsonpatch against generated
documents and patches:

- make_patch: diffing equal documents gives an empty patch, applying
  make_patch(src, dst) to src gives dst, inputs are not modified, the
  result shares no objects with dst
- apply_patch: the document and the patch are not modified, only
  JsonPatchException / JsonPointerException are raised (also for
  malformed patches), in_place and string patches give the same result
- single operations: whole-document targets and sources, moving into
  own children, replace of any existing location, 'test' using JSON
  equality
- JsonPatch: string roundtrip, equal patches have equal hashes
- a state machine applying random valid operations and comparing each
  result with a direct implementation of RFC 6902

Properties that do not hold yet are expected failures, each pinned to the
minimal counterexample Hypothesis found. Among them are known issues
(#124, #137, #138, #179, #180, #190) and some that appear to be
unreported: make_patch mishandling object keys that int() accepts,
replace rejecting the object member '-', hash() failing for patches with
array/object values, 'test' treating 1 and true as equal, copy from the
whole document failing, and moves into own children being allowed for
array members.

The tests run in CI and via "make test".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqGXptMsaz9bfrMoaMpZ1A
The whole-document fixes from #191 and #192 make some pinned
counterexamples pass:

- test_copy_whole_document now passes; drop its expected-failure marker
- test_whole_document_as_target still fails, but only for scalar
  documents, where 'add' raises TypeError while 'replace' works
- test_raises_only_documented_exceptions still fails, now pinned to
  'move' from the whole document, 'copy'/'move' from the '-' of an
  array, and operations on a scalar whole document

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JqGXptMsaz9bfrMoaMpZ1A
@stefankoegl
stefankoegl merged commit d70a4d6 into master Oct 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants