test_error.py
Overview
The `test_error.py` file is a test suite designed to verify the behavior and error handling of JSON encoding and decoding operations, primarily when using the `orjson` library alongside Python's built-in `json` module. It focuses on confirming that errors are raised correctly, that error information is consistent between `json` and `orjson`, and that custom exceptions and edge cases in JSON serialization/deserialization are properly handled.
This file contains two main test classes:
TestJsonDecodeError: Tests related to JSON decoding errors, comparingjsonandorjsonerror outputs.TestJsonEncodeError: Tests related to JSON encoding errors, especially howorjsonraisesJSONEncodeErrorand chains exceptions from custom serialization functions.
Additional utility functions and classes are defined to facilitate testing of error propagation during encoding.
Classes and Functions
Class: TestJsonDecodeError
Tests the decoding (parsing) of JSON strings/bytes and ensures that decoding errors from `orjson` match those from Python’s standard `json` module.
Methods
_get_error_infos(json_decode_error_exc_info) -> dictExtracts error position information from a caught json.decoder.JSONDecodeError exception info object.
Parameters:
json_decode_error_exc_info: A pytest exception info object from aJSONDecodeError.
Returns:
Dictionary containing
pos,lineno, andcolnoof the error.
Usage Example:
err_info = self._get_error_infos(json_exc_info)
_test(data: str or bytes, expected_err_infos: dict)Helper method that attempts to load
dataas JSON using bothjson.loadsandorjson.loads, expecting both to raiseJSONDecodeErrorwith matching error position info.Parameters:
data: JSON string or bytes expected to fail parsing.expected_err_infos: Dictionary with expected error info keys:pos,lineno,colno.
Raises: AssertionError if error info does not match or exceptions are not raised.
Usage Example:
self._test('["unterminated string', {"pos": 17, "lineno": 1, "colno": 18})
test_empty()Tests that decoding an empty string with
orjson.loadsraises aJSONDecodeErrorwith a message indicating empty input.test_ascii()Tests decoding a malformed ASCII JSON string
ASCII_TESTand verifies error location.test_latin1()Tests decoding a malformed string containing Latin-1 characters.
test_two_byte_str()Tests decoding a malformed string containing two-byte UTF-8 characters (Japanese characters).
test_two_byte_bytes()Similar to
test_two_byte_str, but tests decoding bytes input with two-byte characters.test_four_byte()Tests decoding a malformed multi-line JSON string containing four-byte UTF-8 characters (emoji).
test_tab()Tests decoding a JSON fixture file
fail26.json(loaded viaread_fixture_str) containing a tab character error, ensuring correct error positions for bothjsonandorjson.
Class: Custom
A dummy empty class used in encoding tests to simulate serialization of unsupported types.
Class: CustomException
A custom exception class used for testing exception chaining in encoding errors.
Functions for encoding error chaining tests
These functions simulate `default` callable handlers passed to `orjson.dumps` to test how exceptions propagate and chain.
default_typeerror(obj)Raises
TypeError.default_notimplementederror(obj)Raises
NotImplementedError.default_systemerror(obj)Raises
SystemError.default_importerror(obj)Attempts to import a non-existent module, raising
ImportError.default_customerror(obj)Raises
CustomExceptionwith messageCUSTOM_ERROR_MESSAGE.
Class: TestJsonEncodeError
Tests the behavior of `orjson.dumps` when encoding invalid input or when the `default` serialization handler raises exceptions.
Methods
test_dumps_arg()Tests that calling
orjson.dumps()with no arguments raisesorjson.JSONEncodeErrorwith a message about missing the required positional argument.test_dumps_chain_none()Tests encoding a
Custominstance without adefaulthandler, expecting aJSONEncodeErrorwith a message about the type not being serializable.test_dumps_chain_u64()Tests encoding a list containing a large unsigned 64-bit integer and a
Custominstance, verifying no exception cause chaining.test_dumps_chain_default_typeerror()Tests encoding with a
defaulthandler that raisesTypeError, verifies that theTypeErroris chained as the cause in theJSONEncodeError.test_dumps_chain_default_systemerror()Tests encoding with a
defaulthandler that raisesSystemError, verifying exception chaining.test_dumps_chain_default_importerror()Tests encoding with a
defaulthandler that raisesImportError, verifying chaining.test_dumps_chain_default_customerror()Tests encoding with a
defaulthandler that raises a customCustomException, verifying the exception is chained and the message matchesCUSTOM_ERROR_MESSAGE.test_dumps_normalize_exception()Tests encoding a very large integer (
10**60), expecting aJSONEncodeError.
Important Implementation Details and Algorithms
Error Information Extraction:
The_get_error_infosmethod extracts the positional error details (pos,lineno,colno) fromJSONDecodeErrorexceptions to compare errors raised byjsonandorjson. This ensures consistent error reporting across different libraries.Exception Chaining:
The encoding error tests verify that when a user-defineddefaultfunction raises an exception during serialization,orjson.dumpsraises aJSONEncodeErrorthat chains the original exception as its cause (__cause__). This preserves the original exception context, which is useful for debugging.Use of Pytest Exception Info:
Tests usepytest.raisescontext managers to capture exceptions and inspect their types, messages, and causes.Testing with Various Unicode Encodings:
The decoding tests include JSON strings with ASCII, Latin-1, multi-byte UTF-8 characters, and emojis to test error handling robustness with different character sets.Fixtures and Conditional Test Execution:
The@needs_datadecorator is used to conditionally run tests that rely on external data fixtures (fail26.json).
Interaction with Other Parts of the System
Dependency on
orjson:
This file tests error scenarios using theorjsonJSON library, which is a performant alternative to Python’s built-injsonmodule.Use of Local Utilities:
The file importsneeds_dataandread_fixture_strfrom a local.utilmodule, which presumably provide test fixture loading and conditional test execution capabilities.Testing Integration:
The file is designed to be run as part of a test suite, likely withpytest. It verifies thatorjsonbehaves compatibly with or similarly to Python’s built-injsonin error scenarios.Custom Exception Classes:
TheCustomandCustomExceptionclasses are defined here solely for testing serialization failure and exception chaining scenarios.
Usage Examples
Example: Testing JSON decoding error positions
test = TestJsonDecodeError()
test._test('["unterminated string', {"pos": 17, "lineno": 1, "colno": 18})
This will verify that both `json.loads` and `orjson.loads` raise a `JSONDecodeError` at the same position.
Example: Testing encoding error chains
test = TestJsonEncodeError()
try:
orjson.dumps(Custom(), default=default_typeerror)
except orjson.JSONEncodeError as e:
print(f"Chained exception: {e.__cause__}") # Outputs: TypeError
Diagram: Class Structure of test_error.py
classDiagram
class TestJsonDecodeError {
+_get_error_infos(json_decode_error_exc_info) dict
+_test(data, expected_err_infos)
+test_empty()
+test_ascii()
+test_latin1()
+test_two_byte_str()
+test_two_byte_bytes()
+test_four_byte()
+test_tab()
}
class TestJsonEncodeError {
+test_dumps_arg()
+test_dumps_chain_none()
+test_dumps_chain_u64()
+test_dumps_chain_default_typeerror()
+test_dumps_chain_default_systemerror()
+test_dumps_chain_default_importerror()
+test_dumps_chain_default_customerror()
+test_dumps_normalize_exception()
}
class Custom
class CustomException
TestJsonEncodeError ..> Custom : uses
TestJsonEncodeError ..> CustomException : uses
TestJsonEncodeError ..> default_typeerror : uses
TestJsonEncodeError ..> default_systemerror : uses
TestJsonEncodeError ..> default_importerror : uses
TestJsonEncodeError ..> default_customerror : uses
Summary
The `test_error.py` file is a comprehensive test module validating JSON encoding and decoding error handling, focusing on consistency and correct exception chaining when using the `orjson` library. It includes tests for various malformed inputs, unicode edge cases, and propagating exceptions from custom serializers. The tests ensure robust error reporting and compatibility between `orjson` and Python’s standard `json` module, contributing to the reliability of JSON operations within the broader application or library ecosystem.