1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
"""Test Python JSONPath against the json-path-comparison project's regression suite.
Assumes a version of the regression suite is available in the current working
directory as "comparison_regression_suite.yaml".
See https://github.com/cburgmer/json-path-comparison.
We've deliberately named this file so as to exclude it when running `pytest` or
`hatch run test`. Target it specifically using `pytest tests/consensus.py`.
"""
import operator
import unittest
from dataclasses import dataclass
from typing import Any
from typing import Dict
from typing import List
from typing import Mapping
from typing import Optional
from typing import Sequence
from typing import Union
import pytest
from yaml import safe_load
import jsonpath
@dataclass
class Query:
id: str # noqa: A003
selector: str
document: Union[Mapping[str, Any], Sequence[Any]]
consensus: Any = None
not_found_consensus: Any = None
scalar_not_found_consensus: Any = None
scalar_consensus: Any = None
ordered: Optional[bool] = None
RENAME_MAP = {
"not-found-consensus": "not_found_consensus",
"scalar-not-found-consensus": "scalar_not_found_consensus",
"scalar-consensus": "scalar_consensus",
}
SKIP = {
# "bracket_notation_with_number_on_object": "We support unquoted property names",
"dot_notation_with_number_-1": "conflict with compliance",
"dot_notation_with_number_on_object": "conflict with compliance",
}
def clean_query(query: Dict[str, Any]) -> Dict[str, Any]:
# Replace hyphens with underscores in dict names.
for old, new in RENAME_MAP.items():
if old in query:
query[new] = query[old]
del query[old]
return query
def queries() -> List[Query]:
with open("comparison_regression_suite.yaml", encoding="utf8") as fd:
data = safe_load(fd)
return [Query(**clean_query(q)) for q in data["queries"]]
QUERIES_WITH_CONSENSUS = [
q for q in queries() if q.consensus is not None and q.consensus != "NOT_SUPPORTED"
]
@pytest.mark.parametrize("query", QUERIES_WITH_CONSENSUS, ids=operator.attrgetter("id"))
def test_consensus(query: Query) -> None:
if query.id in SKIP:
pytest.skip(reason=SKIP[query.id])
case = unittest.TestCase()
rv = jsonpath.findall(query.selector, query.document)
case.assertCountEqual(rv, query.consensus) # noqa: PT009
|